У меня есть следующий словарь:
let myDict: [String: Any] = [
"first": [
"message": "qqq",
"extras": ["task": "first"]
],
"second": [
"message": "www",
"extras": ["task": "second"]
],
"third": [
"message": "eee",
"extras": ["task": "third"]
],
]
Обратите внимание, как это обозначено как [String: Any]
. Тем не менее, Swift, похоже, жалуется, что сами ключи не аннотированы:
/tmp/example.swift:2:12: warning: heterogeneous collection literal could only be inferred to '[String : Any]'; add explicit type annotation if this is intentional
"first": [
^
/tmp/example.swift:6:13: warning: heterogeneous collection literal could only be inferred to '[String : Any]'; add explicit type annotation if this is intentional
"second": [
^
/tmp/example.swift:10:12: warning: heterogeneous collection literal could only be inferred to '[String : Any]'; add explicit type annotation if this is intentional
"third": [
^
Можно ли вообще аннотировать ключи словаря? Что удовлетворило бы Свифта в этой ситуации?
Кажется, это работает для меня без каких-либо предупреждений. Это может быть какая-то проблема с общими скобками или что-то в этом роде. Можете ли вы поделиться всем файлом здесь?
@nutz Обновите свой Xcode.
Вы неправильно читаете предупреждение. Компилятор говорит о значении, а не о ключе. Проблема в том, что эти значения сами по себе являются разнородными словарями:
[
"message": "qqq",
"extras": ["task": "first"]
]
Это словарь со строковыми ключами, но значениями двух разных типов. Таким образом, это [String: Any]
. Итак, вам нужно сказать, что:
let myDict: [String: [String: Any]] = [
В качестве альтернативы вы можете записать это в общей нотации:
let myDict: Dictionary<String, Dictionary<String, Any>> = [
Может показаться, что компилятор здесь излишне придирчив, но идея в том, что ранее компилятор делал предположение, пытаясь вывести здесь тип, и получение такого предположения дорого обходится. На самом деле вывод типов стоит дорого, за исключением самых простых случаев. Литералы массивов и словарей всегда стоит аннотировать явно, потому что в противном случае компилятору придется просматривать каждый отдельный элемент. (Если их достаточно, компилятор сдастся с жалобой на то, что он не может вывести тип за разумное время; возможно, вы видели эту ошибку.) Таким образом, чем больше времени вы можете потратить на аннотирование ваших типов, тем что компилятору не нужно их выводить, тем быстрее ваше приложение будет компилироваться в Xcode.
Для полноты предупреждение, показанное в Xcode, имеет «исправление», которое изменит строку на "first": [ "message": "qqq", "extras": ["task": "first"]] as [String: Any]
. Четко объявить myDict: [String: [String: Any]]
лучше.
Спасибо за подробное объяснение. Просто чтобы было абсолютно ясно, вы говорите, что этот удар по производительности влияет только на время компиляции, а не на время выполнения, верно? Я буду иметь это в виду. Я делал небольшие CLI-приложения, так что это пока не проблема.
Да, но лучше завести хорошие привычки. И независимо от производительности Swift движется к отмене «случайного Any». Это предупреждение будет ошибкой в Swift 6. Итак, давайте будем готовы.
[String: [String: Any]]
можно?