Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add NSIndexPath to NSUserDefaults in swift

I am trying to save NSIndexPath at NSUserDefaults, but got the following exception:-

Attempt to set a non-property-list object {length = 2, path = 0 - 12} as an NSUserDefaults/CFPreferences value for key LastSelectedIndeX

My code:-

let selectedIndexPath = tableView.indexPathForSelectedRow
   NSUserDefaults.standardUserDefaults().setObject(selectedIndexPath, forKey: "lastSelectedIndex")
   NSUserDefaults.standardUserDefaults().synchronize()

So how can I save NSIndexPath so that I can use it later on at another view controller.

like image 252
pkc456 Avatar asked May 03 '16 10:05

pkc456


3 Answers

You can't save directly indexPath in NSUserDefault. You can Store NSArray , NSDictionary , NSNumber , NSString and NSDictionary in NSUserDefault.

Store IndexPath using NSKeyedArchiver:

let data = NSKeyedArchiver.archivedDataWithRootObject(selectedIndexPath)
NSUserDefaults.standardUserDefaults().setObject(data, forKey: "indexKey")

Get IndexPath using NSKeyedArchiver:

let data1 = NSUserDefaults.standardUserDefaults().objectForKey("indexKey") as? NSData
let indexP1 = NSKeyedUnarchiver.unarchiveObjectWithData(data1!) as! NSIndexPath
like image 112
Kirit Modi Avatar answered Nov 06 '22 12:11

Kirit Modi


As mentioned by the others (NS)IndexPath is not property list compliant.

A solution is to use this simple extension of UserDefaults to save the IndexPath as an array of two integers

extension UserDefaults {

  func indexPath(forKey key : String) -> IndexPath?
  {
    guard let indexArray = array(forKey: key) as? [Int] else { return nil }
    return IndexPath(row: indexArray[0], section: indexArray[1])
  }

  func set(_ indexPath : IndexPath, forKey key: String)
  {
    set([indexPath.row, indexPath.section], forKey: key)
  }
}

You can find the syntax for an older Swift version in the edit history.

like image 25
vadian Avatar answered Nov 06 '22 12:11

vadian


This Swift code would work for any depth of IndexPath

extension UserDefaults {
    func indexPath(forKey key: String) -> IndexPath? {
        if let data = data(forKey: key), let indexPath = try? JSONDecoder().decode(IndexPath.self, from: data) {
            return indexPath
        }
        return nil
    }
    func set(_ indexPath: IndexPath, forKey key: String) {
        if let data = try? JSONEncoder().encode(indexPath) {
            set(data, forKey: key)
        }
    }
}
like image 1
Jeremy Buchman Avatar answered Nov 06 '22 12:11

Jeremy Buchman