Сбой IBDesignable EXC_BAD_ACCESS при попытке вызвать loadNibNamed

У меня есть базовый класс под названием DesignableControl. Я использую его в своих пользовательских представлениях, чтобы видеть их в раскадровке. Вот базовый класс:

public class DesignableControl: UIControl {

    private var view: UIView!

    override public init(frame: CGRect) {
        super.init(frame: frame)
        configureViewForStoryboard()
    }

    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        configureViewForStoryboard()
    }

    func configureViewForStoryboard() {
        if let nibView = NSBundle(forClass: self.dynamicType).loadNibNamed("\(self.dynamicType)", owner: self, options: nil).first as? UIView {
            view = nibView
        } else {
            Log("Error loading view for storyboard preview. Couldn't find view named \(self.dynamicType)")
            view = UIView()
        }
        view.frame = bounds
        view.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]
        backgroundColor = .clearColor()
        addSubview(view)
    }
}

Вот мой подкласс StackedButton:

class StackedButton: DesignableControl {
    @IBOutlet weak var imageView: UIImageView!
    @IBOutlet weak var imageViewHeightConstraint: NSLayoutConstraint!
    @IBOutlet weak var imageViewWidthConstraint: NSLayoutConstraint!
    @IBOutlet weak var label: UILabel!

    ...
}

Приведенный выше код работает и выглядит нормально, когда я запускаю приложение, однако, когда я просматриваю его в раскадровке, происходит сбой процесса Interface Builder с EXC_BAD_ACCESS в следующей строке в DesignableControl (выделено для ясности):

func configureViewForStoryboard() {
    let bundle = NSBundle(forClass: self.dynamicType)
    print("bundle: \(bundle)")
    let nibArray = bundle.loadNibNamed("\(self.dynamicType)", owner: self, options: nil)
    print("nibArray: \(nibArray)") //<-- EXC_BAD_ACCESS

    ...
}

Когда я впервые написал этот код, он работал, но, похоже, не работает в последней версии Xcode (7.2.1 на момент публикации). Что я делаю не так?


person Albert Bori    schedule 24.02.2016    source источник
comment
Похоже, что при работе в IB loadNobNamed(...) возвращает ноль. Глупая мысль, но проверьте, что self.dynamicType разрешается в одно и то же имя в обоих случаях.   -  person drekka    schedule 24.02.2016


Ответы (1)


Обновление:

Код начал падать при запуске, потому что представление не настраивалось должным образом. Оказывается, проблема с переполнением стека была отвлекающим маневром. Была ошибка в подклассе некоторых @IBDesignable свойств, которые обращались к @IBOutlets до того, как они были установлены. Это было корневой проблемой.

До:

@IBInspectable var text: String? {
    get { return label.text }
    set { label.text = newValue }
}

После:

@IBInspectable var text: String? {
    get { return label?.text }
    set { label?.text = newValue }
}

Исходный ответ:

Переполнение стека™!!!

loadNibNamed() вызывал один из конструкторов, который вызывал configureViewForStoryboard(), который вызывал один из конструкторов, который вызывал configureViewForStoryboard().

Я удалил вызов configureViewForStoryboard() из init?(coder aDecoder: NSCoder), и теперь он работает.

person Albert Bori    schedule 24.02.2016