iOS - 线程 / 进程 的通信

1. 线程中的通信

  • 线程中通信的体现
1 .一个线程传递数据给另一个线程
2 .在一个线程中执行完特定任务后,转到另一个线程继续执行任务

在iOS多线程开发中,有NSThread、GCD、NSOpeartion几种方式,
对应的线程间通信

1.1 NSThread

NSThread可以先将自己的当前线程对象注册到某个全局的对象中去,这样相互之间就可以获取对方的线程对象,然后就可以使用下面的方法进行线程间的通信了,由于主线程比较特殊,所以框架直接提供了在主线程执行的方法

回到主线程执行

/*
 *  aSelector: 执行方法
 *  arg: 携带参数
 */
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;

去指定线程执行任务

/*
 *   aSelector: 执行方法
 *   thr: 指定线程
 *   arg: 携带参数
 */
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait;

关于 waitUntilDone

waitUntilDone的含义:
如果传入的是YES: 那么会等到主线程中的方法执行完毕, 才会继续执行下面其他行的代码
如果传入的是NO: 那么不用等到主线程中的方法执行完毕, 就可以继续执行下面其他行的代码
1.2 GCD
  • 什么是GCD
    全称是Grand Central Dispatch,可译为“牛逼的中枢调度器”
    纯C语言,提供了非常多强大的函数

  • GCD的使用
    GCD中有2个核心概念
    (1)任务:执行什么操作
    (2)队列:用来存放任务

    GCD的使用就2个步骤
    (1)定制任务
    (2)确定想做的事情

    将任务添加到队列中,GCD会自动将队列中的任务取出,放到对应的线程中执行
    注意:任务的取出遵循队列的FIFO原则:先进先出,后进后出

  /*
  * queue:队列
  * block:任务 
  */
(1)用同步的方式执行任务 dispatch_sync(dispatch_queue_t queue, dispatch_block_t block);
(2)用异步的方式执行任务 dispatch_async(dispatch_queue_t queue, dispatch_block_t block);
  • 线程通信
// queue 表示某个子线程
dispatch_async(subQueue, ^{
        // 在子线程中
  dispatch_async(dispatch_get_main_queue(), ^{
      #回到主线程
    });
});

关于GCD 远远不止这些功能, 这里这是讲了最基本的简单通信.

1.3 NSOperation
  • 简介
    NSOperation是基于GCD的,那么使用起来也和GCD差不多,其中,NSOperation相当于GCD中的任务,而NSOperationQueue则相当于GCD中的队列。

  • NSOperation实现多线程的使用步骤分为三步:
    创建任务:先将需要执行的操作封装到一个NSOperation对象中。
    创建队列:创建NSOperationQueue对象。
    将任务加入到队列中:然后将NSOperation对象添加到NSOperationQueue中。

  • 获取队列

// 主队列
// 凡是添加到主队列中的任务(NSOperation),都会放到主线程中执行
NSOperationQueue *queue = [NSOperationQueue mainQueue];
// 其他队列(非主队列)
// 添加到这种队列中的任务(NSOperation),就会自动放到子线程中执行
// 同时包含了:串行、并发功能
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
  • 添加任务
    - (void)addOperation:(NSOperation *)op
    需要先创建任务,再将创建好的任务加入到创建好的队列中去
// 1.创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];

// 2. 创建操作  
// 创建NSInvocationOperation    
NSInvocationOperation *op1 = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(test) object:nil];    
// 创建NSBlockOperation    
NSBlockOperation *op2 = [NSBlockOperation blockOperationWithBlock:^{
  NSLog(@"op2 ---- %@", [NSThread currentThread]);
}];

// 3. 添加操作到队列中:addOperation:   
[queue addOperation:op1]; // [op1 start]    
[queue addOperation:op2]; // [op2 start]

- (void)run{
  NSLog(@"op1 ---- %@", [NSThread currentThread]);
}

- (void)addOperationWithBlock:(void (^)(void))block
无需先创建任务,在block中添加任务,直接将任务block加入到队列中。

// 1. 创建队列
NSOperationQueue *queue = [[NSOperationQueue alloc] init];

// 2. 添加操作到队列中:addOperationWithBlock:
[queue addOperationWithBlock:^{
  NSLog(@"%@", [NSThread currentThread]);
}];
  • 线程通信
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperationWithBlock:^{
  NSLog(@"1 ---- %@", [NSThread currentThread]);
  # 回到主线程
  [[NSOperationQueue mainQueue] addOperationWithBlock:^{
        NSLog(@"2 ---- %@", [NSThread currentThread]);
  }];
}];

NSOperation 和GCD一样 不止以上这些功能,这里只是讲述了基本的使用和简单的线程通信.

2.进程的通信

进程是容纳运行一个程序所需要所有信息的容器。在iOS中每个APP里就一个进程,所以进程间的通信实际上是APP之间的通信.

