2015-04-01 49 views
2

我试图进入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 } 
} 

应该是有效的,但斯威夫特的类型推断是不及格可是...(?)。我不能让自己摆脱困境并责怪语言,但在这种情况下看起来很合理。我错过了什么吗?

+0

什么类型不'$ 0“消息”]'回来吗? 'AnyObject!'? – pwightman 2015-04-02 14:33:36

+0

正确。 'AnyObject!'。 – Shinigami 2015-04-02 21:21:00

回答

1

这些类型并不完全匹配。 createdAtOptional,并且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因为这是一个不安全的投(从AnyObjectString)。如果有message是零的机会,在对象上,你可能还需要有某种回退:

.map { $0["message"] as? String ?? "Default message" } 
+0

如果你在Swift 1.2中,你可能会喜欢尝试'flatMap'而不是'switch':notifications.sorted {lhs,rhs in rhs.createdAt.flatMap {lhs.createdAt?.compare($ 0)} = = .OrderedAscending}' – 2015-04-01 14:00:38

+0

感谢您的答复!我有两个后续问题:1)我也试过:'notifications.sorted {$ 0.createdAt!.compare($ 1.createdAt!)== .OrderedAscending}'(即强制展开可选日期),并且这有同样的问题,在我原来的职位。这是为什么? 2)'flatMap'到底有多帮助? – Shinigami 2015-04-01 16:56:25