Jef
Jef

Reputation: 4728

Altering (refining) delegate type in swift

I have a (swift) class which has a weak pointer to a delegate like this:

import UIKit


@objc public protocol DRSlidingPanelViewControllerDelegate : class {

    optional func didSlidePanel(panelHidden : Bool , sender : DRSlidingPanelViewController) -> Void

} 

public class DRSlidingPanelViewController: UIViewController {

    public weak var delegate : DRSlidingPanelViewControllerDelegate?

///other stuff...
}

Now i make a subclass with another protocol which extends the first, and i want to alter the inherited 'delegate' property

@objc public protocol  DRTableViewControllerDelegate : DRSlidingPanelViewControllerDelegate  {

    optional func someFunction(sender : DRTableViewController) -> Void
}


public class DRTableViewController: DRSlidingPanelViewController {

 //  public weak var delegate : DRTableViewControllerDelegate?
}

^ this (re)declaration of delegate in the subclass gives me 3 errors when I uncomment it.

  1. Property 'delegate' with type 'DRTableViewControllerDelegate?' (aka 'Optional') cannot override a property with type 'DRSlidingPanelViewControllerDelegate?' (aka 'Optional')
  2. Getter for 'delegate' with Objective-C selector 'delegate' conflicts with getter for 'delegate' from superclass 'DRSlidingPanelViewController' with the same Objective-C selector
  3. Setter for 'delegate' with Objective-C selector 'setDelegate:' conflicts with setter for 'delegate' from superclass 'DRSlidingPanelViewController' with the same Objective-C selector

Now i understand the nature of these errors, and that they are different facets of the one error (attempting to change the 'type' on the delegate pointer.) Can anybody give me a clue how to do this? It obviously can be done, look at how UITableView alters the delegate pointer which it inherits from UIScrollView. In objC I would get a warning which could be silenced with an @dynamic. Thanks and best regards

edit / addition Thanks Matt, I do see this previous question, but unfortunately it is closed and I would personally not accept that answer as the definitive answer because it is a compromise.

If I right click on UITableView in xCode and 'jump to definition' I see this

@available(iOS 2.0, *)
public class UITableView : UIScrollView, NSCoding {

    public init(frame: CGRect, style: UITableViewStyle) // must specify style at creation. -initWithFrame: calls this with UITableViewStylePlain
    public init?(coder aDecoder: NSCoder)

    public var style: UITableViewStyle { get }
    weak public var dataSource: UITableViewDataSource?
    **weak public var delegate: UITableViewDelegate?**

//plenty other stuff..
}

So I respectfully submit that there definitely is a way to do this.

Upvotes: 3

Views: 548

Answers (1)

matt
matt

Reputation: 535889

I would say that as things stand you can't do it. This is disappointing to say the least. You'll just have to call the delegate variable in the subclass something else.

So, this is legal, but of course it totally fails to meet your requirements:

@objc protocol P1 {
}
@objc protocol P2 : P1 {
}
public class VC1: UIViewController {
    weak var delegate : P1?
}
public class VC2: VC1 {
    weak var delegate2 : P2?
}

If you really hate the multiplication of storage you can make the delegate2 a computed variable that accesses the inherited delegate:

@objc protocol P1 {
}
@objc protocol P2 : P1 {
}
public class VC1: UIViewController {
    weak var delegate : P1?
}
public class VC2: VC1 {
    weak var delegate2 : P2? {
        set {
            super.delegate = newValue
        }
        get {
            return super.delegate as? P2
        }
    }
}

Upvotes: 3

Related Questions