Ios Swift if let在可选项上成功计算(无)
我有一个名为Field的自定义对象。我基本上用它来定义表单中的单个字段Ios Swift if let在可选项上成功计算(无),ios,cocoa,cocoa-touch,swift,optional,Ios,Cocoa,Cocoa Touch,Swift,Optional,我有一个名为Field的自定义对象。我基本上用它来定义表单中的单个字段 class Field { var name: String var value: Any? // initializers here... } 当用户提交表单时,我验证每个字段对象,以确保它们包含有效值。有些字段不是必需的,所以我有时会故意将nil设置为值属性,如下所示: field.value = nil 当我使用if let来确定字段是否为零时,这似乎带来了一个问题 if let val
class Field {
var name: String
var value: Any?
// initializers here...
}
当用户提交表单时,我验证每个字段
对象,以确保它们包含有效值。有些字段不是必需的,所以我有时会故意将nil
设置为值
属性,如下所示:
field.value = nil
当我使用if let来确定字段是否为零时,这似乎带来了一个问题
if let value = field.value {
// The field has a value, ignore it...
} else {
// Add field.name to the missing fields array. Later, show the
// missing fields in a dialog.
}
我在上面的if-else和中设置断点,当字段。value
被故意设置为nil时,它通过if-let块,而不是else。但是,对于其字段。value
未初始化和未分配的字段,程序转到else块。
我尝试在if let块内打印出字段.value
和value
:
if let value = field.value {
NSLog("field.value: \(field.value), value: \(value)")
}
这就是我得到的:
field.value:可选(无),值:无
所以我想,也许对于optionals,一件事是未初始化,另一件事是具有nil值。但是,即使在if-let中添加另一个if也不会让编译器满意:
if let value = field.value {
if value == nil { // Cannot invoke '==' with an argument list of type '(Any, NilLiteralConvertible)'
}
}
我该怎么做?我只想检查
字段.value
是否为nil
我相信这是因为Any?
允许任何值和可选。由于Optional
是一个枚举,因此没有一个值被解释为另一个值
AnyObject?
应该无法执行此操作,因为它只能包含可选。一些([any class object])
,这不允许大小写可选。一些(可选)
值为可选。无
这甚至让人难以启齿。要点是:尝试AnyObject?
而不是Any?
,看看这是否有效
更重要的是,Matt的一条评论提到,他想使用Any
的原因是用于选择,可以是文本输入字段,也可以是用于选择核心数据对象的字段
在这种情况下,最快捷的方法是使用,基本上与。下面介绍如何声明、分配和使用此类枚举:
enum DataSelection {
case CoreDataObject(NSManagedObject)
case StringField(String)
}
var selection : DataSelection?
selection = .CoreDataObject(someManagedObject)
if let sel = selection { // if there's a selection at all
switch sel {
case .CoreDataObject(let coreDataObj):
// do what you will with coreDataObj
case .StringField(let string):
// do what you will with string
}
}
使用这样的枚举,不必担心哪些东西可能隐藏在Any?
中。有两个案例,并记录在案。当然,选择变量可以是可选的,没有任何顾虑。有一个技巧,可以用枚举替换我的any?
类型,但我无法从脑海中消除这个错误。改变我的方法并不能改变我当前的方法有问题的事实,我必须弄清楚我是如何得到一个可选(nil)
输出的
我能够通过在一个新的单视图项目中编写以下视图控制器来重现错误。注意init
签名
import UIKit
class Field {
var name: String = "Name"
var value: Any?
init(_ name: String, _ value: Any) {
self.name = name
self.value = value
}
}
class AppState {
var currentValue: Field?
}
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let f = Field("Amount", AppState().currentValue)
NSLog("\(f.value)")
}
}
简而言之,我将nil值(AppState().currentValue
)传递给接受Any
的初始值设定项,并将其分配给类型为Any?
的属性。有趣的是,如果我直接传递了nil
,编译器会抱怨:
let f = Field("Amount", nil) // Type 'Any' does not conform to protocol 'NilLiteralConvertible'
似乎在这个过程中的某个地方,Swift将AppState()的nil
值包装为可选值。currentValue
因此optional(nil)
无法复制。您使用哪个Xcode版本?Xcode 6 GM。尝试重新启动它,但仍然没有成功:(你能发布一个完整的自我包含的示例来演示这个问题吗?不要尝试使用Any
。使用Any
你就放弃了一半的Swift功能(强类型)。为什么不在那里使用一个好的泛型类型?@MattQuiros:所以使用一个枚举和两个案例:case-CoreDataObject(NSManagedObject)
和case-StringField(String)
,然后使用该枚举的可选项作为类型,而不是Any?
。正确答案是“不惜一切代价避免Any
”。如果您使用的是可选的Any
,那么您就完蛋了。是的,因为语言似乎没有办法区分可选。没有一个用于实际值或标记可选的Any
中没有值nil
不作为值存在(仅作为关键字),但可选。None
是任何可选变量的默认值,当要求它描述自身时,它会打印nil
。