我正在努力养成以 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? {获取}
。
我在这里遗漏了什么会扰乱 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
上遇到错误:无法使用类型为“((_) -> _)”的参数列表调用“map”
。
在我看来是这样的:
if let notifications = objects as? [PFObject] {
let sortedMessages: [String] = notifications.sorted { $0.createdAt!.compare($1.createdAt!) == .OrderedAscending }
.map { $0["message"] as! String }
}
应该是有效的,但是 Swift 的类型推断还没有达到标准……(?)。我不愿意让自己摆脱困境并责怪语言,但在这种情况下看起来很合理。我错过了什么吗?
最佳答案
类型不完全匹配。 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
有可能为 nil,您可能还需要某种回退:
.map { $0["message"] as? String ?? "Default message" }
关于swift - 了解 Swift 的闭包类型要求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29381084/