objective-cjailbreaktheostweakspringboard

How to keep object alive across the application in objective-c


I have the problem is that I want to use an object across the applications such as SpringBoard, Safari, Settings, Notes, etc. I'm using Singleton pattern. But when I dump these objects, they have it own allocate. Therefore, I think they are different objects. Is there any way to keep an object alive across the applications? I have root permission.

Here's my log on HomeScreen (SpringBoard), Safari and Settings:

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

Solution

  • If you want to use the same object, you're going to have to develop some method of interprocess communication (IPC). While I don't have very much experience with it, I know the RocketBootstrap library can be a good place to start learning.

    The main concept is that you inject two different versions of your tweak into SpringBoard and UIKit applications. In SpringBoard, you will run a server and listen for messages. In UIKit applications, you will connect to this server and send a request whenever you need to execute a function on the singleton. You can use RocketBootstrap to send this message. It's definitely not seamless, since you have to design a communication protocol, but everything will work out if done properly.

    If you need to be able to send requests from SpringBoard to UIKit applications, you'll have to drop down to the mach_msg level rather than using RocketBootstrap. It can still help you get a grip on what you're doing however.