Swift如果让评估成功可选(无)
我有一个名为Field的自定义对象。 我基本上用它来定义一个窗体中的单个字段。
class Field { var name: String var value: Any? // initializers here... }
当用户提交表单时,我validation每个Field
对象以确保它们包含有效的值。 有些字段不是必需的,所以我有时故意将nil
设置为value
属性,如下所示:
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中设置了断点,而当field.value
被故意设置为nil时,它通过if-let块而不是else。 但是,对于其字段field.value
未初始化和未赋值的字段, 程序将转到else块。
我试图打印出if. let块内的field.value
和value
:
if let value = field.value { NSLog("field.value: \(field.value), value: \(value)") }
这就是我得到的:
field.value:可选(nil),值:nil
所以我认为,也许用可选项,未初始化是另一回事,有零的价值。 但是,即使在if-let内部添加另一个也不会使编译器感到高兴:
if let value = field.value { if value == nil { // Cannot invoke '==' with an argument list of type '(Any, NilLiteralConvertible)' } }
我如何解决这个问题? 我只是想检查field.value
是否nil
。
我相信这是因为Any?
允许任何值和Optional.None
被解释为只是另一个值,因为Optional
是一个枚举!
AnyObject?
应该无法执行此操作,因为它只能包含Optional.Some([any class object])
,它不允许使用Optional.Some(Optional)
,其值为Optional.None
。
这甚至令人困惑,甚至谈论。 重点是:尝试AnyObject?
而不是Any?
看看是否有效。
更重要的是,Matt的评论之一提到,他想使用Any
的原因是用于select文本input的字段或用于select核心数据对象的字段。
在这种情况下要做的Swifty事情是使用一个枚举与关联的值 ,基本上是一样的东西作为标记/歧视的联盟 。 以下是如何声明,分配和使用这样的枚举:
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?
。 有两种情况,他们被logging在案。 当然,selectvariables可以是可选的,不用担心。
有一个技巧来取代我的Any?
键入一个枚举,但我不能得到这个错误,我的头。 改变我的方法并不能改变我目前的问题,我不得不弄清楚我是如何到达Optional(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)") } }
简而言之,我将一个零值( AppState().currentValue
)传递给接受Any
的初始化程序,并将其赋值给Any?
types的属性Any?
。 这里有趣的是如果我直接通过nil
,编译器会抱怨:
let f = Field("Amount", nil) // Type 'Any' does not conform to protocol 'NilLiteralConvertible'
似乎在某个地方,Swift将AppState().currentValue
的nil
值封装在一个可选的, Optional(nil)
。