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?
3 réponses
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{
}
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!
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
}
}
De nouvelles questions
swift
Swift est un langage de programmation polyvalent sûr, rapide et expressif développé par Apple Inc. pour ses plateformes et Linux. Swift est open-source. Utilisez la balise uniquement pour les questions sur les fonctionnalités linguistiques ou nécessitant du code dans Swift. Utilisez les balises [ios], [ipados], [macos], [watch-os], [tvos], [cocoa-touch] et [cocoa] pour les questions (indépendantes du langage) sur les plates-formes ou les frameworks.