Interface Builder, @IBOutlet and protocols for delegate and dataSource in Swift

和自甴很熟 提交于 2019-12-17 18:22:17

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!