Присвоение свойства массива всегда приводит к сбою 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)
]

(Такая же техника необходима для типов протоколов.)

Другие вопросы по тегам