我试图养成以Swifty方式做事而不是翻译Obj-C的习惯。
我正在用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"] }
}
在我看来,所有类型都应该清晰和匹配。
更新
我今天回到这里并开始工作。我没有在我的原帖中写出来,但昨天我确实试图强制打开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 }
}
应该是有效的,但Swift的类型推断还没有达到鼻烟......(?)。我不喜欢让自己摆脱困境并责怪语言,但在这种情况下看起来很合理。我错过了什么吗?
答案 0 :(得分:1)
这些类型并不匹配。 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 }
请注意,在Swift 1.2中,您需要使用as!
代替as
,因为这是一个不安全的演员(从AnyObject
到String
)。如果message
在对象上有{n}的可能性,您可能还希望有某种后备:
.map { $0["message"] as? String ?? "Default message" }