2.1 URL Scheme
  • 什么是URL Scheme
    由于苹果的app都是在沙盒中,相互是不能访问数据的。但是苹果还是给出了一个可以在app之间跳转的方法:URL Scheme。简单的说,URL Scheme就是一个可以让app相互之间可以跳转的协议。每个app的URL Scheme都是不一样的,如果存在一样的URL Scheme,那么系统就会响应先安装那个app的URL Scheme,因为后安装的app的URL Scheme被覆盖掉了,是不能被调用的。

  • URL Scheme怎么使用
    App1通过openURL的方法跳转到App2,并且在URL中带上想要的参数,有点类似http的get请求那样进行参数传递。

源 APP1 的配置
源App1需要在info.plist中配置LSApplicationQueriesSchemes,指定目标App2的scheme


源 APP1 的配置

目标 APP2 的配置
然后在目标App2的info.plist中配置好URL types,表示该app接受何种URL scheme的唤起。


目标 APP2 的配置

也可以在 项目-> info -> URL types 中直接添加


配置方法二

源 APP1 的代码调用

UIApplication *application = [UIApplication sharedApplication];
NSURL *URL = [NSURL URLWithString:@"testApp2://hello,word"];
[application openURL:URL options:@{} completionHandler:nil];

目标 APP2 的代码接收

AppDelegate.m 中
- (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options{
    NSLog(@"%@",url);
    return YES;
}
打印结果
2.2 UIPasteboard

UIPasteboard是剪切板功能,因为iOS的原生控件UITextView,UITextField 、UIWebView,我们在使用时如果长按,就会出现复制、剪切、选中、全选、粘贴等功能,这个就是利用了系统剪切板功能来实现的。而每一个App都可以去访问系统剪切板,所以就能够通过系统剪贴板进行App间的数据传输了。
UIPasteboard典型的使用场景就是淘宝的淘口令。

  • 使用
    源APP赋值
    [[UIPasteboard generalPasteboard] setString:@"hello,word"];
    目标APP取值
    NSString *value = [UIPasteboard generalPasteboard].string;
2.3 Keychain

Keychain是iOS中一个安全存储容器,本质是一个sqlite数据库,位置在/private/var/Keychains/keychain-2.db。它是独立于每个App的沙盒之外的,所以即使App被删除之后,Keychain里面的信息依然存在。基于安全和独立于app沙盒的两个特性,Keychain主要用于给app保存登录和身份凭证等敏感信息,这样只要用户登录过,即使用户删除了app重新安装也不需要重新登录。
Keychain用于App间通信的一个典型场景也和app的登录相关,就是统一账户登录平台。使用同一个账号平台的多个app,只要其中一个app用户进行了登录,其他app就可以实现自动登录不需要用户多次输入账号和密码。一般开放平台都会提供登录SDK,在这个SDK内部就可以把登录相关的信息都写到keychain中,这样如果多个app都集成了这个SDK,那么就可以实现统一账户登录了。

具体使用
目前我自己还不太熟悉这个框架的使用,后续了解清楚会补充该框架的本人理解及使用方法.

2.4 分享

通过将源APP数据分享给目标APP 实现通信
原生分享

  • UIActivityViewController(轻量级信息分享),
// Items: 元素1是标题,元素2是URL
UIActivityViewController *avc = [[UIActivityViewController alloc]initWithActivityItems:@[@"title",url] applicationActivities:nil];
    
[self presentViewController:avc animated:YES completion:nil];
    
//分享结果回调方法
UIActivityViewControllerCompletionWithItemsHandler myblock = ^(NSString * __nullable activityType, BOOL completed, NSArray * __nullable returnedItems, NSError * __nullable activityError){
    };
avc.completionWithItemsHandler = myblock;
  • UIDocumentInteractionController (主要是共享文档,预览)
NSString *urlStr = [[NSBundle mainBundle] pathForResource:@"1.png" ofType:nil];
NSURL *url = [NSURL fileURLWithPath:urlStr];
    
UIDocumentInteractionController *documentVc = [UIDocumentInteractionController interactionControllerWithURL:url];
documentVc.delegate = self;

[documentVc presentPreviewAnimated:YES];
#pragma mark - UIDocumentInteractionController 代理方法
// 预览的视图控制器
- (UIViewController *)documentInteractionControllerViewControllerForPreview:(UIDocumentInteractionController *)controller{
    return self;
}
// 父View
- (UIView *)documentInteractionControllerViewForPreview:(UIDocumentInteractionController *)controller{
    return self.view;
}
// 预览界面的尺寸
- (CGRect)documentInteractionControllerRectForPreview:(UIDocumentInteractionController *)controller{
    return self.view.bounds;
}
  • 第三方SDK分享
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 199,340评论 5 467
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 83,762评论 2 376
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 146,329评论 0 329
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 53,678评论 1 270
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 62,583评论 5 359
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 47,995评论 1 275
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,493评论 3 390
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,145评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,293评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,250评论 2 317
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,267评论 1 328
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,973评论 3 316
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,556评论 3 303
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,648评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,873评论 1 255
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,257评论 2 345
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 41,809评论 2 339