ios – Swift和NSUserDefaults – 当用户默认为空时,EXC_BAD_INSTRUCTION

前端之家收集整理的这篇文章主要介绍了ios – Swift和NSUserDefaults – 当用户默认为空时,EXC_BAD_INSTRUCTION前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在将我的一个项目转换为 Swift文件.我有一个奇怪的行为与NSUserDefaults.我使用NSString而不是String来与其他代码兼容
var selectedMonth : NSString {
get {
    return NSUserDefaults.standardUserDefaults().objectForKey(AppUserDefaults.SelectedMonth.value()) as NSString
}
set {
    NSUserDefaults.standardUserDefaults().setObject(self,forKey: AppUserDefaults.SelectedMonth.value())
    NSUserDefaults.standardUserDefaults().synchronize()
}
}

方法获取/设置属性时正常工作,但是当应用程序第一次执行并且用户默认值为空时,在返回NSUserDefaults.standardUserDefaults()时收到EXC_BAD_INSTRUCTION错误.objectForKey(AppUserDefaults.SelectedMonth.value())作为NSString

问题不在于回报,因为我可以“扩展”这样的语句:

let defaultKey = AppUserDefaults.SelectedMonth.value()
    let defaults = NSUserDefaults.standardUserDefaults()  // defaults is correctly set
    let result : AnyObject = defaults.objectForKey(defaultKey)  // <-- the error is here
    return result as NSString

客观C中的类似声明正确运行,返回零,但是我看到swift中的objectForKey的声明是

func objectForKey(defaultName: String!) -> AnyObject!

注意感叹号到底,似乎一个对象必须从函数中返回,但是我认为正确的声明(使其在objc中工作)应该以a结尾?
所以我认为行为发生了变化,并没有写在文档中.

你认为这是一个错误(所以我会提交)或者我错过了什么?
谢谢

解决方法

编辑
这个答案不再更新,因为在最后的Swift版本中,Apple更改了NSUserDefaults上的objectForKey的方法声明(以及从目标c桥接的许多其他方法)返回一个可选的(?),而不再有一个隐式解包可选(!)
结束编辑

好的,我阅读更好的文档和意思!在一个宣言中,这是不一样的!当使用变量时.

!在一个声明中意味着该变量被隐式解开(在Swift书中,读取“隐含展开的可选项”和“未知引用和隐式解开的可选属性”章节,以更好地了解它的含义

简单来说,这意味着返回值仍然可以为零,但是由于它很少发生,所以返回值/变量没有被标记为可选的(带有?).
这是为了避免程序员需要每次打开值(使用if语句检查并打开值)来清除代码.

然而,第一个问题是EXC_BAD_INSTRUCTION被错误地列出,因为这个声明

let defaultKey = AppUserDefaults.SelectedMonth.value()
let defaults = NSUserDefaults.standardUserDefaults() 
let result : AnyObject = defaults.objectForKey(defaultKey) 
return NSString(UTF8String: "")

没有给出错误(结果没有返回,但是objectForKey调用没有失败)
所以这再次给了我正确的方法,并且理解了隐含解开的可选项的含义

解决方案很简单,因为返回的值可以为零,selectMonth应该有一个变量? (被标记为可选)或一个! (被标记为隐式展开的可选)

例子

1)返回AnyObject? optinal值作为var selectedMonth的类型

var selectedMonth : AnyObject? {
get {
    return NSUserDefaults.standardUserDefaults().objectForKey(AppUserDefaults.SelectedMonth.value())

}
set {
    NSUserDefaults.standardUserDefaults().setObject(newValue,forKey: AppUserDefaults.SelectedMonth.value())
    NSUserDefaults.standardUserDefaults().synchronize()
}
}

2)返回一个可选的NSString?将返回类型转换为AnyObject?然后到NSString?

var selectedMonth : NSString? {
get {
    return NSUserDefaults.standardUserDefaults().objectForKey(AppUserDefaults.SelectedMonth.value()) as AnyObject? as NSString?
}
set {
    NSUserDefaults.standardUserDefaults().setObject(newValue,forKey: AppUserDefaults.SelectedMonth.value())
    NSUserDefaults.standardUserDefaults().synchronize()
}
}

这就像写作

var selectedMonth : NSString? {
get {
    var returnValue : AnyObject? = NSUserDefaults.standardUserDefaults().objectForKey(AppUserDefaults.SelectedMonth.value())
    return returnValue as NSString?
}
set {
    NSUserDefaults.standardUserDefaults().setObject(newValue,forKey: AppUserDefaults.SelectedMonth.value())
    NSUserDefaults.standardUserDefaults().synchronize()
}
}

3)返回一个隐含包装的NSString!

var selectedMonth : NSString! {
get {
    var returnValue : AnyObject! = NSUserDefaults.standardUserDefaults().objectForKey(AppUserDefaults.SelectedMonth.value())
    return returnValue as NSString!
}
set {
    NSUserDefaults.standardUserDefaults().setObject(newValue,forKey: AppUserDefaults.SelectedMonth.value())
    NSUserDefaults.standardUserDefaults().synchronize()
}
}

4)短版

var selectedMonth : NSString! {
get {
    return NSUserDefaults.standardUserDefaults().objectForKey(AppUserDefaults.SelectedMonth.value()) as AnyObject! as NSString!
}
set {
    NSUserDefaults.standardUserDefaults().setObject(newValue,forKey: AppUserDefaults.SelectedMonth.value())
    NSUserDefaults.standardUserDefaults().synchronize()
}
}
原文链接:https://www.f2er.com/iOS/329470.html

猜你在找的iOS相关文章