如何在objective-c中使对象在整个应用程序中保持活动状态
Posted
技术标签:
【中文标题】如何在objective-c中使对象在整个应用程序中保持活动状态【英文标题】:How to keep object alive across the application in objective-c 【发布时间】:2014-10-20 10:31:02 【问题描述】:我的问题是我想在 SpringBoard、Safari、Settings、Notes 等应用程序中使用一个对象。我使用的是单例模式。但是当我转储这些对象时,它们有自己的分配。因此,我认为它们是不同的对象。有没有办法让一个对象在应用程序中保持活跃?我有root权限。
这是我在 HomeScreen (SpringBoard)、Safari 和设置上的日志:
Oct 20 17:05:5 MyPhone SpringBoard[982] <Warning>: MyClass: <MyClass: 0x17f72680>
Oct 20 17:06:29 MyPhone MobileSafari[1001] <Warning>: MyClass: <MyClass: 0x15da9b60>
Oct 20 17:06:34 MyPhone Preferences[1002] <Warning>: MyClass: <MyClass: 0x175864c0>
MyClass.h
#import <Foundation/Foundation.h>
@interface MyClass : NSObject
+ (instancetype)sharedInstance;
- (void)doSomething;
@end
MyClass.m
#import "MyClass.h"
@implementation MyClass
- (instancetype)init
self = [super init];
return self;
+ (instancetype)sharedInstance
static dispatch_once_t p = 0;
__strong static id _sharedSelf = nil;
dispatch_once(&p, ^
_sharedSelf = [[self alloc] init];
);
return _sharedSelf;
- (void)doSomething
NSLog(@"MyClass: %@", self);
@end
Tweak.xm
#import <SpringBoard/SpringBoard.h>
#import <MyClass.h>
%hook SpringBoard
- (void)applicationDidFinishLaunching:(UIApplication *)application
%orig;
MyClass *myClass = [MyClass sharedInstance];
[myClass doSomething];
%end
%hook UIViewController
- (void)viewDidLoad
%orig;
MyClass *myClass = [MyClass sharedInstance];
[myClass doSomething];
%end
【问题讨论】:
【参考方案1】:如果您想使用同一个对象,您将不得不开发一些进程间通信 (IPC) 方法。虽然我没有太多经验,但我知道RocketBootstrap 库是开始学习的好地方。
主要概念是将两个不同版本的调整注入 SpringBoard 和 UIKit 应用程序。在 SpringBoard 中,您将运行一个服务器并监听消息。在 UIKit 应用程序中,您将连接到该服务器并在您需要在单例上执行功能时发送请求。您可以使用 RocketBootstrap 发送此消息。这绝对不是无缝的,因为你必须设计一个通信协议,但如果做得好,一切都会好起来的。
如果您需要能够将请求从 SpringBoard 发送到 UIKit 应用程序,则必须下拉到 mach_msg 级别,而不是使用 RocketBootstrap。不过,它仍然可以帮助您掌握正在做的事情。
【讨论】:
谢谢@Ryan Pendleton。我会试试你的建议。我的问题是:我必须创建新控件(在这种情况下是一个矩形)。我的控件始终显示在 SpringBoard 和每个应用程序的顶部。它看起来像 iPhone/iPod/iPad 上的 AssistiveTouch。为了解决我的问题,我创建了一个自定义 UIWindow 并向其中添加了一个 UIView。但是我希望当 SpringBoard 和每个应用程序上的设备方向发生变化时,我的控件会旋转。但是对于每个应用程序,即使我已经使用单例模式,也会创建自定义 UIWindow 的新实例。这是我的自定义 UIWindow pastie.org/9664645 @MinhQuy 你有什么理由将你的调整注入应用程序吗?似乎将其注入 SpringBoard 就足够了,除非我缺少某些东西。 有很多方法可以处理设备方向的变化,但它们都有同样的问题。在每个应用程序进程(SpringBoard、Safari、Notes 等)中,它将创建自己的自定义 UIWindow 对象。我可以旋转新对象,但在 SpringBoard 中创建的旧对象仍然显示,我无法删除或隐藏它。我正在尝试检测 SpringBoard 何时进入前台和后台。 @MinhQuy 但是如果 SpringBoard 的窗口在所有应用程序中都是可见的,为什么还要在应用程序中加载插件呢?我只会在 SpringBoard 中加载它。 我想是这样,但事实不同:(。这是我的代码pastie.org/9666768。我从github.com/rpetrich/IconRotator复制和修改。你可以看到何时调用updateWithDeviceOrientation:
方法,我的对象window 在每个应用程序进程中会有不同的内存分配(不同的对象)。因此,我想在应用程序中加载我的插件【参考方案2】:
每个进程都有自己的变量副本,因为这是进程在 ios 中的工作方式(而不仅仅是在 iOS 中)。每个进程都有自己独立的内存,它们之间根本不共享数据。因此,您的单例将为每个进程单独构建。
【讨论】:
感谢您的回答。我会尝试其他解决方案。 嗨 WojtekSurowka,我使用 NSDistributedNotificationCenter 来解决我的问题以上是关于如何在objective-c中使对象在整个应用程序中保持活动状态的主要内容,如果未能解决你的问题,请参考以下文章
如何在 Objective-C 的 UITableView 中使 UITableViewRowAction 完全透明
如何在Asp .Net Web API中的请求的整个生命周期中使类对象可用?