如何检测iPhone应用程序状态变化?
我发布这个问题(连同答案),以便其他人可以从我开发的一种巧妙的技术中受益,该技术可以让模块自动检测(并响应)iOS 应用程序状态变化。 (格式化的)博客讨论在这里 我的博客
I am posting this question (along with the answer) so that other people can benefit from a neat technique I have evolved to have modules automatically detect (and respond to) iOS app state changes. The (formatted) blog discussion is here My Blog
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
如果您搜索执行代码以响应应用程序状态更改的解决方案,您将找到代码示例,其中将对代码的调用添加到应用程序委托中,因为每当应用程序 didFinishLaunchingWithOptions、didBecomeActive 或 WillEnterBackground 时都会调用它。
但假设您开始开发另一个应用程序,该应用程序重复使用了您的大量代码。如果您只需复制一些文件并获得所有功能,而不必担心重新连接应用程序委托方法,那不是很好吗?
总而言之,我们希望插入式模块只需在项目中即可执行其工作,而无需任何额外的工作或接线。此时您可能会说“我也想要独角兽和精灵给我带来披萨”。耐心听我说。
我不确定在阅读文档时我是如何错过这一点的,但是当 iOS 应用程序更改状态时,不仅仅是应用程序委托知道它。 NSNotifications 也会针对所有主要状态更改发布。以下是直接取自 api 参考的文本:
调用 [applicationDidBecomeActive] 后,应用程序还会发布 UIApplicationDidBecomeActiveNotification 通知,为感兴趣的对象提供响应转换的机会。
类似地,有一个 UIApplicationDidFinishLaunchingNotification 在应用程序完成启动后立即发布,以及其他用于进入后台或进入前台的通知。
因此,这简化了我们的代码:我们不必调用
应用程序委托的 applicationDidBecomeActive 实现,而只需让 RobustWebService 响应 UIApplicationDidFinishLaunchingNotification 即可。
现在思考一下,您可能会意识到,为了让 RWS 类处理通知,它必须注册为观察者。这个电话看起来像这样
在哪里可以完成呢?请记住,我们不想触及应用程序委托,因为这会违背拥有独立嵌入式模块的意图。如果有某种方法可以让该类自动调用 addObserver 函数就好了。要是……
到了这个地步,我们就得跳出“Cocoa”,深入挖掘 Objective-C 的底层技术了。果然,有一个名为“load”的类方法,如果类定义中存在该方法,则在首次加载类时将自动调用该方法。让我们在代码中重申一下。如果您在任何 class.m 文件中编写此函数,
它将在 iOS 加载该类时运行。有趣的是,它在调用应用程序的 main() 例程之前运行,因此您必须非常小心尝试执行的操作!此时,您的大部分应用程序实际上尚未启动并运行,但可以保证您的类链接的所有框架都将首先加载。像 NSNotificationCenter 这样的框架,所以如果你在你的 class.m 中包含这个,
那么当你的应用程序变得活跃时,你的 handleAppBecomeActive 方法将被调用,除了在你的项目中包含 class.h 和 class.m 之外,你不需要做任何事情。
如果您将此代码包含在您的 class.m 文件中,
您的班级将收到所有应用程序状态更改的通知,无需其他工作。这太酷了,以至于我仍然感到刺痛。享受!
特里
If you google around for solutions to having code execute in response to app state changes, you’ll find code examples where you add in calls to your code into your app delegate, because it gets called whenever the application didFinishLaunchingWithOptions, or didBecomeActive, or WillEnterBackground.
But let’s say you start working on another app, which re-uses a lot of your code. Wouldn’t it be nice if you could just copy over some files and get all the functionality, without having to worry about re-wiring up the app delegate methods?
To summarize, we want drop-in modules that, just by the virtue of being in the project, will perform their work, without any additional effort or wiring up. At this point you may be saying “and I also want unicorns and elves to bring me a pizza”. Bear with me.
I’m not sure how I missed this when reading the docs, but when iOS applications change state, it isn’t just the app delegate that knows about it. NSNotifications also get posted for all major state changes. Here is text taken directly from the api reference:
After calling [applicationDidBecomeActive], the application also posts a UIApplicationDidBecomeActiveNotification notification to give interested objects a chance to respond to the transition.
Similarly, there is a UIApplicationDidFinishLaunchingNotification that gets posted immediately after the application finishes launching, and other notifications for entering the background, or entering the foreground.
So this simplifies our code: instead of having to call
in the app delegate’s implementation of applicationDidBecomeActive, we just have to have RobustWebService respond to UIApplicationDidFinishLaunchingNotification.
Now pondering this a moment, you might realize that in order for the RWS class to handle the notification, it has to register as an observer. That call looks something like
And where can that get done? Remember, we do not want to touch the app delegate because that would defeat the intent of having a self-contained drop-in module. If only there were some way to have the addObserver function call happen automatically for the class. If only…
At this point we have to drop out of “Cocoa” and dig into the underlying technology of Objective-C. Sure enough, there is a class method, called “load” which, if present in your class definition, will automatically be called when the class is first loaded. Let’s restate that in code. If you write this function in any class.m file
It will run when the class is loaded by iOS. Interestingly enough, it is run before your app’s main() routine is called so you have to be very careful about what you try to do! Most of your app is NOT actually up and running at this point, but you are guaranteed that all frameworks that your class links too will be loaded first. Frameworks such as NSNotificationCenter, so if you include this in your class.m
Then your handleAppBecomeActive method WILL get called when your app becomes active, without you having to do anything other than include the class.h and class.m in your project.
And if you include this code in your class.m file
Your class will get notified of all app state changes, with no other work required. This is so cool that it still makes me feel tingly. Enjoy!
Terry