问题
Can't connect delegate property of CustomView
declared as @IBOutlet toViewController
in Interface Builder – simply can't establish a connection.
Here's the code
class CustomView: UIView {
@IBOutlet var delegate: CustomViewDelegate?
}
@objc protocol CustomViewDelegate {
...
}
class ViewController: UIViewController, CustomViewDelegate {
...
}
@objc
is used because of swift protocol, IBOutlet property cannot have non-object type, don't know why protocol CustomViewDelegate: class {}
doesn't work.
Anyone else came across something like that?
回答1:
From the Xcode release notes:
Interface Builder does not support connecting to an outlet in a Swift file when the outlet’s type is a protocol.
Workaround: Declare the outlet's type as AnyObject or NSObject, connect objects to the outlet using Interface Builder, then change the outlet's type back to the protocol.
EDIT: Xcode 9 beta 3 release notes say that this workaround should no longer be necessary.
回答2:
Adam Waite provides a nice workaround. I however prefer the following solution as it emphasizes the workaround and the extra property can also easily be removed once Xcode gets fixed.
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 {
...
}
Hey, is this bug already one and a half years old?
回答3:
An elegant workaround:
#if TARGET_INTERFACE_BUILDER
@IBOutlet open weak var delegate: AnyObject?
#else
open weak var delegate: CustomViewDelegate?
#endif
See: https://github.com/WenchaoD/FSPagerView/blob/master/Sources/FSPagerView.swift#L88
回答4:
Another that's not pretty but:
@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:
This is an old thread, but I thought I'd point out that as of Xcode 9 beta 3, it is now possible to connect a custom delegate written in swift to interface builder.
According to the release notes
Interface Builder now recognizes outlets, actions, and inspectable properties declared on classes which have a Swift protocol extension. (22201035)
// Can connect this to interface builder now
class MyViewController: UIViewController {
@IBOutlet weak var myDelegate: TheNewDelegate?
}
回答6:
For me, the reason was the table view was nil
at the point I attempted to set it's datasource and delegate. This was due to the designated initializer calling initWithNibName:bundle:
which does not guarantee initialized connections. Deferring my delegate and datasource setting to viewDidload
worked like a charm.
来源:https://stackoverflow.com/questions/26180268/interface-builder-iboutlet-and-protocols-for-delegate-and-datasource-in-swift