在iOS模拟器下,我无法在应用启动时从NSUserDefault获取一致的值。我已经在应用程序的上一次运行中设置了值(我在那里放了一些打印件以确保没有意外更改),所以我不认为我调用synchronize()的方式有问题。读取也发生在主线程上,并在我设置了默认值之后。几秒钟后,如果我重新尝试从NSUserDefaults获取,我得到正确的值(我在那里放了一个计时器来验证值是否得到纠正,并且在启动后似乎保持不变)。
该值表示用户存储数据的位置(在iCloud上或仅在本地设备上),并由用户默认值中的整数表示。这是表示值的枚举:
class MovingDocument: UIDocument {
enum StorageSettingsState: Int {
case NoChoice = 0
case Local = 1
case ICloud = 2
}
}
以下是用于访问NSUserDefaults的类的摘录:
class Settings {
static let global = Settings()
private enum LocalStoreKeys : String {
case IsHorizontal = "IsHorizontal"
case ItemInPortrait = "ItemInPortrait"
case RotateTitle = "RotateTitle"
case StorageLocation = "StorageLocation"
}
// Other computed variables here for the other settings.
// Computed variable for the storage setting.
var storageLocation: MovingDocument.StorageSettingsState {
get {
print("Storage state fetch: \(NSUserDefaults.standardUserDefaults().integerForKey(LocalStoreKeys.StorageLocation.rawValue))")
return MovingDocument.StorageSettingsState(rawValue: NSUserDefaults.standardUserDefaults().integerForKey(LocalStoreKeys.StorageLocation.rawValue)) ?? .NoChoice
}
set {
print("Setting storage location to \(newValue) (\(newValue.rawValue))")
NSUserDefaults.standardUserDefaults().setInteger(newValue.rawValue, forKey: LocalStoreKeys.StorageLocation.rawValue)
synchronize()
CollectionDocument.settingsChanged()
}
}
func prepDefaultValues() {
NSUserDefaults.standardUserDefaults().registerDefaults([
LocalStoreKeys.IsHorizontal.rawValue: true,
LocalStoreKeys.ItemInPortrait.rawValue: true,
LocalStoreKeys.RotateTitle.rawValue: true,
LocalStoreKeys.StorageLocation.rawValue: MovingDocument.StorageSettingsState.NoChoice.rawValue
])
}
func synchronize() {
NSUserDefaults.standardUserDefaults().synchronize()
}
}
我应该阅读的值(以及我在启动后似乎总是得到的值)是值'1'或.Local。我有时得到的值是'0'或.NoChoice(恰好是默认值)。因此,它似乎在应用程序启动之后的某个时间点使用默认值。
为了完整起见,这里是相关的应用代理代码:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
Settings.global.prepDefaultValues() // Must be called before doing CollectionDocument.start() because we need the default value for storage location.
CollectionDocument.start()
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
browserController = ViewController()
navController = UINavigationController(rootViewController: browserController!)
navController!.navigationBar.translucent = false
self.window!.rootViewController = navController
self.window!.makeKeyAndVisible()
checkStorageLocation()
return true
}
在CollectionDocument.start()中调用getter(CollectionDocument是MovingDocument的子类,其中定义了位置枚举)。 checkStorageLocation()最后的调用是我对存储位置值的定期调试检查(它通过dispatch_after()调用自身。)
作为旁注,我还尝试将应用程序中的大部分代码(didFinishLaunchingWithOptions ...)放入dispatch_async调用(在主线程上)以查看是否有所不同(只是调用设置默认值和return语句立即完成,其余的调用被放入异步调用块),它仍然得到错误的值(有时)。我想我可以尝试使用dispatch_after(并等待一两秒钟),但是在完成之前我无法真正启动应用程序(因为在我知道它的位置之前我无法从文档中读取用户数据)只有这个问题的加载屏幕似乎很荒谬。
关于可能出错的任何想法?我不知道NSUserDefaults的任何限制,只要你被允许阅读它...
答案 0 :(得分:1)
重新启动我的mac修复了问题(不管它是什么)。 iOS 10, NSUserDefaults Does Not Work有一个类似的问题和相同的解决方案(虽然情况完全不同,因为我既没有尝试Xcode 8也没有尝试iOS 10)。