How to connect delegate from custom class in xib?

Matthieu luci picture Matthieu luci · Nov 19, 2015 · Viewed 7.1k times · Source

I have created a class "DeletableImageView" (.swift + .xib) which uses the protocol I defined as "DeletableImageViewDelegate" through a property I called delegate.

Example for sake of clarity:

DeletableImageView.swift

protocol DeletableImageViewDelegate {
    func deleteImageWithTag(tag: Int!) -> (Bool)
    func addImageOnViewWithTag(tag: Int!) -> (Bool)
    ...
}

class DeletableImageView: UIView {

    var view: UIView!
    var delegate: DeletableImageViewDelegate?

    // Some random methods + some use of the delegate protocol's methods
    ...
}

My problem is that now, when I try to use my class in a controller from the associated .xib file (which means that I drag and drop a view in interface builder and assign the DeletableImageView class to this view) I cannot link the delegate property (even if I declare this property as an IBOutlet).

What I want to be able to do is to directly link the view's delegate outlet to the "File's Owner" in the .xib

The exact same thing you do when you link datasource and delegate from a tableview directly in the .xib file.

But when I control-drag they won't link together.

Does anyone have any idea of what is happening ?

Thank you very much.

Answer

Said Sikira picture Said Sikira · Nov 19, 2015

First thing you need to do is to add @objc in from of your protocol definition, so that it looks like:

@objc protocol DeletableImageViewDelegate {
    ...
}

You might ask why do you need to do this. It's because you want to add delegate property to the storyboard, and in order to set some property visible by storyboard, it must have @IBOutlet prefix, and that prefix requires it to be Objective C protocol.

So the next thing you want to do is change var delegate: DeletableImageViewDelegate? to

@IBOutlet var delegate: DeletableImageViewDelegate?

Now if you right click on the view in the interface builder you will get something like this, which means that we exposed our delegate property to the interface builder. Exposed property

If you try to connect it to file owner (for example UIViewController), it will not work because your file owner still doesn't implement that protocol. To implement it you need to write:

extension UIViewController : DeletableImageViewDelegate {
    // Implementation
}

After you do that, you should be able to connect delegate property to the view controller, thus receiving delegate method messages. In each case your file owner must implement the protocol.