2017-08-23 32 views
1

好吧,那麼,快速noob警報:Swift 3迭代嵌套的Dictionary?

如何做最簡單的迭代給予以下數組(我不知道該稱爲這種形狀:數組,字典,對象...)?

func showNotification(_ sender: [AnyHashable: Any]) { ... } 

sender["actions"]:

Optional([{"text":"Confirm","type":"response"},{"text":"Decline","type":"response"},{"link":"https://www.stackoverflow.com","text":"Website","type":"info"}])

嘗試:

if let result = sender["actions"] { 
    print("YES \(result)") 
    for action in result as! [String] { 
    print(action) 
    } 
} 

the above prints

YES [{"text":"Confirm","type":"response"},{"text":"Decline","type":"response"},{"link":"https:\/\/www.stackoverflow.com","text":"Website","type":"info"}] 

...然而,返回以下錯誤:

Could not cast value of type '__NSCFString' (0x1a7c28d50) to 'NSArray' (0x1a7c297c8)

這裏的最終目標是簡單地去行動的每一個單獨的,即:

{"text":"Confirm","type":"response"}

{"text":"Decline","type":"response"

等...

確實斯威夫特有map功能。 FYI Im來自Java和JavaScript世界... swiftyjson似乎有點重一個循環。

謝謝,並一如既往的幫助和指導表示讚賞!

編輯:

這是通過傳遞給函數sender帕拉姆打印:

sender: [AnyHashable("title"): title!, AnyHashable("message"): message, AnyHashable("message_id"): 0:1503511875428318%03300c3203300c32, AnyHashable("id"): 1497708240713, AnyHashable("actions"): [{"text":"Confirm","type":"response"},{"text":"Decline","type":"response"},{"link":"https:\/\/www.notifyd.com","text":"Website","type":"info"}], AnyHashable("aps"): { 
    "content-available" = 1; 
}] 
+1

Swift does have map – ryantxr

+0

這個問題很混亂。請清楚顯示'print(「YES \(result)」)的輸出。 – rmaddy

+0

不,我仍然無法循環嵌套的字典。 「Swift是否有地圖功能」是一個替代選擇的建議,而不是問題。 – studiobrain

回答

3

你想解碼JSON字符串,然後轉換爲詞典的數組:

if 
    // cast sender["actions"] to String 
    let actionsString = sender["actions"] as? String, 
    // decode data of string and then cast to Array<Dictionary<String, String>> 
    let actionsStringData = actionsString.data(using: .utf8), 
    let result = try JSONSerialization.jsonObject(with: actionsStringData, options: []) as? [[String : String]] { 

    print("YES \(result)") 

    for action in result { 
     print(action) 
    } 
} 
+2

你不需要'如果讓'兩次。 – ryantxr

+1

'if let result = sender [「actions」] as? [[String:String]]' – ryantxr

+0

這似乎是正確的(最終),但它不能解釋錯誤消息。問題中的假設輸出意味着這個答案是正確的,但錯誤消息指出'result'實際上是一個'String',而不是一個字典數組。這個問題似乎是矛盾的。 – rmaddy

0

這真的是你在這裏得到的是一個未解碼的JSON字符串嗎?在這種情況下,斯威夫特4使這真的很容易:

struct S : Decodable { 
    let link : String? 
    let text : String 
    let type : String 
} 

if let acts = sender["actions"] as? String { 
    let data = acts.data(using: .utf8)! 
    if let arr = try? JSONDecoder().decode(Array<S>.self, from: data) { 
     arr.forEach {print($0)} 
    } 
} 

/* 
S(link: nil, text: "Confirm", type: "response") 
S(link: nil, text: "Decline", type: "response") 
S(link: Optional("https://www.stackoverflow.com"), text: "Website", type: "info") 
*/ 
+0

看起來比替代品更清潔。不幸的是,這是一個反應原生的應用程序,我不相信本機模塊部分(swift)將支持3以上(我沒有實際研究過,但事實如此)。 – studiobrain

0

這裏的數據有點可疑。讓我們更仔細地處理數據。以下是從JSON對象,JSON數組,數據對象或字符串獲取JSON的方法。

enum JsonError: Error { case notJson; case notJsonArray } 

func json(from any: Any?) throws -> Any { 
    if let json = any as? [String: Any] { return json } 
    if let json = any as? [Any] { return json } 

    if let data = any as? Data { 
     return try JSONSerialization.jsonObject(with: data) 
    } 

    if let string = any as? String, let data = string.data(using: .utf8) { 
     return try JSONSerialization.jsonObject(with: data) 
    } 

    throw JsonError.notJson 
} 

現在,我對JSON對象更加小心,我應該得到我想要的或知道更多關於錯誤的信息。

func showNotification(_ sender: [AnyHashable: Any]) { 
    do { 
     guard let result = try json(from: sender["actions"]) as? [Any] else { 
      throw JsonError.notJsonArray 
     } 

     print("YES \(result)") 

     for action in result { 
      print("Action: \(action)") 
     } 
    } catch { 
     // Do Something 
    } 
}