了解Swift的关闭类型要求
我试图进入Swifty方式而不是翻译Obj-C的习惯。了解Swift的关闭类型要求
我正在用Parse做一个项目,并且在获取一堆Parse对象之后,我想先对它们进行排序,然后从它们中提取特定的属性。这就是我想现在:
if let notifications = fetchedObjects as? [PFObject] {
// This line tells me "Cannot invoke 'sorted' with an argument list of type '((_, _) -> _)'
let sortedMessages: [String] = notifications.sorted { $0.createdAt.compare($1.createdAt) == .OrderedAscending }
}
PFObject
宣布这样的createdAt
属性:var createdAt: NSDate? { get }
。
我在这里错过了与Swift的类型检查混淆?
这是我想要的东西搞清楚上述错误之后:
if let notifications = fetchedObjects as? [PFObject] {
let sortedMessages: [String] = notifications.sorted({ $0.createdAt.compare($1.createdAt) == .OrderedAscending }).map { $0["message"] }
}
这在我看来就像所有类型应该明确和匹配。
UPDATE
我回到这个今天得到它的工作。我没有把它写在我原来的职位,但我昨天试图强行拆礼物createdAt
可选太:
if let notifications = fetchedObjects as? [PFObject] {
// This line tells me "Cannot invoke 'sorted' with an argument list of type '((_, _) -> _)'
let sortedMessages: [String] = notifications.sorted { $0.createdAt!.compare($1.createdAt!) == .OrderedAscending }
}
这是给我确切的同样的错误。到目前为止,我学习玩Swift的一件事是,当它给出隐藏类型不匹配错误时,最好将类型声明显式添加到每个变量 - 这通常会导致更具体的错误消息。所以,今天我写了上面这样的代码:
if let notifications = objects as? [PFObject] {
let sortedMessages: [String] = notifications.sorted { (lhs: PFObject, rhs: PFObject) -> Bool in
return rhs.createdAt!.compare(lhs.createdAt!) == .OrderedAscending
}.map { $0["message"] as! String }
}
这似乎编译没有问题。但是,如果我依靠类型推断:
if let notifications = objects as? [PFObject] {
let sortedMessages: [String] = notifications.sorted { lhs, rhs in
return rhs.createdAt!.compare(lhs.createdAt!) == .OrderedAscending
}.map { $0["message"] as! String }
}
我得到map
的错误:Cannot invoke 'map' with an argument list of type '((_) -> _)'
。
在我看来是这样的:
if let notifications = objects as? [PFObject] {
let sortedMessages: [String] = notifications.sorted { $0.createdAt!.compare($1.createdAt!) == .OrderedAscending }
.map { $0["message"] as! String }
}
应该是有效的,但斯威夫特的类型推断是不及格可是...(?)。我不能让自己摆脱困境并责怪语言,但在这种情况下看起来很合理。我错过了什么吗?
这些类型并不完全匹配。 createdAt
是Optional
,并且compare
方法采用非可选方式。此外,如果不知道PFObject
返回的具体含义,如果它像字典一样,我的猜测是AnyObject!
或AnyObject?
,在这种情况下,它需要进行类型转换并可能用!
强制解包。下面的代码可以编译:
notifications.sorted {
switch ($0.createdAt, $1.createdAt) {
case (.Some(let first), .Some(let second)):
return first.compare(second) == .OrderedAscending
default:
return true
}
}.map { $0["message"]! as String }
注意,在雨燕1.2,你需要使用as!
而不是as
因为这是一个不安全的投(从AnyObject
到String
)。如果有message
是零的机会,在对象上,你可能还需要有某种回退:
.map { $0["message"] as? String ?? "Default message" }
如果你在Swift 1.2中,你可能会喜欢尝试'flatMap'而不是'switch':notifications.sorted {lhs,rhs in rhs.createdAt.flatMap {lhs.createdAt?.compare($ 0)} = = .OrderedAscending}' – 2015-04-01 14:00:38
感谢您的答复!我有两个后续问题:1)我也试过:'notifications.sorted {$ 0.createdAt!.compare($ 1.createdAt!)== .OrderedAscending}'(即强制展开可选日期),并且这有同样的问题,在我原来的职位。这是为什么? 2)'flatMap'到底有多帮助? – Shinigami 2015-04-01 16:56:25
什么类型不'$ 0“消息”]'回来吗? 'AnyObject!'? – pwightman 2015-04-02 14:33:36
正确。 'AnyObject!'。 – Shinigami 2015-04-02 21:21:00