Подтвердить что ты не робот

Interface Builder, @IBOutlet и протоколы для делегата и dataSource в Swift

Невозможно связать свойство делегата CustomView, объявленное как @IBOutlet, с ViewController в Interface Builder - просто не удается установить соединение.

Здесь код

class CustomView: UIView {
     @IBOutlet var delegate: CustomViewDelegate?
}

@objc protocol CustomViewDelegate {
     ...
}


class ViewController: UIViewController, CustomViewDelegate {
     ...
}

@objc используется в связи с быстрым протоколом, свойство IBOutlet не может иметь тип без объекта, не знаю, почему protocol CustomViewDelegate: class {} не работает.

Кто-нибудь натолкнулся на что-то подобное?

4b9b3361

Ответ 1

Из примечаний к выпуску Xcode:

Интерфейс Builder не поддерживает подключение к розетке в файле Swift, когда тип выходов является протоколом.

Обходной путь: объявите тип розетки как AnyObject или NSObject, подключите объекты к розетке с помощью Interface Builder, затем измените тип розетки обратно на протокол.

EDIT: Xcode 9 beta 3 отмечает, что это обходное решение больше не нужно.

Ответ 2

Адам Уэйт обеспечивает приятное обходное решение. Однако я предпочитаю следующее решение, поскольку оно подчеркивает обходное решение, а дополнительное свойство также можно легко удалить после исправления Xcode.

class CustomView: UIView {
    @IBOutlet
    public var delegate: CustomViewDelegate?

    /// Workaround for Xcode bug that prevents you from connecting the delegate in the storyboard.
    /// Remove this extra property once Xcode gets fixed.
    @IBOutlet
    public var ibDelegate: AnyObject? {
        get { return delegate }
        set { delegate = newValue as? CustomViewDelegate }
    }

    func someMethod() {
        // Here we always refer to `delegate`, not `ibDelegate`
        delegate?.onSomethingHappened()
    }
}

@objc protocol CustomViewDelegate {
    ...
}

Эй, эта ошибка уже полтора года?

Ответ 3

Другой, что не очень, но:

@IBOutlet weak var ibDelegate: NSObject?
@IBOutlet weak var ibDataSource: NSObject?
var delegate: MultipleButtonViewDelegate? { return ibDelegate as? MultipleButtonViewDelegate }
var dataSource: MultipleButtonViewDataSource? { return ibDataSource as? MultipleButtonViewDataSource }

Ответ 5

Это старый поток, но я думал, что хочу отметить, что с Xcode 9 beta 3 теперь можно подключить пользовательский делегат, написанный в быстром интерфейсе.

В соответствии с примечаниями к выпуску

Интерфейс Builder теперь распознает выходы, действия и проверяемые свойства, объявленные на классах с расширением протокола Swift. (22201035)

// Can connect this to interface builder now    
class MyViewController: UIViewController {
    @IBOutlet weak var myDelegate: TheNewDelegate?
}

Ответ 6

Для меня причиной было представление таблицы было nil в том месте, где я попытался установить его источник данных и делегировать. Это произошло из-за назначенного инициализатора, вызывающего initWithNibName:bundle:, который не гарантирует инициализированные подключения. Отмена настройки моего делегата и источника данных на viewDidload работала как шарм.