如何在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 完全透明

如何在objective-c中使UIImage为NULL

如何在objective-c的动画中使视图振动? [关闭]

如何在Asp .Net Web API中的请求的整个生命周期中使类对象可用?

Android:- 如何在整个应用程序中使动态 HashMap 可访问? [复制]

如何在我的 Android 应用程序中使视图填充其父级的整个宽度?