NSArray、NSUserDefaults、可选项和解包混乱
NSArray, NSUserDefaults, optionals and unwrapping mess
我在处理看似简单的事情时遇到了严重的错误。
我有一个 NSArray
,我会在应用程序第一次启动时用文字填充它。
然后在某个时候我想使用数组,所以我在 class:
中声明了另一个数组
var localArray = NSUserDefaults.standardUserDefaults().arrayForKey("array")!
然后我想在标签中显示一个词。当用户按下按钮 (forward/backward) 时,会出现 next/previous 字样。很简单,对吧?是的,但不知何故我得到了非常讨厌的错误。
对于 next/previous 个单词,我有 2 种方法:
@IBAction func nextWord(sender: AnyObject) {
if let currentIndex = localArray.indexOf(label.text!)
{
if currentIndex == localArray.count-1
{
label.text = localArray[0] as? String
}
else
{
label.text = localArray[currentIndex+1]
}
}
}
另一种倒退的方法是相同的(有必要的修改)。
而在 viewDidLoad
中,我只是设置了标签的文本:
label.text = localArray[0] as? String
问题出在 if let
语句上。在使用用户默认值之前,我只是用一些字符串初始化了 localArray
。一切正常。但是一旦我添加了用户默认值,疯狂就开始了。我在使用 localArray
的任何地方都有错误,说数组没有展开。所以我在初始化本地的时候在user defaults数组后面加了!
但是最后 2 个错误(在 if let
语句中)毫无意义。现在 indexOf()
方法抛出一个错误,这是以前没有发生过的事情。它还告诉我它无法将字符串 (label.text!) 转换为 @noescape (AnyObject) throws -> Bool
.
所以现在我需要将该字符串转换为 NSString
才能正常工作或怎样?我在用户默认值中发现了一些关于 "bridging" 与数组相关的内容。那是我的问题吗?
这就是困扰我的问题:为什么我必须明确地将数组中的字符串向下转换为字符串?为什么 indexOf
方法改变了。
未包装的可选是否像非可选一样?
如果用取模运算符实现会好很多。
let newIndex = (oldIndex + 1) % localArray.count
我需要更多信息来回答您的大部分问题。 localArray
的类型是什么?
您正在创建的对象不是数组(至少编译器不知道它是)。函数 arrayForKey("array")!
返回 AnyObject
,而不是 Array
。所以从那时起,编译器认为这个对象是一个 AnyObject
。我将如何解决这个问题(可能不是正确的方法)是立即投射数组:
if let myArray: AnyObject! = NSUserDefaults.standardUserDefaults().objectForKey("array") {
//Your array exists, cast it now and use it
var localArray = myArray as! Array<String>
}
else
{
//Something bad happened, the array isn't there.
}
那你稍后就得解包了。如果您知道此对象将始终存在并且转换将始终有效,您可以将 ?
更改为 !
。
查看 this answer 了解更多信息。
你应该总是(并且对于大部分强制向下转换)。为了从 NSUserDefaults
中安全地检索您的数组(使用正确的类型),您可以执行以下操作:
if let array = NSUserDefaults.standardUserDefaults().arrayForKey("array") as? [String] {
// do something with your [String] array
} else {
// do error handling
}
这样做的目的是从 NSUserDefaults
中获取一个 [AnyObject]?
,代表您的数组。然后,您可以使用 as?
有条件地向下转换并将其桥接回 Swift 字符串数组 ([String]
)。如果这不成功,您可以安全地处理这种情况。
我在处理看似简单的事情时遇到了严重的错误。
我有一个 NSArray
,我会在应用程序第一次启动时用文字填充它。
然后在某个时候我想使用数组,所以我在 class:
中声明了另一个数组var localArray = NSUserDefaults.standardUserDefaults().arrayForKey("array")!
然后我想在标签中显示一个词。当用户按下按钮 (forward/backward) 时,会出现 next/previous 字样。很简单,对吧?是的,但不知何故我得到了非常讨厌的错误。
对于 next/previous 个单词,我有 2 种方法:
@IBAction func nextWord(sender: AnyObject) {
if let currentIndex = localArray.indexOf(label.text!)
{
if currentIndex == localArray.count-1
{
label.text = localArray[0] as? String
}
else
{
label.text = localArray[currentIndex+1]
}
}
}
另一种倒退的方法是相同的(有必要的修改)。
而在 viewDidLoad
中,我只是设置了标签的文本:
label.text = localArray[0] as? String
问题出在 if let
语句上。在使用用户默认值之前,我只是用一些字符串初始化了 localArray
。一切正常。但是一旦我添加了用户默认值,疯狂就开始了。我在使用 localArray
的任何地方都有错误,说数组没有展开。所以我在初始化本地的时候在user defaults数组后面加了!
但是最后 2 个错误(在 if let
语句中)毫无意义。现在 indexOf()
方法抛出一个错误,这是以前没有发生过的事情。它还告诉我它无法将字符串 (label.text!) 转换为 @noescape (AnyObject) throws -> Bool
.
所以现在我需要将该字符串转换为 NSString
才能正常工作或怎样?我在用户默认值中发现了一些关于 "bridging" 与数组相关的内容。那是我的问题吗?
这就是困扰我的问题:为什么我必须明确地将数组中的字符串向下转换为字符串?为什么 indexOf
方法改变了。
未包装的可选是否像非可选一样?
如果用取模运算符实现会好很多。
let newIndex = (oldIndex + 1) % localArray.count
我需要更多信息来回答您的大部分问题。 localArray
的类型是什么?
您正在创建的对象不是数组(至少编译器不知道它是)。函数 arrayForKey("array")!
返回 AnyObject
,而不是 Array
。所以从那时起,编译器认为这个对象是一个 AnyObject
。我将如何解决这个问题(可能不是正确的方法)是立即投射数组:
if let myArray: AnyObject! = NSUserDefaults.standardUserDefaults().objectForKey("array") {
//Your array exists, cast it now and use it
var localArray = myArray as! Array<String>
}
else
{
//Something bad happened, the array isn't there.
}
那你稍后就得解包了。如果您知道此对象将始终存在并且转换将始终有效,您可以将 ?
更改为 !
。
查看 this answer 了解更多信息。
你应该总是NSUserDefaults
中安全地检索您的数组(使用正确的类型),您可以执行以下操作:
if let array = NSUserDefaults.standardUserDefaults().arrayForKey("array") as? [String] {
// do something with your [String] array
} else {
// do error handling
}
这样做的目的是从 NSUserDefaults
中获取一个 [AnyObject]?
,代表您的数组。然后,您可以使用 as?
有条件地向下转换并将其桥接回 Swift 字符串数组 ([String]
)。如果这不成功,您可以安全地处理这种情况。