如何在本地保存 NSIndexPath?
How to save NSIndexPath locally?
我可以通过以下方式获取 table 视图中可见单元格的第一行:
let topRow = tableView?.indexPathsForVisibleRows![0]
我想保存这个 NSIndexPath
以便应用程序下次启动时,table 视图可以滚动到与离开时相同的位置。
我想我应该保存 topRow.row 和 topRow.section。还有别的事吗?或者有什么更好的方法吗?
对于这种事情使用NSUserDefaults
是个不错的主意。我建议阅读此 post 以获取详细信息。
TLDR;
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setInteger(indexPath.row, forKey: "LastVisibleRowKey")
defaults.setInteger(indexPath.section, forKey: "LastVisibleSectionKey")
为了检索您保存的项目:
let row = defaults.integerForKey("LastVisibleRowKey")
希望对您有所帮助。
更好的方法是使用 State Restoration,而不是尝试自行保留 UIKit 状态。
iOS 文档的应用程序编程指南涵盖了 how to enable state preservation and restoration 您的应用程序。
From the user’s perspective, quitting an app should just seem like a temporary interruption. When the user returns to an app, that app should always return the user to the last point of use, so that the user can continue with whatever task was in progress. This behavior provides a better experience for the user and with the state restoration support built in to UIKit is relatively easy to achieve.
The state preservation system in UIKit provides a simple but flexible infrastructure for preserving and restoring the state of your app’s view controllers and views.
如您所见,它可以为您保留的不仅仅是 tableView 的内容偏移量。
NSIndexPath
实现了 NSSecureCoding
协议。这意味着您可以使用 NSKeyedArchiver
和 NSKeyedUnarchiver
将索引路径转换为可以存储在 plist 或用户默认值中的数据。
示例:
extension NSUserDefaults {
func indexPathForKey(key: String) -> NSIndexPath? {
if let data = self.objectForKey(key) as? NSData {
if let indexPath = NSKeyedUnarchiver.unarchiveObjectWithData(data) as? NSIndexPath {
return indexPath
}
}
return nil;
}
func setIndexPath(indexPath: NSIndexPath, forKey key:String) {
self.setObject(NSKeyedArchiver.archivedDataWithRootObject(indexPath), forKey: key)
}
}
let defaults = NSUserDefaults.standardUserDefaults()
//
// Saving an index path
//
let myIndexPath = NSIndexPath(indexes:[1, 2, 3, 4], length: 4)
defaults.setIndexPath(myIndexPath, forKey:"MyIndexPath")
//
// Loading an index path
//
if let newIndexPath = defaults.indexPathForKey("MyIndexPath") {
print("Loaded index path: \(newIndexPath)")
assert(myIndexPath == newIndexPath)
}
您可以使用 NSKeyedArchiver
archiveRootObject
将索引数据写入库首选项目录中的 plist 文件,然后使用 NSKeyedUnarchiver
unarchiveObjectWithFile
将其解压缩。只需创建一个名为 lastSelectedIndex 的 属性 以及一个 getter 和一个 setter 即可自动保存和加载它:
var lastSelectedIndex: NSIndexPath? {
get {
guard
let filePath = NSFileManager().URLsForDirectory(.LibraryDirectory, inDomains: .UserDomainMask).first?.URLByAppendingPathComponent("Preferences", isDirectory: true).URLByAppendingPathComponent("myAppData.plist").path
else { return nil }
return NSKeyedUnarchiver.unarchiveObjectWithFile(filePath) as? NSIndexPath
}
set {
guard
let newValue = newValue,
filePath = NSFileManager().URLsForDirectory(.LibraryDirectory, inDomains: .UserDomainMask).first?.URLByAppendingPathComponent("Preferences", isDirectory: true).URLByAppendingPathComponent("myAppData.plist").path
else { return }
NSKeyedArchiver.archiveRootObject(newValue, toFile: filePath)
}
}
在您的方法 didSelectRowAtIndexPath 中设置您的 lastSelectedIndex:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
lastSelectedIndex = indexPath
// your code
}
并加载如下:
override func viewDidLoad() {
super.viewDidLoad()
guard let lastSelectedIndex = lastSelectedIndex else { return }
tableView.selectRowAtIndexPath(lastSelectedIndex, animated: false, scrollPosition: .None)
}
我可以通过以下方式获取 table 视图中可见单元格的第一行:
let topRow = tableView?.indexPathsForVisibleRows![0]
我想保存这个 NSIndexPath
以便应用程序下次启动时,table 视图可以滚动到与离开时相同的位置。
我想我应该保存 topRow.row 和 topRow.section。还有别的事吗?或者有什么更好的方法吗?
对于这种事情使用NSUserDefaults
是个不错的主意。我建议阅读此 post 以获取详细信息。
TLDR;
let defaults = NSUserDefaults.standardUserDefaults()
defaults.setInteger(indexPath.row, forKey: "LastVisibleRowKey")
defaults.setInteger(indexPath.section, forKey: "LastVisibleSectionKey")
为了检索您保存的项目:
let row = defaults.integerForKey("LastVisibleRowKey")
希望对您有所帮助。
更好的方法是使用 State Restoration,而不是尝试自行保留 UIKit 状态。
iOS 文档的应用程序编程指南涵盖了 how to enable state preservation and restoration 您的应用程序。
From the user’s perspective, quitting an app should just seem like a temporary interruption. When the user returns to an app, that app should always return the user to the last point of use, so that the user can continue with whatever task was in progress. This behavior provides a better experience for the user and with the state restoration support built in to UIKit is relatively easy to achieve.
The state preservation system in UIKit provides a simple but flexible infrastructure for preserving and restoring the state of your app’s view controllers and views.
如您所见,它可以为您保留的不仅仅是 tableView 的内容偏移量。
NSIndexPath
实现了 NSSecureCoding
协议。这意味着您可以使用 NSKeyedArchiver
和 NSKeyedUnarchiver
将索引路径转换为可以存储在 plist 或用户默认值中的数据。
示例:
extension NSUserDefaults {
func indexPathForKey(key: String) -> NSIndexPath? {
if let data = self.objectForKey(key) as? NSData {
if let indexPath = NSKeyedUnarchiver.unarchiveObjectWithData(data) as? NSIndexPath {
return indexPath
}
}
return nil;
}
func setIndexPath(indexPath: NSIndexPath, forKey key:String) {
self.setObject(NSKeyedArchiver.archivedDataWithRootObject(indexPath), forKey: key)
}
}
let defaults = NSUserDefaults.standardUserDefaults()
//
// Saving an index path
//
let myIndexPath = NSIndexPath(indexes:[1, 2, 3, 4], length: 4)
defaults.setIndexPath(myIndexPath, forKey:"MyIndexPath")
//
// Loading an index path
//
if let newIndexPath = defaults.indexPathForKey("MyIndexPath") {
print("Loaded index path: \(newIndexPath)")
assert(myIndexPath == newIndexPath)
}
您可以使用 NSKeyedArchiver
archiveRootObject
将索引数据写入库首选项目录中的 plist 文件,然后使用 NSKeyedUnarchiver
unarchiveObjectWithFile
将其解压缩。只需创建一个名为 lastSelectedIndex 的 属性 以及一个 getter 和一个 setter 即可自动保存和加载它:
var lastSelectedIndex: NSIndexPath? {
get {
guard
let filePath = NSFileManager().URLsForDirectory(.LibraryDirectory, inDomains: .UserDomainMask).first?.URLByAppendingPathComponent("Preferences", isDirectory: true).URLByAppendingPathComponent("myAppData.plist").path
else { return nil }
return NSKeyedUnarchiver.unarchiveObjectWithFile(filePath) as? NSIndexPath
}
set {
guard
let newValue = newValue,
filePath = NSFileManager().URLsForDirectory(.LibraryDirectory, inDomains: .UserDomainMask).first?.URLByAppendingPathComponent("Preferences", isDirectory: true).URLByAppendingPathComponent("myAppData.plist").path
else { return }
NSKeyedArchiver.archiveRootObject(newValue, toFile: filePath)
}
}
在您的方法 didSelectRowAtIndexPath 中设置您的 lastSelectedIndex:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
lastSelectedIndex = indexPath
// your code
}
并加载如下:
override func viewDidLoad() {
super.viewDidLoad()
guard let lastSelectedIndex = lastSelectedIndex else { return }
tableView.selectRowAtIndexPath(lastSelectedIndex, animated: false, scrollPosition: .None)
}