2016-07-20 12 views
3

Ich habe eine Tabelle, die auf folgende Weise funktioniert. Wenn eine Zeile ausgewählt ist, wird ein der ausgewählten Zeile entsprechender Wert zu var total hinzugefügt, ein Häkchen wird hinzugefügt. Wenn es deaktiviert ist, wird der Betrag abgezogen, das Häkchen wird auf "Keine" gesetzt. Mein Code funktionierte ordnungsgemäß, bevor versucht wurde, die Daten zu/von NSUserDefaults zu speichern/abzurufen. Die Fehler sind: Wenn ich die erste Zeile auswähle, subtrahiert sie den Betrag, anstatt ihn hinzuzufügen; Nachdem eine Zeile ausgewählt wurde, wenn ich auf die Zurück-Schaltfläche klicke und dann zum selben Bildschirm zurückkehre, wird das Häkchen nicht angezeigt. In diesem Konstrukt, wenn ich versuche, von NSUserDefaults abrufen indexPathForCellSelected wertet auf Null, obwohl ich if indexPathForCellSelected != nil überprüfen, bevor die Zuordnung zu machen. fataler Fehler: unerwartet null gefunden, während ein optionaler WertFehler beim Speichern in NSUserdefaults

if indexPathForCellSelected != nil { self.tableView.cellForRowAtIndexPath(indexPathForCellSelected!)?. 
accessoryType = .Checkmark 
} 



class NinethViewController: UIViewController, UITableViewDelegate,UITableViewDataSource { 

var total = 0 
var indexRowRetrieved:Int? 
var rowSelected:Int? 
var indexRowSelectedKey = "indexRowKey" 
var amountKey = "amountKey" 
var totalKey = "totalKey" 
let indexPathKey = "indexPathForCellSelected" 
var indexPathForCellSelected: NSIndexPath? 


struct Item { 
    var name:String // name of the row 
    var selected:Bool // whether is selected or not 
    var amount: Int // value of the item 
} 

var extras = [ 

    Item(name:"Inside Cabinets",selected: false, amount: 5), 
    Item(name:"Inside Fridge",selected: false, amount: 5), 
    Item(name:"Inside Oven",selected: false, amount: 5), 
    Item(name:"Laundry wash & dry",selected: false, amount: 10), 
    Item(name:"Interior Windows", selected: false, amount: 5) 
] 


@IBOutlet weak var tableView: UITableView! 

override func viewDidLoad() { 
    super.viewDidLoad() 
} 

override func viewDidAppear(animated: Bool) { 
    super.viewDidAppear(animated) 

    // loadData from NSUserDefaults 
    loadData() 
} 

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
    return extras.count 
} 

func numberOfSectionsInTableView(tableView: UITableView) -> Int { 
    return 1 
} 

// configure the cell 
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) 
    -> UITableViewCell  { 
     let cell = tableView.dequeueReusableCellWithIdentifier("Cell") 
     cell?.textLabel?.text = extras[indexPath.row].name 
     return cell! 
} 

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 

    // if the cell has not been selected before 
    if !extras[indexPath.row].selected { 

     // marks the cell as selected 
     extras[indexPath.row].selected = true 
     tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .Checkmark 

     self.total += extras[indexPath.row].amount 
     indexPathForCellSelected = indexPath 
     rowSelected = indexPath.row 
     print(total) 

     // save all info in NSUserDefaults 
       saveData() 

    } else { 
     // marks the cell as not selected 
     extras[indexPath.row].selected = false 
     tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .None 

     self.total -= extras[indexPath.row].amount 
     print(total) 



    } 
} 


func saveData(){ 

    // save indexPathForCellSelected in NSUserDefaults 
    if indexPathForCellSelected != nil { 
     let data = NSKeyedArchiver.archivedDataWithRootObject(indexPathForCellSelected!) 
        NSUserDefaults.standardUserDefaults().setObject(data, forKey: indexPathKey) 

     // save indexRowSelected 
     NSUserDefaults.standardUserDefaults().setInteger(rowSelected!, forKey: indexRowSelectedKey) 

     // save amount for corresponding row in NSUserDefaults 
     NSUserDefaults.standardUserDefaults().setObject(extras[rowSelected!].amount, forKey: amountKey) 

     //save total in NSUserDefaults 
     NSUserDefaults.standardUserDefaults().setObject(total, forKey: totalKey) 

    } 

} 



