1. 程式人生 > >iOS執行緒通訊和程序通訊的例子(NSMachPort和NSTask,NSPipe)

iOS執行緒通訊和程序通訊的例子(NSMachPort和NSTask,NSPipe)

iOS執行緒間的通訊

iOS中,兩個執行緒之間要想互相通訊,可以使用:NSMachPort
下面是例子

#define kMsg1 100
#define kMsg2 101

- (void)viewDidLoad {
    [super viewDidLoad];

    //1. 建立主執行緒的port
    // 子執行緒通過此埠傳送訊息給主執行緒
    NSPort *myPort = [NSMachPort port];

    //2. 設定port的代理回撥物件
    myPort.delegate = self;

    //3. 把port加入runloop,接收port訊息
[[NSRunLoop currentRunLoop] addPort:myPort forMode:NSDefaultRunLoopMode]; NSLog(@"---myport %@", myPort); //4. 啟動次執行緒,並傳入主執行緒的port MyWorkerClass *work = [[MyWorkerClass alloc] init]; [NSThread detachNewThreadSelector:@selector(launchThreadWithPort:) toTarget:work withObject:myPort]; } - (void
)handlePortMessage:(NSMessagePort*)message{ NSLog(@"接到子執行緒傳遞的訊息!%@",message); //1. 訊息id NSUInteger msgId = [[message valueForKeyPath:@"msgid"] integerValue]; //2. 當前主執行緒的port NSPort *localPort = [message valueForKeyPath:@"localPort"]; //3. 接收到訊息的port(來自其他執行緒) NSPort *remotePort = [message valueForKeyPath:@"remotePort"
]; if (msgId == kMsg1) { //向子線的port傳送訊息 [remotePort sendBeforeDate:[NSDate date] msgid:kMsg2 components:nil from:localPort reserved:0]; } else if (msgId == kMsg2){ NSLog(@"操作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. 儲存主執行緒傳入的port
        remotePort = port;

        //2. 設定子執行緒名字
        [[NSThread currentThread] setName:@"MyWorkerClassThread"];

        //3. 開啟runloop
        [[NSRunLoop currentRunLoop] run];

        //4. 建立自己port
        myPort = [NSPort port];

        //5.
        myPort.delegate = self;

        //6. 將自己的port新增到runloop
        //作用1、防止runloop執行完畢之後推出
        //作用2、接收主執行緒傳送過來的port訊息
        [[NSRunLoop currentRunLoop] addPort:myPort forMode:NSDefaultRunLoopMode];



        //7. 完成向主執行緒port傳送訊息
        [self sendPortMessage];


    }
}

/**
 *   完成向主執行緒傳送port訊息
 */
- (void)sendPortMessage {

    NSMutableArray *array  =[[NSMutableArray alloc]initWithArray:@[@"1",@"2"]];
    //傳送訊息到主執行緒,操作1
    [remotePort sendBeforeDate:[NSDate date]
                         msgid:kMsg1
                    components:array
                          from:myPort
                      reserved:0];

    //傳送訊息到主執行緒,操作2
    //    [remotePort sendBeforeDate:[NSDate date]
    //                         msgid:kMsg2
    //                    components:nil
    //                          from:myPort
    //                      reserved:0];
}


#pragma mark - NSPortDelegate

/**
 *  接收到主執行緒port訊息
 */
- (void)handlePortMessage:(NSPortMessage *)message
{
    NSLog(@"接收到父執行緒的訊息...\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

以上就可以完成一個執行緒間的資料通訊。

iOS程序間的通訊(越獄時用到)

先建立一個命令列工程,建一個簡單的子專案。名為: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;
}

再建立一個有介面的主專案。程序通訊部分程式碼。需要引用標頭檔案:NSTask.h見下面的引用

    NSString* string = [[NSBundle mainBundle] pathForResource:@"taskchild" ofType:nil];//taskchild是所要啟動的名字二進位制檔名,上面建的子專案。
    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);

引用