Быстрая ошибка словаря?

Итак, я начал проект в Swift, и я пришел к этой проблеме:

этот код работает:

var dictionary = ["a":"valueOfA","b":"valueOfB","c":"valueOfC"]
println(dictionary)
dictionary["c"] = "newValOfC"
println(dictionary)

и это не так:

var dictionary = [:]
dictionary = ["a":"valueOfA","b":"valueOfB","c":"valueOfC"]
println(dictionary)
dictionary["c"] = "newValOfC"
println(dictionary)

Дает ошибку:

Playground execution failed: error: <REPL>:35:17: error: cannot assign to the result of this expression
dictionary["c"] = "newValC"
~~~~~~~~~~~~~~~ ^

Обратите внимание, что это не постоянное значение

Так почему же строка

dictionary = ["a":"valueOfA","b":"valueOfB","c":"valueOfC"]

введите ошибку?

Ответ 1

Поскольку контекст не предоставляет достаточной информации для вывода типа, вам нужно явно называть его как словарь, иначе swift предполагает, что это NSDictionary (я не понимаю, почему. лучше совместимость с OBJC):

Работает следующий код:

// Playground
import UIKit

var str:NSString = "Hello, playground"

var d0 = [:]
var d1: Dictionary = [:]

d0.setValue(UIWebView(), forKey: "asdf")

d1["asdf"] = 1
d1["qwer"] = "qwer"

Ответ 2

Хорошо, я нашел его, проблема в том, что, инициализируя пустой словарь, вывод типа немного сумасшедший.

Вам понадобится этот код:

var dictionary = Dictionary<String, String>()

вместо

var dictionary = [:]

но это все еще не объясняет, почему строка

dictionary = ["a":"valueOfA","b":"valueOfB","c":"valueOfC"]

не дает ошибки

Ответ 3

И ссылаясь на Руководство по языку Swift,

dictionary = [:]
Синтаксис

правильный, если контекст уже предоставляет информацию о типе.

Ответ 4

Большая разница в том, что

var dictionary = [:]

не дает возможности компилятору вывести правильный тип, тогда как

var dictionary = ["a":"valueOfA","b":"valueOfB","c":"valueOfC"]

делает.

На самом деле, похоже, что первая строка создает экземпляр __NSDictionaryI, тогда как второй создает Dictionary<String,String, как ожидалось.

Из книги Swift Programming Language

Если контекст уже предоставляет информацию о типе, создайте пустой словарь с пустым словарным литералом, который написан как [:] (двоеточие внутри пары квадратных скобок):

что означает, что первая строка неоднозначна.

Ответ 5

Синтаксис [:] работает только в том случае, если в текущем контексте достаточно информации, чтобы иметь возможность выводить те типы. Вот несколько способов, которыми известен контекст...

Как уже упоминалось, приведенный ниже код работает, поскольку можно предположить, что ключи и значения являются строками:

var dictionary = [ "a" : "valueOfA" , "b" : "valueOfB" , "c" : "valueOfC" ]

Словарь, переданный в функцию, имеет известный контекст:

func dictionaryFunc(var dictionary : Dictionary<String, String>) {
    // Do stuff with the dictionary
}

В обоих случаях теперь известны ключи/значения для словаря, поэтому вы можете сделать это для создания нового словаря с тем же именем переменной...

dictionary = [:]

В первом случае, если вы использовали синтаксис [:] после объявления, вы бы удалили содержимое исходного словаря. Во втором случае словари копируются, когда они передаются в функции, поэтому использование [:] будет только стирать копию.

Ответ 6

В Swift 2.0 я использую это:

var dictionary = [String:String]()
dictionary["key1"] = "value1"