func loadData() { 
    //retrieve indexPathForCellSelected from NSUserDefaults 
    if let retrievedIndexPath = NSUserDefaults.standardUserDefaults().dataForKey(indexPathKey) { 
     if let data1 = NSKeyedUnarchiver.unarchiveObjectWithData(retrievedIndexPath) as? NSIndexPath{ 
      indexPathForCellSelected = data1 
     } 
    } 


    // retrieve the index for row selected to select the state of the row: true or false 
    if let retrievedIndexRow = NSUserDefaults.standardUserDefaults().integerForKey(indexRowSelectedKey) as? Int  { 
      indexRowRetrieved = retrievedIndexRow 
       extras[retrievedIndexRow].selected = true 
    } 

    // retrieve amount for corresponding row in NSUserDefaults 
    if let itemAmount = NSUserDefaults.standardUserDefaults().objectForKey(amountKey) as? Int { 
     extras[indexRowRetrieved!].amount = itemAmount 

     // assign checkmark to row selected 
      if indexPathForCellSelected != nil { 
       self.tableView.cellForRowAtIndexPath(indexPathForCellSelected!)?.accessoryType = .Checkmark 
     } 
    } 
    // retrieve total from NSUserDefaults 
     if let totalRetrieved = NSUserDefaults.standardUserDefaults().objectForKey(totalKey) as? Int { 
      total = totalRetrieved 
       print(total) 
     } 
    } 
} 
+0

Siehe meine Antwort, Entschuldigung für die Verzögerung. Ich war beschäftigt –

Antwort

1

Ich weiß nicht, warum Sie alle NSIndexPath ‚s für die Zellen zuvor ausgewählten sparen, wenn Sie Ihre vorherige Frage und dieses nach, können Sie nur den Index der Zelle ausgewählt speichern müssen und den Wert die Summe, die Sie hatten, wenn Sie zu einem anderen Controller gehen. Sie können es auf folgende Weise tun:

var frequency = [ 
    Item(name:"Every week",selected: false, amount: 30), 
    Item(name:"Every 2 weeks",selected: false, amount: 30), 
    Item(name:"Every 4 weeks",selected: false, amount: 30), 
    Item(name:"Once",selected: false, amount: 40), 
    Item(name:"End of tenancy cleaning", selected: false, amount: 44) 
] 

var indexPathForCellSelected: NSIndexPath? 
var total = 0 

let indexPathKey = "indexPathForCellSelectedNinethViewControllerKey" 
let totalKey = "totalNinethViewControllerKey" 

override func viewDidLoad() { 
    super.viewDidLoad() 

    loadData() 
} 

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { 

    let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) 
    cell.textLabel?.text = frequency[indexPath.row].name 
    if let _ = indexPathForCellSelected where indexPath == indexPathForCellSelected { 
     cell.accessoryType = .Checkmark 
    } 
    return cell 
} 

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 

    if !frequency[indexPath.row].selected { 

     // this avoid set initial value for the first time 
     if let index = indexPathForCellSelected { 
      // clear the previous cell 
      frequency[index.row].selected = false 
      tableView.cellForRowAtIndexPath(index)?.accessoryType = .None 
      self.total -= frequency[index.row].amount 
     } 

     // mark the new one 
     frequency[indexPath.row].selected = true 
     tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .Checkmark 

     indexPathForCellSelected = indexPath 
     self.total += frequency[indexPath.row].amount 

     saveData() 
    } 
} 

private func saveData() { 

    // save the index for the cell selected in NSUserDefaults 
    NSUserDefaults.standardUserDefaults().setInteger(indexPathForCellSelected!.row, forKey: indexPathKey) 

    // save total in NSUserDefaults 
    NSUserDefaults.standardUserDefaults().setInteger(total, forKey: totalKey) 
} 

private func loadData() { 

    // get the values from NSUserDefaults if exist 
    if let indexValue = NSUserDefaults.standardUserDefaults().valueForKey(indexPathKey), totalValue = NSUserDefaults.standardUserDefaults().valueForKey(totalKey) { 
     indexPathForCellSelected = NSIndexPath(forRow: indexValue as! Int, inSection: 0) 
     total = totalValue as! Int 
    } 
} 

Ich hoffe, das hilft Ihnen.

+0

Ich denke nicht über NSIndexPath Beispiel der Konstruktion des Indexwert verwendet wird. Danke für Ihre Hilfe. – bibscy

-3

Try Abwickeln die NSUserDefaults nach Einstellung der Daten zu synchronisieren.

let defaults = NSUserDefaults.standardUserDefaults() 

defaults.setObject("1", forKey: "SomeKey") 
defaults.synchronize() // Sync the defaults to update the data 
+1

Der Zweck von defaults.synchronize() ist es, die Benutzerstandardwerte sofort auf die Festplatte geschrieben zu bekommen. iOS macht es nur in geeigneten Momenten. – felipenbrito

+1

synchronize() ist veraltet. Dies ist nicht der Grund, warum mein Code nicht funktioniert. – bibscy

1

Versuchen Sie einen Ausdruck setzen Sie das Häkchen in der tableView(_:didSelectRowAtIndexPath:) Funktion hinzuzufügen, in dem Sie auch in der Lage sein sollte, das Addieren und Subtrahieren, basierend auf seinen Zustand zu implementieren. So könnten Sie so etwas tun:

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 
     if let cell = tableView.cellForRowAtIndexPath(indexPath) { 
      if cell.accessoryType == .None { 
       cell.accessoryType = .Checkmark 
       total += extras[indexPath.row].amount 
      } else if cell.accessoryType == .Checkmark { 
       cell.accessoryType = .None 
       total -= extras[indexPath.row].amount 
      } 
      // Call function to save here 
     } 
    } 
