Невозможно преобразовать Array‹Codable› в Codable

Учитывая, что Array соответствует Codable, я предполагаю, что массив Codable, т.е. [Codable], определенно должен быть приведен к Codable. Я сделал простой пример только с частью Decodable. И просто для проверки:

// Attempt to conform Array to Decodable
extension Array : Decodable { }

Это вызывает предупреждение: Conformance of 'Array<Element>' to protocol 'Decodable' conflicts with that stated in the type's module 'Swift' and will be ignored; there cannot be more than one conformance, even with different conditional bounds

Что имеет смысл, поскольку Array уже соответствует Decodable.

// Totally decodable array
var array: [Decodable] = ["Decodable", "strings"]

// Attempt to cast the decodable array
var decodable: Decodable = array

Это вызывает ошибку компилятора: Value of type [Decodable] does not conform to specified type 'Decodable'

И FixIt: Insert 'as! Decodable'

Применение FixIt вызывает ошибку времени выполнения: Could not cast value of type 'Swift.Array<Swift.Decodable>' (0x11f84dd08) to 'Swift.Decodable' (0x11f84db18).

Я использую Xcode 10 на macOS 10.14.

Так что я делаю неправильно здесь?

РЕДАКТИРОВАТЬ: я только что попробовал Xcode 9.2, и тот же пример работает нормально. Итак, возникает вопрос, почему это больше не работает в Xcode 10 и что я должен делать вместо этого? Нигде не могу найти ссылку на это изменение.


person user614273    schedule 21.10.2018    source источник
comment
Пожалуйста, сначала скажите, что вы хотите сделать; какой JSON вы хотите декодировать?   -  person meaning-matters    schedule 21.10.2018
comment
@meaning-matters В данном случае это будут строки Decodable и strings. Дело не в этом. Я уже знаю, какими будут декодированные данные. Вы можете заменить каждое вхождение Decodable в примере на Encodable и получить те же ошибки. Дело в том, что код не компилируется. @vadian [Decodable] означает Array<Decodable>, что означает Array, где Element равно Decodable. Расширение было просто для демонстрации того, что Array действительно уже соответствует Decodable, требованием которого, как вы указываете, является то, что его универсальный Element соответствует Decodable.   -  person user614273    schedule 21.10.2018


Ответы (1)


В соответствии с законами условного соответствия, вступившими в силу в Swift 4.2:

  • Массив некоторого типа (класс, структура или перечисление), который соответствует Decodable, является декодируемым.

  • Массив протокола не декодируется, потому что протокол не соответствует себе.

(Что происходило до Swift 4.2, так это то, что условного соответствия не существовало, и мы просто получали своего рода универсальный проход; вы могли рассматривать любой массив как декодируемый, и вы не сталкивались с проблемой до времени выполнения. если вы были неправы. Теперь, с условным соответствием, компилятор фактически смотрит на тип элемента.)

person matt    schedule 21.10.2018
comment
Приятно иметь некоторую ясность, я принял ваш ответ. Теперь, поскольку это отлично работало в предыдущих версиях (и я имею в виду, что код не просто компилировался, он работал во время выполнения), должно быть какое-то простое решение, чтобы добиться такого же поведения? - person user614273; 22.10.2018
comment
Я добавлю небольшое пояснение к моему ответу. - person matt; 22.10.2018