iOS執行緒通訊和程序通訊的例子(NSMachPort和NSTask,NSPipe)
阿新 • • 發佈:2019-01-25
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);