+0

Die Funktionalität zum Hinzufügen von Subtraktion ist bereits implementiert und funktioniert wie erwartet. Die oben angegebenen Fehler werden angezeigt, wenn ich Daten mit NSUserDefaults hinzufüge/abrufe. Können Sie meiner aktuellen NSUserDefaults-Implementierung etwas hinzufügen oder sagen, was falsch ist? – bibscy

+0

Wenn Sie die Daten festgelegt, versuchen Sie es von 'NSKeyedArchiver Ändern ...' auf 'NSUserDefaults.standardUserDefaults(). ObjectForKey (indexPathForCellSelected)' und sehen, ob das funktioniert. Setzen Sie auch einen Haltepunkt in Ihrer if-Anweisung, und gehen Sie dann zum nächsten Schritt über, um sicherzustellen, dass er eingegeben wird. –

+0

Es funktioniert nicht. Können Sie versuchen, meinen Code in Xcode auszuführen? – bibscy

0

Dies ist die richtige Antwort auf meine Frage. Wenn jemand einen besseren Ansatz hat, posten Sie Ihre Version im Antwortbereich.

class NinethViewController: UIViewController, UITableViewDelegate,UITableViewDataSource { 
var total = 0 
var totalKey = "totalNinethViewControllerKey" 
let indexPathKey = "indexPathForCellSelectedNinethViewControllerKey" 
var indexPathsForCellSelected: NSMutableSet = NSMutableSet()// {NSIndexPath} 


struct Item { 
    var name:String // name of the row 
    var selected:Bool // whether is selected or not 
    var amount: Int // value of the item 
} 

var extras = [ 

    Item(name:"Inside Cabinets",selected: false, amount: 5), 
    Item(name:"Inside Fridge",selected: false, amount: 5), 
    Item(name:"Inside Oven",selected: false, amount: 5), 
    Item(name:"Laundry wash & dry",selected: false, amount: 10), 
    Item(name:"Interior Windows", selected: false, amount: 5) 
] 


@IBOutlet weak var tableView: UITableView! 

override func viewDidLoad() { 
    super.viewDidLoad() 
} 

override func viewDidAppear(animated: Bool) { 
    super.viewDidAppear(animated) 

    // loadData from NSUserDefaults 
    self.loadData() 

} 

func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
    return extras.count 
} 

func numberOfSectionsInTableView(tableView: UITableView) -> Int { 
    return 1 
} 

// configure the cell 
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) 
    -> UITableViewCell  { 
     let cell = tableView.dequeueReusableCellWithIdentifier("Cell") 
     cell?.textLabel?.text = extras[indexPath.row].name 
     return cell! 
} 

func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) { 

    // if the cell has not been selected before 
    if !extras[indexPath.row].selected { 

     // marks the cell as selected once 
     extras[indexPath.row].selected = true 
     tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .Checkmark 
     self.total += extras[indexPath.row].amount 

     indexPathsForCellSelected.addObject(indexPath) 


     print("selecting") 
     print(total) 



    } else { 
     // marks the cell as not selected 
     extras[indexPath.row].selected = false 
     tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .None 
     self.total -= extras[indexPath.row].amount 

     indexPathsForCellSelected.removeObject(indexPath) 
     print(total) 
    } 
    // save all info in NSUserDefaults 
    self.saveData() 
} 

func saveData() { 
    // save indexPathsForCellSelected in NSUserDefaults 
    let data = NSKeyedArchiver.archivedDataWithRootObject(indexPathsForCellSelected) 
    NSUserDefaults.standardUserDefaults().setObject(data, forKey: indexPathKey) 

    //save total in NSUserDefaults 
    NSUserDefaults.standardUserDefaults().setObject(total, forKey: totalKey) 
} 

func loadData() { 
    //retrieve indexPathForCellSelected from NSUserDefaults 
if let retrievedIndexPath = NSUserDefaults.standardUserDefaults().dataForKey(indexPathKey) { 
     if let data1 = NSKeyedUnarchiver.unarchiveObjectWithData(retrievedIndexPath) as? NSMutableSet{ 
      indexPathsForCellSelected = data1 
     } 
    } 

    // assign checkmark to row selected 
    for item in indexPathsForCellSelected { 

     if let indexPath = item as? NSIndexPath { 
      extras[indexPath.row].selected = true 
       self.tableView.cellForRowAtIndexPath(indexPath)?.accessoryType = .Checkmark 

      /* let tableV = self.tableView 
      let cell = tableV.cellForRowAtIndexPath(indexPath) 
      extras[indexPath.row].selected = true 
      cell?.accessoryType = .Checkmark */ 

     } 
    } 

    // retrieve total from NSUserDefaults 
    if let totalRetrieved = NSUserDefaults.standardUserDefaults().objectForKey(totalKey) as? Int { 
     total = totalRetrieved 
     print(total) 
    } 
} 
} 
Verwandte Themen