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 {}
не работает.
Кто-нибудь натолкнулся на что-то подобное?
Ответы
Ответ 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 }
Ответ 4
Элегантное обходное решение:
#if TARGET_INTERFACE_BUILDER
@IBOutlet open weak var delegate: AnyObject?
#else
open weak var delegate: CustomViewDelegate?
#endif
См:
https://github.com/WenchaoD/FSPagerView/blob/master/Sources/FSPagerView.swift#L88
Ответ 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
работала как шарм.