Doug Smith Doug Smith - 2 months ago 47
Swift Question

In Swift, how do I have a UIScrollView subclass that has an internal and external delegate?

I'm subclassing

to add some features such as double tap to zoom and an image property for gallery purposes. But in order to do the image part my subclass has to be its own delegate and implement the

But then when someone uses my scroll view subclass, they might like to get delegate notifications as well to see
or what have you.

In Swift, how do I get both of these?


Here is a Swift version of this pattern:

Although forwardInvocation: is disabled in Swift, we can still use forwardingTargetForSelector:

class MyScrollView: UIScrollView {

    class _DelegateProxy: NSObject, UIScrollViewDelegate {
        weak var _userDelegate: UIScrollViewDelegate?

        override func respondsToSelector(aSelector: Selector) -> Bool {
            return super.respondsToSelector(aSelector) || _userDelegate?.respondsToSelector(aSelector) == true

        override func forwardingTargetForSelector(aSelector: Selector) -> AnyObject? {
            if _userDelegate?.respondsToSelector(aSelector) == true {
                return _userDelegate
            else {
                return super.forwardingTargetForSelector(aSelector)

        func viewForZoomingInScrollView(scrollView: MyScrollView) -> UIView? {
            return scrollView.viewForZooming()

        // Just a demo. You don't need this.
        func scrollViewDidScroll(scrollView: MyScrollView) {

    private var _delegateProxy =  _DelegateProxy()

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        super.delegate = _delegateProxy

    override init(frame: CGRect) {
        super.init(frame: frame)
        super.delegate = _delegateProxy

    override var delegate:UIScrollViewDelegate? {
        get {
            return _delegateProxy._userDelegate
        set {
            self._delegateProxy._userDelegate = newValue;
            /* It seems, we don't need this anymore.
            super.delegate = nil
            super.delegate = _delegateProxy

    func viewForZooming() -> UIView? {
        println("self viewForZooming")
        return self.subviews.first as? UIView // whatever

    func didScroll() {
        println("self didScroll")