Ответ 1
Я нашел решение. Это довольно... неудовлетворительно, но это работает. Где я устанавливаю массив на контроллере представления назначения, я делаю:
destinationViewController.options = options.map({$0 as Option})
Я объявил протокол Swift:
protocol Option {
var name: String { get }
}
Я объявляю несколько реализаций этого протокола - некоторые классы, некоторые перечисления.
У меня есть контроллер представления с объявленным как свойство:
var options: [Option] = []
Когда я пытаюсь установить это свойство в массив объектов, реализующих протокол Option
в другом VC prepareForSegue
, я получаю ошибку времени выполнения:
fatal error: array cannot be bridged from Objective-C
Почему это не работает? Компилятор имеет всю необходимую ему информацию, и я не понимаю, что с этим связано Objective-C - мой проект содержит только файлы Swift, и эти массивы не входят в какие-либо фреймворки, необходимо, чтобы их соединили до NSArray
.
Я нашел решение. Это довольно... неудовлетворительно, но это работает. Где я устанавливаю массив на контроллере представления назначения, я делаю:
destinationViewController.options = options.map({$0 as Option})
компилятор знает, что я передаю в Массив вещи, которые реализуют Option
Вы позволили сделать там очень показательное замечание, которое предлагает источник проблемы. "Массив объектов, реализующих опцию", не является массивом опций.
Проблема заключается в типе options
назад в том месте, где вы его создали (в prepareForSegue
). Вы не показываете этот код, но я держу пари, что вы не можете использовать/набирать его в этот момент. Вот почему неудача назначается. options
может быть массивом вещей, которые на самом деле происходят с опцией Option, но этого недостаточно; его необходимо ввести в виде массива Option.
Итак, вернемся в prepareForSegue
, сформируйте ваш options
следующим образом:
let options : [Option] = // ... whatever ...
Теперь вы сможете назначить его непосредственно destinationViewController.options
.
Вот быстрый тестовый пример (на игровой площадке, я ненавижу игровые площадки, но они могут использовать их):
protocol Option {
var name : String {get}
}
class ViewController : UIViewController {
var options : [Option] = []
}
enum Thing : Option {
var name : String {
get {
return "hi"
}
}
case Thing
}
let vc = ViewController()
let options : [Option] = [Thing.Thing]
vc.options = options // no problem
(Я также тестировал это в реальном приложении с фактическим prepareForSegue
, и он отлично работает.)
У меня была такая же проблема, и я исправил ее, отметив мой протокол @objc
, в вашем случае это будет выглядеть как
@objc protocol Option {
var name: String { get }
}
Получено решение из этого ответа
Этот тоже отлично работает
destinationViewController.options = options.map{$0}