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

后端 未结 4 1910
悲&欢浪女
悲&欢浪女 2020-12-14 11:24

I\'m subclassing UIScrollView 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 s

4条回答
  •  猫巷女王i
    2020-12-14 11:48

    I don't know about any 100% Swift solution for this. Taking this ObjC answer to the same problem, and trying to port it to Swift it turns out that is not possible since NSInvocation is not available in Swift.

    What we can do is to implement the suggested MyScrollViewPrivateDelegate in ObjC(don't forget to import it in the bridging header file) and the scroll view subclass in Swift like the following:

    MyScrollView.swift

    import UIKit
    
    class MyScrollView: UIScrollView {
    
        private let myDelegate = MyScrollViewPrivateDelegate()
    
        required init(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            super.delegate = myDelegate
        }
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            super.delegate = myDelegate
        }
    
        override var delegate: UIScrollViewDelegate? {
            set {
                myDelegate.userDelegate = newValue
                super.delegate = nil
                super.delegate = myDelegate
            }
    
            get {
                return myDelegate.userDelegate
            }
        }
    
        func viewForZooming() -> UIView {
            return UIView()// return whatever you want here...
        }
    }
    

    MyScrollViewPrivateDelegate.h

    #import 
    
    @interface MyScrollViewPrivateDelegate : NSObject 
    
    @property (weak, nonatomic) id userDelegate;
    
    @end
    

    MyScrollViewPrivateDelegate.m

    #import "MyScrollViewPrivateDelegate.h"
    #import "YOUR_MODULE-Swift.h"
    
    @implementation MyScrollViewPrivateDelegate
    
    - (UIView *)viewForZoomingInScrollView:(UIScrollView *)scrollView
    {
        // you could check if the user delegate responds to viewForZoomingInScrollView and call it instead...
        return [(MyScrollView *)scrollView viewForZooming];
    }
    
    - (BOOL)respondsToSelector:(SEL)selector 
    {
        return [_userDelegate respondsToSelector:selector] || [super respondsToSelector:selector];
    }
    
    - (void)forwardInvocation:(NSInvocation *)invocation 
    {
        [invocation invokeWithTarget:_userDelegate];
    }
    
    @end
    

提交回复
热议问题