2015-09-04 2 views
0

Супер новый для Swift, поэтому, пожалуйста, несите меня.error: '_' не конвертируется в 'StringLiteralConvertible'

Я в РЕПЛ, пробуя то, что я думал, что простая структура данных, следующие:

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" 
     ] 
    ] 
] 

Swift жалуется на это следующим образом:

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 типа, и по уважительной причине. Если это произойдет, это приведет к появлению большинства ошибок типа. Поэтому вы можете заставить Swift использовать тип Any, если вы хотите ...

Но вы, вероятно, не должны. Если вы используете Any, вы теряете довольно много типов безопасности. Лучший способ справиться с этим - создать enum для хранения различных типов. Таким образом вы можете ограничить свой список только тем, что вы ожидаете. Если мы определим перечисление вроде следующего:

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

Мы можем определить список, только немного более многословным, и Swift будет иметь возможность правильно определить тип всего выражения, и дают нам большую безопасность.

> 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 один раз, и что каждый раз вы можете просто использовать голый .. Набрав это мой Swift РЕПЛ правильно выводит тип как

stuff: [[String : ListOrString]] 
+0

Это замечательно! Typos: вы переходите от 'ListOrString' к' StringOrList', а ваш 'enum' нужен' case' перед каждым объявлением. В противном случае это то, что мне нужно было знать. Спасибо! –

+1

Спасибо, это то, что я получаю за то, что просто перепечатал свою работу REPL вместо копирования в нее. – porglezomp

0

Это «правильный» способ создания такой структуры данных, но вы должны попытаться сделать вид менее двусмысленным либо путем указания требуемого типа или с использованием структуры для ее моделирования.

На игровой площадке предполагается, что тип [NSDictionary], но вы должны использовать [[String : AnyObject]] на таком статическом языке, как Swift.

Но ни один тип не работает в REPL. Итак, обходным путем вы можете использовать [[String : Any]]. Вероятно, это связано с тем, что он не может выводить стандартные типы.