J'ai le code suivant:

extension ViewController {


func AddLeftGesture(){
    let SwipeLeft:UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(MyDismissOnSwipeLeft))

    self.view.addGestureRecognizer(SwipeLeft)
}

func MyDismissOnSwipeLeft(){

    self.dismiss(animated: true, completion: nil)
}

Et ce que je voudrais accomplir, c'est que remplacer le viewDidLoad et appeler la méthode AddLeftGesture pour qu'elle fasse partie de chaque VC que je crée et je n'ai pas à le taper encore et encore dans chaque viewDidLoad,

Est-ce possible? ou avez-vous d'autres suggestions?

0
Asım Gündüz 19 avril 2017 à 22:59

3 réponses

Meilleure réponse

Eh bien, je ne pense pas que ce soit une bonne idée, car généralement viewDidLoad est utilisé pour définir la plupart des propriétés et si vous souhaitez le remplacer dans un contrôleur de vue, vous devez l'écrire à nouveau. une base ViewController et ajoutez ce code dans le viewDidLoad de celui-ci, puis sous-classez chaque viewController du contrôleur de vue de base, de cette façon chaque fois que vous voulez changer tout ce que vous appelez simplement super.viewDidLoad

class BaseViewController: UIViewController{

    override func viewDidLoad() {
        super.viewDidLoad()

        addLeftGesture()
    }
}


class CustomViewController: BaseViewController{

}
1
Alan 19 avril 2017 à 20:05

Rendre cette classe qui hérite de UITapGestureRecognizer

open class BlockTap: UITapGestureRecognizer {
    fileprivate var tapAction: ((UITapGestureRecognizer) -> Void)?

public override init(target: Any?, action: Selector?) {
    super.init(target: target, action: action)
}

public convenience init (
    tapCount: Int = 1,
    fingerCount: Int = 1,
    action: ((UITapGestureRecognizer) -> Void)?) {
        self.init()
        self.numberOfTapsRequired = tapCount

        #if os(iOS)
        self.numberOfTouchesRequired = fingerCount
        #endif

        self.tapAction = action
        self.addTarget(self, action: #selector(BlockTap.didTap(_:)))
}

open func didTap (_ tap: UITapGestureRecognizer) {
    tapAction? (tap)
}
}

Puis faites une extension de UIView

extension UIView {
        public func addTapGesture(tapNumber: Int = 1, action: ((UITapGestureRecognizer) -> ())?) {
            let tap = BlockTap(tapCount: tapNumber, fingerCount: 1, action: action)
            addGestureRecognizer(tap)
            isUserInteractionEnabled = true
        }
    }

Ensuite, vous pouvez l'utiliser comme

override func viewDidLoad() {
        super.viewDidLoad()
         self.view.addTapGesture(action: {[unowned self] (_) in
                //Do whatever on click of View
         })
}

J'espère que cela aide!

1
Agent Smith 20 avril 2017 à 07:11

Il y a deux options AFAIK. Soit vous pouvez sous-classer UIViewController puis faire hériter tous vos contrôleurs de celui sous-classe, soit vous pouvez swizzle UIViewController 's viewDidLoad().

Personnellement, je choisirais swizzling, même si cela présente un inconvénient: cela cache l'implémentation et peut être déroutant pour un nouveau développeur qui se lance dans un projet. Assurez-vous donc de documenter cela correctement, quelque part dans votre projet README et dans le code également.

Maintenant, pour quelques exemples de code:

Sous-classement UIViewController

MyViewController.swift

class MyViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()

        addGesture()
    }

    func addGesture() {
        // Do what you need
    }
}

class OtherViewController: MyViewController {
    // Automatically will add gesture because it's a subclass of  MyViewController
}

Swizzling viewDidLoad

Ce que fait le swizzling de méthode, c'est qu'il échange les implémentations de vos méthodes. Cela signifie simplement que le nom de votre fonction pointe sur le code d'une fonction différente. Pour plus d'informations sur ce sujet, lisez cet article.

UIViewController+Swizzle.swift

static func swizzle(selector originalSelector: Selector,
                    with newSelector: Selector,
                    on targetClass: AnyClass) {
    let originalMethod = class_getInstanceMethod(targetClass, originalSelector)
    let swizzledMethod = class_getInstanceMethod(targetClass, newSelector)

    // If we were able to add the swizzled function, replace methods.
    // Otherwise exchange implementations if method already exists.
    if class_addMethod(targetClass, originalSelector,
                       method_getImplementation(swizzledMethod),
                       method_getTypeEncoding(swizzledMethod)) {

        class_replaceMethod(targetClass, newSelector,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod))
    } else {
        method_exchangeImplementations(originalMethod, swizzledMethod)
    }
}

extension UIViewController {

    // This function is getting called automatically by the runtime, 
    // when this class is loaded to perform some additional intiialization. 
    // However, this has now been deprecated in Swift, so only option is to 
    // declare a static function which you need to remember to call from 
    // somewhere, preferably early in your app initialization, like your 
    // didFinishLaunching function in AppDelegate or even AppDelegate's init 
    // function. I kept the initialize function in the code as a reference, 
    // however you would probably want to write it like in the comment 
    // below, to silence the warning.
    //
    // class func swizzle()
    //
    open override class func initialize() {
        if self != UIViewController.self { return }

        let swizzlingClosure: () = {
            swizzle(selector: #selector(UIViewController.viewDidLoad),
                             with: #selector(UIViewController.swizzled_viewDidLoad),
                             on: UIViewController.self)
        }()

        swizzlingClosure
    }

    @objc private func swizzled_viewDidLoad() {
        // Calls the original implementation,
        // because implementations are switched.
        swizzled_viewWillAppear(animated)

        // Do whatever you need
        addGesture()
    }

    @objc func addGesture() {
        // Add your gesture
    }
}
0
Dominik Hadl 19 avril 2017 à 20:17