Присвоение свойства массива всегда приводит к сбою EXC_BAD_ACCESS
Я не могу понять, почему следующий код каждый раз падает на Xcode 6 GM, используя Swift. Не могли бы вы помочь мне понять эту проблему?
Заранее спасибо.
OptionsToSelect.swift
import Foundation
struct OptionToSelect {
var value : Any
var desc : String
var available : Bool
}
SomeClass.swift
import Foundation
class SomeClass {
var items = Array<OptionToSelect>()
}
ViewController.swift
override func viewDidLoad() {
super.viewDidLoad()
var c = SomeClass()
c.items = [ /// <------------- __ EXC_BAD_ACCESS here, why?! __
OptionToSelect(value: 1, desc: "A", available: true),
OptionToSelect(value: 2, desc: "B", available: true)
]
}
Редактировать 1 В твиттере я получил ответ, что это связано с Any
, и действительно. Но почему?
1 ответ
Компилятор все еще имеет различные проблемы с Any
поэтому короткий ответ - "ошибка в Swift". Это также имеет проблемы, если value
это протокол. Я подозреваю, что ему трудно понять, как сделать копию; но это предположение
Но вы должны строго избегать использования Any
Вот. Вы почти никогда не должны использовать Any
, В большинстве случаев вы хотите универсальный:
struct OptionToSelect<T> {
let value : T
let desc : String
let available : Bool
}
(То, как вы используете это, let
кажется более подходящим, чем var
Вот; вам действительно нужно изменить эти значения?)
Это требует, чтобы весь массив имел одинаковые значения:
var items = [OptionToSelect<Int>]()
Но это обычно правильно в любом случае. Если это не так; если вам нужно сочетание значений, вам следует подумать, какому протоколу могут соответствовать все значения. Это на самом деле не решит вашу проблему (Swift тоже будет зависать при протоколе), но дизайн будет намного лучше, чем Any
, Если лучшее, что вы можете сказать о типе: "ну, это что-то", то вы получите много сложного (а иногда и опасного) кода, понижающего рейтинг. Вы будете бороться с этим каждый раз, когда вы поворачиваетесь.
Чтобы использовать протокол здесь (или Any
) вы можете сделать OptionToSelect
класс (это самый простой ответ) или скрыть проблему в поле:
struct OptionToSelect {
let value : AnyBox
let desc : String
let available : Bool
}
final class AnyBox {
let value: Any
init (_ value: Any) { self.value = value }
}
[
OptionToSelect(value: AnyBox(1), desc: "A", available: true),
OptionToSelect(value: AnyBox(2), desc: "B", available: true)
]
(Такая же техника необходима для типов протоколов.)