2015-04-01 103 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