【问题标题】:iOS - How to be notified when visible (top) view controller is changediOS - 如何在可见(顶部)视图控制器更改时收到通知
【发布时间】:2018-01-12 19:48:20
【问题描述】:

我正在尝试构建一个推送模型来检测我的 iOS 应用中可见的视图控制器更改。

我知道我可以为所有 willDidAppear 方法设置一个侦听器或实现类似的委托方法。

例如:

- (void)navigationController:(UINavigationController *)navigationController didShowViewController:(UIViewController *)viewController animated:(BOOL)animated;

另外,我知道我可以听UINavigationControllerDidShowViewControllerNotification,但不是每个类都是UINavigationController 的子类。所以这可能不适合我。

我想知道有没有更简单、更强大的方法来实现目标? 谢谢!

【问题讨论】:

  • 你想听所有的意见,对吧? (抽象 viewWillAppear 以便他们都向同一个代表报告)

标签: ios objective-c model-view-controller


【解决方案1】:

您可以通过向 UIViewController 添加扩展并使用您自己的方法调整 viewDidLoad 方法来做到这一点,因此每次推送或呈现您自己的 viewDidLoad 实现的任何 UIViewController 都会被调用,您可以在其中做任何您想做的事情,您也可以调整任何方法,不仅是 viewDidLoad 看看这个 swizzling 是如何工作的例子

extension UIViewController {
// We cannot override load like we could in Objective-C, so override initialize instead
public override static func initialize() {

    // Make a static struct for our dispatch token so only one exists in memory
    struct Static {
        static var token: dispatch_once_t = 0
    }

    // Wrap this in a dispatch_once block so it is only run once
    dispatch_once(&Static.token) {
        // Get the original selectors and method implementations, and swap them with our new method
        let originalSelector = #selector(UIViewController.viewDidLoad)
        let swizzledSelector = #selector(UIViewController.myViewDidLoad)

        let originalMethod = class_getInstanceMethod(self, originalSelector)
        let swizzledMethod = class_getInstanceMethod(self, swizzledSelector)

        let didAddMethod = class_addMethod(self, originalSelector, method_getImplementation(swizzledMethod), method_getTypeEncoding(swizzledMethod))

        // class_addMethod can fail if used incorrectly or with invalid pointers, so check to make sure we were able to add the method to the lookup table successfully
        if didAddMethod {
            class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod))
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
        }
    }
}

// Our new viewDidLoad function
// In this example, we are just logging the name of the function, but this can be used to run any custom code
func myViewDidLoad() {
    // This is not recursive since we swapped the Selectors in initialize().
    // We cannot call super in an extension.
    self.myViewDidLoad()
    print("do what you want here") // logs myViewDidLoad()
}
}

【讨论】:

  • Method swizzling 是相当深刻的,黑暗的魔力,只适用于 Objective-C 风格的消息传递。对于刚开始进行 iOS 开发的人来说,这可能不是最好的主意。
  • @ali : 用什么版本的objective-c写的?
  • @Duncan 肯定这可能不是最好的主意,但他可以通过使用它来实现他想要的,然后他可以使用任何其他方式来改进它
  • @YvesLeBorg 它是 swift 3 而不是 Objective-c
  • @AliAdam 不在 Swift 5 中工作。你有什么想法吗?
猜你喜欢
  • 1970-01-01
  • 2018-06-13
  • 2014-01-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多