2015-09-04 77 views
0

Swift超級新手,請耐心等待。錯誤:'_'不能轉換爲'StringLiteralConvertible'

我在REPL,施展出了我認爲是一個簡單的數據結構,如下:

var stuff = [ 
    [ 
     "id" : "A9AD6748-62A1-47E9-B0F7-2CF9B9C138EE", 
     "label" : "My Cool Label", 
     "things" : [ 
      "1st string", 
      "2nd string", 
      "3rd string" 
     ] 
    ], 
    [ 
     "id" : "9C7882A7-E40C-421F-BEDB-8C0249A768E3", 
     "label" : "Another Cool Label", 
     "things" : [ 
      "4th string", 
      "5th string", 
      "6th string" 
     ] 
    ] 
] 

斯威夫特抱怨它以下列方式:

repl.swift:72:13: error: '_' is not convertible to 'StringLiteralConvertible' 
      "id" : "A9AD6748-62A1-47E9-B0F7-2CF9B9C138EE", 
      ^~~~ 
repl.swift:70:17: error: type of expression is ambiguous without more context 
    var stuff = [ 
       ^

我不沒辦法。我的代碼中沒有_。是混合類型(字符串和數組)的問題?

什麼是創建這種結構的正確方法?

+1

在這種情況下,'_'是指未知的推斷類型。 – porglezomp

回答

2

你猜這個問題來自你的字典中混合類型是絕對正確的。您看到的'_'是指未知的推斷類型。 Swift無法弄清楚你的代碼中有什麼類型的stuff,所以你必須讓它更清楚。 處理這個問題的快速和骯髒的方法是斷言你的字典可以容納任何東西。

> let x = ["one": 1, "two": "2"] 
repl.swift:7:27: error: '_' is not convertible to 'UnicodeScalarLiteralConvertible' 
> let x : [String: Any] = ["one": 1, "two": "2"] 
x: [String : Any] = 2 key/value pairs { ... } 

的原因,雨燕不會爲你做這是斯威夫特永遠不會推斷Any型,並有很好的理由。如果這樣做,它會使大多數類型的錯誤不會出現。所以你可以強制斯威夫特使用Any類型,如果你想......

但你可能不應該。如果您使用的是Any,則會損失相當多的類型安全。處理這個問題的最佳方法是創建一個enum以保存您想要的不同類型。通過這種方式,您可以將列表限制爲只包含您期望的內容。如果我們定義如下所示的枚舉:

enum Thing { 
    case AnInt(Int); 
    case AString(String); 
} 

我們可以定義一個列表,只是稍微囉嗦了,斯威夫特就能夠正確地推斷出整個表達式的類型,並提供我們更多的安全性。

> let x = ["one": Thing.AnInt(1), "two": Thing.AString("2")] 
x: [String : Thing] = 2 key/value pairs { ... } 

你舉的例子可以使用一個枚舉像這樣

enum ListOrString { 
    case AString(String); 
    case AList([String]); 
} 

而且你可以寫你的字典裏是這樣的:

var stuff = [ 
    [ 
     "id" : ListOrString.AString("A9AD6748-62A1-47E9-B0F7-2CF9B9C138EE"), 
     "label" : .AString("My Cool Label"), 
     "things" : .AList([ 
      "1st string", 
      "2nd string", 
      "3rd string" 
     ]) 
    ], 
    [ 
     "id" : .AString("9C7882A7-E40C-421F-BEDB-8C0249A768E3"), 
     "label" : .AString("Another Cool Label"), 
     "things" : .AList([ 
      "4th string", 
      "5th string", 
      "6th string" 
     ]) 
    ] 
] 

請注意,您只需要指定一次ListOrString,和那個時間你可以用一個裸的.。鍵入這個,我斯威夫特REPL正確推斷類型

stuff: [[String : ListOrString]] 
+0

這太棒了!錯別字:你從'ListOrString'轉到'StringOrList',你的'enum'需要'case'在每個聲明之前。否則,這正是我需要知道的。謝謝! –

+1

謝謝,這就是我重新鍵入我的REPL工作而不是複製粘貼它。 – porglezomp

0

這是「正確」的方式來創建這樣的數據結構,但你應該儘量讓類型更加明確通過指定所需的類型或使用結構模型。

在遊樂場中,類型被推斷爲[NSDictionary],但您應該使用如Swift這樣的靜態語言使用[[String : AnyObject]]

但是這兩種類型都不適用於REPL。所以作爲解決方法,您可以使用[[String : Any]]。這可能是因爲它不能推斷橋接標準類型。

相關問題