当用户默认为空时,Swift和NSUserDefaults - EXC_BAD_INSTRUCTION [英] Swift and NSUserDefaults - EXC_BAD_INSTRUCTION when user defaults empty

查看:101
本文介绍了当用户默认为空时,Swift和NSUserDefaults - EXC_BAD_INSTRUCTION的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在将我的一个项目转换为Swift,逐个文件。我对NSUserDefaults有一种奇怪的行为。我使用NSString而不是String来与其他代码兼容

I'm converting one of my projects to Swift, file by file. I have a strange behavior with NSUserDefaults. I use an NSString and not a String for compatibility with other code

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()
}
}

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

The method works correctly for getting/setting the property, but when the app is executed the first time and the user defaults are empty, I receive an EXC_BAD_INSTRUCTION error on return NSUserDefaults.standardUserDefaults().objectForKey(AppUserDefaults.SelectedMonth.value()) as NSString

问题不在于回报,因为我可以扩展这句话:

The problem is not in the return, since I can "expand" the statement as this:

    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中的类似语句正常工作,返回nil,但我看到 objectForKey

A similar statement in objective C works correctly, returning nil, but I see that the declaration of objectForKey in swift is

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

注意最后的感叹号,似乎必须从函数返回一个对象,但是我认为正确的声明(使它像在objc中一样工作)应该以一个?
所以我认为行为发生了变化,而且没有写在文档中。

Note the exclamation mark at the end, it seems that an object MUST be returned from the function, but I think that the correct declaration (to make it work like in objc) should end with a ? So I think that the behavior changed, and it's not written in the documentation.

你认为这是一个错误(所以我会把它归档)或我错过了什么吗?
谢谢

Do you think it's a bug (so I'll file it) or am I missing something? Thanks

推荐答案

编辑

这个答案已不复存在自从最终的Swift版本发布以来,Apple更改了NSUserDefaults上的objectForKey的方法声明(以及从目标c桥接的许多其他方法)以返回一个可选的(?)而不再是一个隐式解包的可选(!)

结束编辑

好的,我更好地阅读了文档及其含义!在一个声明,这是一个不同于!使用变量时。

Ok, I read better the docs and the meaning of the ! in a declaration, which is different from a ! when using a variable.

!在一个声明中意味着该变量是隐式展开的(在Swift书上,读取隐式展开的选项和无主参考和隐式展开的可选属性章节以更好地理解它的含义

! in a declaration means that that variable is implicitly unwrapped (on the Swift book, read "Implicitly Unwrapped Optionals" and "Unowned References and Implicitly Unwrapped Optional Properties" chapters to understand better what it means

简单来说,这意味着返回值仍然可以为零,但由于它很少发生,因此返回值/变量未标记为可选(使用?)。
这是为了避免程序员每次需要打开值(用if语句检查并解开值),代码更清晰。

In simple words, it means that the return value can still be nil, but since it happens "rarely", the return value / variable is not marked as optional (with the ?). This is made to avoid the needing for the programmer to unwrap the value every time (checking with an if statement and unwrapping the value) having a cleaner code.

然而,第一个问题是EXC_BAD_INSTRUCTION是在错误的行上给出的,因为使用此语句

However, the first problem was that the EXC_BAD_INSTRUCTION was given on the wrong line, since with this statement

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

没有给出错误。(结果没有被返回,但是objectForKey调用没有失败)
所以这让我再次走上正确的道路并理解了Implicitly Unwrapped Optionals的含义

no error is given.(the result was not returned but the objectForKey call did not fail) So this brought me on the right way again and understanding the meaning of Implicitly Unwrapped Optionals

解决方案很简单,因为返回的值可以是nil变量 selectedMonth 应该有? (标记为可选)或a! (被标记为隐式展开的可选项)

The solutions are simple, since the returned value can be nil the variable selectedMonth should have a ? (to be marked as optional) or a ! (to be marked as implicitly unwrapped optional)

示例

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

1) return AnyObject? optinal value as a type for the 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?

2) return an optional NSString?, cast the return type to AnyObject? and then to 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!

3) return an implicitly wrapped 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()
}
}

这篇关于当用户默认为空时,Swift和NSUserDefaults - EXC_BAD_INSTRUCTION的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