3

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.

Community
  • 1
  • 1
Jef
  • 4,728
  • 2
  • 25
  • 33
  • 1
    Pretty well covered here: http://stackoverflow.com/questions/31839512/overriding-a-superclass-delegate-in-swift It's definitely a problem! – matt Feb 21 '16 at 01:14
  • 1
    Interesting discussion here too: http://stackoverflow.com/questions/24094158/overriding-superclass-property-with-different-type-in-swift – matt Feb 21 '16 at 01:18
  • 1
    Yeah, but the underlying code is written in Objective-C. You're just looking at a Swift API translation. So you can't actually _do_ this _in_ Swift, is what I'm saying. I'd love to be wrong but I don't think I am... – matt Feb 21 '16 at 01:35

1 Answers1

3

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
        }
    }
}
matt
  • 515,959
  • 87
  • 875
  • 1,141
  • I really appreciate your input but I'm going to give you a +1 rather than an accept because I know there is a way. I remain a fan, best – Jef Feb 21 '16 at 01:30
  • I see another compromise, I could alter my DRTableViewControllerDelegate protocol to an extension on DRSlidingPanelViewControllerDelegate but I think that will force me to use only optional functions – Jef Feb 21 '16 at 01:32
  • 1
    You are totally right not to accept! This is bad news. – matt Feb 21 '16 at 01:32
  • 1
    But I do not believe there is a way; look at the links I gave you. It appears we've been up and down this road already. :( See my revised answer; it's no better but it's sort of cute. – matt Feb 21 '16 at 01:33
  • I do like that and was thinking similar - but private and read only, just a getter which conditionally typecasts the existing delegate pointer. Cheers mate – Jef Feb 21 '16 at 07:39
  • I'd like to see what you come up with! Thanks – matt Feb 21 '16 at 17:13