iOS相当于Android的registerActivityLifecycleCallbacks

问题描述 投票:0回答:2

我开发了一个 Android 应用程序,其中使用 application.registerActivityLifecycleCallbacks (http://developer.android.com/reference/android/app/Application.html) 来了解每个 Activity 何时启动和停止并记录下来以供分析目的。我现在正在开发iOS版本,我找不到与此方法等效的方法来监视应用程序显示的UIViewControllers或UIView。

有人有想法吗?我是 iOS 初学者,所以我可能没有采取正确的方法,请随意提出其他想法。

编辑
在第一次回答之后,我觉得我应该更准确。 我实际上正在为其他开发人员开发一个 SDK,以便将其包含在他们的应用程序中,因此我希望 SDK 对他们的代码的影响尽可能小。

我首先考虑做一个

BaseActivity
/
BaseUIViewController
,开发人员必须在所有
Activity
/
UIViewController
中进行扩展,但感觉很重,而且由于两种语言都不允许 多重继承,这会极大地影响他们的代码。这就是为什么
registerActivityLifecycleCallbacks
方法在 Android 中很棒,因为它们只需要给我一个
Application
Activity
对象。

有适用于 iOS 的解决方案吗?还是我必须创建一个 BaseController ?

提前谢谢您。

ios view uiviewcontroller activity-lifecycle
2个回答
0
投票

我还没有遇到过 iOS 中的 application.registerActivityLifecycleCallbacks 等特定内容,但您始终可以使用 AppDelegate 和每个类中存在的方法来实现您自己的方法。

AppDelegate 为您提供了确定整个应用程序状态的方法,例如确定应用程序何时完成加载、何时进入后台等等。有关这些状态的详细信息可以在UIApplicationDelegate Protocol Reference页面中找到。

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    NSLog("Application did finish launching with options: %@", launchOptions);
    return YES;
}

enter image description here

对于每个视图控制器,您可以将实现添加到每个文件中的各个视图控制器生命周期方法中。可以使用

viewDidLoad
viewWillAppear
viewDidAppear
viewDidLayoutSubviews
等方法。

- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"View %@ did load", self);
}

0
投票

现在回答已经太晚了,但也许对其他人有帮助。要实现类似的行为,您可以使用“Swizzling”方法。下面是 Swift 中解决方案的示例:

  1. 使用您想要拦截的方法定义 UIViewController 扩展。例如
    viewDidAppear(:)
extension UIViewController {   
  
    @objc func internal_viewDidAppear(_ animated: Bool) {
        self.internal_viewDidAppear(animated)// self here is the UIViewController which was appeared on the screen. Do with it whatever you want 
    } 
}
  1. 实现与此类似的混合:
func swizzleViewDidAppear(){

    let clazz = UIViewController.self
    let originalSelector =  #selector(clazz.viewDidAppear(_:))
    let swizledSelector = #selector(clazz.internal_viewDidAppear(_:))    
    swizzle(originalClass: clazz, swizzledClass: clazz, originalSelector: originalSelector, swizzledSelector: swizledSelector)
}
  1. 搅拌的主要魔力:
func swizzle(originalClass: AnyClass, swizzledClass: AnyClass, originalSelector: Selector, swizzledSelector: Selector) {
    let originalMethod = class_getInstanceMethod(originalClass, originalSelector)
    let swizzledMethod = class_getInstanceMethod(swizzledClass, swizzledSelector)
    let didAddMethod = class_addMethod(originalClass, originalSelector, method_getImplementation(swizzledMethod!),method_getTypeEncoding(swizzledMethod!))
    if didAddMethod {
        class_replaceMethod(originalClass, swizzledSelector,method_getImplementation(originalMethod!),method_getTypeEncoding(originalMethod!))
    } else {
        method_exchangeImplementations(originalMethod!, swizzledMethod!)
    }
}

现在您需要在 SDK 启动时调用 swizzleViewDidAppear(最好在

viewDidLaunchWIthOptions
中)。此代码让系统知道它应该调用您的实现,而不是原始的 viewDidAppear(:) 实现。为了触发拦截方法体内的原始实现,我们调用方法本身。

备注:

  1. 每个会话应该调用一次 Swizzling,因此您需要添加一些标志来指示 swizzling 已经被调用,否则它将把实现替换回原来的状态。

  2. 当开发人员重写 viewDidAppear(:) 时,必须调用

    super.viewDidAppear(animated)
    ,因为没有它,swizzling 将无法工作。

祝你好运,编码愉快:)

© www.soinside.com 2019 - 2024. All rights reserved.