Communication between iOS NSMachPort threads and processes

Original: http://blog.csdn.net/yxh265/article/details/51483822

Communication between iOS threads

In iOS, if two threads want to communicate with each other, you can use: NSMachPort
Here is an example

#define kMsg1 100
#define kMsg2 101

- (void)viewDidLoad {
    [super viewDidLoad];

    //1. Create the port of the main thread
    // The sub thread sends messages to the main thread through this port
    NSPort *myPort = [NSMachPort port];

    //2. Set the proxy callback object of port
    myPort.delegate = self;

    //3. Add port to runloop and receive port message
    [[NSRunLoop currentRunLoop] addPort:myPort forMode:NSDefaultRunLoopMode];

    NSLog(@"---myport %@", myPort);
    //4. Start the secondary thread and pass in the port of the main thread
    MyWorkerClass *work = [[MyWorkerClass alloc] init];
    [NSThread detachNewThreadSelector:@selector(launchThreadWithPort:)
                             toTarget:work
                           withObject:myPort];
}
- (void)handlePortMessage:(NSMessagePort*)message{

    NSLog(@"Received message from sub thread!%@",message);

    //1. news id
    NSUInteger msgId = [[message valueForKeyPath:@"msgid"] integerValue];

    //2. port of current main thread
    NSPort *localPort = [message valueForKeyPath:@"localPort"];

    //3. port of message received (from other threads)
    NSPort *remotePort = [message valueForKeyPath:@"remotePort"];

    if (msgId == kMsg1)
    {
        //Send a message to the port of the subline
        [remotePort sendBeforeDate:[NSDate date]
                             msgid:kMsg2
                        components:nil
                              from:localPort
                          reserved:0];

    } else if (msgId == kMsg2){
        NSLog(@"Operation 2....\n");
    }
}
  • MyWorkerClass
#import "MyWorkerClass.h"

@interface MyWorkerClass() <NSMachPortDelegate> {
    NSPort *remotePort;
    NSPort *myPort;
}
@end

#define kMsg1 100
#define kMsg2 101

@implementation MyWorkerClass


- (void)launchThreadWithPort:(NSPort *)port {

    @autoreleasepool {

        //1. Save the port passed in by the main thread
        remotePort = port;

        //2. Set the name of the sub thread
        [[NSThread currentThread] setName:@"MyWorkerClassThread"];

        //3. Open runloop
        [[NSRunLoop currentRunLoop] run];

        //4. Create your own port
        myPort = [NSPort port];

        //5.
        myPort.delegate = self;

        //6. Add your own port to runloop
        //Function 1: prevent the launch of runloop after execution
        //Function 2: receive the port message sent by the main thread
        [[NSRunLoop currentRunLoop] addPort:myPort forMode:NSDefaultRunLoopMode];



        //7. Finish sending message to main thread port
        [self sendPortMessage];


    }
}

/**
 *   Finish sending port message to main thread
 */
- (void)sendPortMessage {

    NSMutableArray *array  =[[NSMutableArray alloc]initWithArray:@[@"1",@"2"]];
    //Send message to main thread, action 1
    [remotePort sendBeforeDate:[NSDate date]
                         msgid:kMsg1
                    components:array
                          from:myPort
                      reserved:0];

    //Send message to main thread, action 2
    //    [remotePort sendBeforeDate:[NSDate date]
    //                         msgid:kMsg2
    //                    components:nil
    //                          from:myPort
    //                      reserved:0];
}


#pragma mark - NSPortDelegate

/**
 *  Main thread port message received
 */
- (void)handlePortMessage:(NSPortMessage *)message
{
    NSLog(@"Message received from parent thread...\n");

    //    unsigned int msgid = [message msgid];
    //    NSPort* distantPort = nil;
    //
    //    if (msgid == kCheckinMessage)
    //    {
    //        distantPort = [message sendPort];
    //
    //    }
    //    else if(msgid == kExitMessage)
    //    {
    //        CFRunLoopStop((__bridge CFRunLoopRef)[NSRunLoop currentRunLoop]);
    //    }
}

@end
  • The above can complete the data communication between threads.

Communication between iOS processes (for jailbreak)

First, create a command line project and a simple subproject. Name: taskchild

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#include <stdio.h>


int main (int argc, const char * argv[])
{

    NSLog(@"receive value arg %d %s %s", argc, argv[0], argv[1]);

    sleep(10);

    // insert code here...
    printf("Hello, World!\n");
    NSLog(@"Hello, World");
    return 0;
}
  • Create another main project with an interface. Process communication part code. Reference header file required: NSTask.h see reference below
    NSString* string = [[NSBundle mainBundle] pathForResource:@"taskchild" ofType:nil];//taskchild is the name of the binary file to be started, the subproject built above.
    NSLog(@"%@",string);

    NSTask *task;
    task = [[NSTask alloc ]init];
    [task setLaunchPath:string];

    NSLog(@"This is NSTask with ping command......\n");
    NSArray *arguments;
    arguments = [NSArray arrayWithObjects:@"22", nil];
    [task setArguments:arguments];

    NSPipe *pipe;
    pipe = [NSPipe pipe];
    [task setStandardOutput:pipe];

    NSFileHandle *file;
    file = [pipe fileHandleForReading];

    [task launch];

    NSData *data;
    data = [file readDataToEndOfFile];

    string = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];

    NSLog(@"get child value :%@",string);

Quote

RunLoops 
NSTask-4-iOS

Tags: iOS encoding

Posted on Fri, 31 Jan 2020 07:19:25 -0800 by myanavrin