0

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
Minh Quy
  • 655
  • 5
  • 21

2 Answers2

0

Each of the processes has its own copy of the variable, because this is the way processes work in iOS (and not only in iOS for that matter). Each process has its own separate memory and data is not shared between them at all. Your singleton will be constructed separately for each process because of that.

Wojtek Surowka
  • 20,535
  • 4
  • 44
  • 51
0

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.

Ryan Pendleton
  • 2,566
  • 19
  • 29
  • Thanks @Ryan Pendleton. I will try your suggestion. My problem is that: I have to create new control (in this case is a rectangle). My control always display on top SpringBoard and every application. It look like AssistiveTouch on iPhone/iPod/iPad. To resolve my problem, I created a custom UIWindow and add to it a UIView. But I want my control will rotate when device orientation changed on SpringBoard and every application. But with each application, new instance of my custom UIWindow will be created even I already using singleton pattern. Here's my custom UIWindow http://pastie.org/9664645 – Minh Quy Oct 21 '14 at 09:40
  • @MinhQuy Is there a reason you're injecting your tweak into applications then? It seems like injecting it into SpringBoard would be enough, unless there's something I'm missing. – Ryan Pendleton Oct 21 '14 at 15:53
  • There are many ways to handle device orientation change but they have the same problem. In each application process (SpringBoard, Safari, Notes, etc) it will create its own an object of my custom UIWindow. I can rotate new object but old object that created in SpringBoard still display and I cannot remove or hide it. I'm trying to detect when SpringBoard come to foreground and background. – Minh Quy Oct 21 '14 at 17:36
  • @MinhQuy But if the window from SpringBoard is visible in all applications, why do you have to load your plugin in applications as well? I would load it in SpringBoard only. – Ryan Pendleton Oct 21 '14 at 22:04
  • I think so but the truth is different :(. Here's my code http://pastie.org/9666768. I copy and modify from https://github.com/rpetrich/IconRotator. You can see when the `updateWithDeviceOrientation:` method is called, object of my window will has different memory allocation (different objects) in each application process. Therefore, I want to load my plugin in applications – Minh Quy Oct 22 '14 at 02:57
  • Hi Ryan Pendleton, there's a solution to fix my problem is that NSDistributedNotificationCenter :) – Minh Quy Oct 27 '14 at 10:36
  • @MinhQuy As long as you don't need to pass information between the processes, that should work. It's certainly a form of IPC – Ryan Pendleton Oct 27 '14 at 14:33