IOS基础理论知识复习(三)

   在简书看到大牛的知识点,发现很多知识点自己一知半解,能做项目但理论不够扎实,默默地去百度总结一下.放到这里和大家交流交流.

如有侵权,告知即删!

01.用StoryBoard开发界面有什么弊端?如何避免?

优点:
开发界面所见即所得,可以快速通过拖拽构造界面。
你可以从 storyboard 中很方便地梳理出所有View Controller的界面间的调用关系。这一点对于新加入项目组的开发同事来说,比较友好。

缺点:
xib 对版本管理是灾难。storyboard 实际上的多个 xib 的集合,所以更容易让多人编辑产生冲突。而虽然它们是 xml 格式,但是冲突解决起来还是不如代码那么容易。
苹果对 xib, storyboard 的设计中带有当前电脑的操作系统版本和 Xcode 版本。所以如果两个协作的开发者电脑操作系统或 Xcode 有不一样的话,每次打开必定会修改这个文件。另外即使操作系统版本和 Xcode 版本一样,有些时候打开看也会造成一些自动的修改。
xib 和 storyboard 不太方便做界面的模块化管理,比如我们想统一修改界面中所有按钮的字体样式,那么在 xib 和 storyboard 只能一个一个手工修改,而如果是代码编写的,则只需要改一个工厂方法的实现即可。
对于复杂的 App,storyboard 的性能会比较差。
02.进程和线程的区别?同步异步的区别?并行和并发的区别?
先简单说说线程与进程的概念:
(1)进程是指一个内存中运行的应用程序,比如在Windows系统中,一个运行的exe就是一个进程。
(2)线程是指进程中的一个执行流程。

区别:
一个程序至少有一个进程,而一个进程至少有一个线程。一个应用程序可以同时启动多个进程。例如对于IE浏览器程序,每打开一个IE浏览器窗口,就启动了一个新的进程。而线程则是指进程中的一个执行流程,一个进程可以有多个线程,每个线程分别执行不同的任务,当进程内的多个线程同时运行时,这种运行方式就被称为并发运行。
另外,线程与进程还有一个非常重要的区别:每个进程在执行过程中都拥有独立的内存单元,而同一个进程中的多个线程则共享内存,从而极大地提高了程序的运行效率。
1.并发:在操作系统中,是指一个时间段中有几个程序都处于已启动运行到运行完毕之间,且这几个程序都是在同一个处理机上运行。其中两种并发关系分别是同步和互斥
2.互斥:进程间相互排斥的使用临界资源的现象,就叫互斥。
3.同步:进程之间的关系不是相互排斥临界资源的关系,而是相互依赖的关系。进一步的说明:就是前一个进程的输出作为后一个进程的输入,当第一个进程没有输出时第二个进程必须等待。具有同步关系的一组并发进程相互发送的信息称为消息或事件。
其中并发又有伪并发和真并发,伪并发是指单核处理器的并发,真并发是指多核处理器的并发。
4.并行:在单处理器中多道程序设计系统中,进程被交替执行,表现出一种并发的外部特种;在多处理器系统中,进程不仅可以交替执行,而且可以重叠执行。在多处理器上的程序才可实现并行处理。从而可知,并行是针对多处理器而言的。并行是同时发生的多个并发事件,具有并发的含义,但并发不一定并行,也亦是说并发事件之间不一定要同一时刻发生。
5.多线程:多线程是程序设计的逻辑层概念,它是进程中并发运行的一段代码。多线程可以实现线程间的切换执行。
6.异步:异步和同步是相对的,同步就是顺序执行,执行完一个再执行下一个,需要等待、协调运行。异步就是彼此独立,在等待某事件的过程中继续做自己的事,不需要等待这一事件完成后再工作。线程就是实现异步的一个方式。异步是让调用方法的主线程不需要同步等待另一线程的完成,从而可以让主线程干其它的事情。
异步和多线程并不是一个同等关系,异步是最终目的,多线程只是我们实现异步的一种手段。异步是当一个调用请求发送给被调用者,而调用者不用等待其结果的返回而可以做其它的事情。实现异步可以采用多线程技术或则交给另外的进程来处理。
03.线程间通信?
线程间通信常用的方法

  1. NSThread可以先将自己的当前线程对象注册到某个全局的对象中去,这样相互之间就可以获取对方的线程对象,然后就可以使用下面的方法进行线程间的通信了,由于主线程比较特殊,所以框架直接提供了在主线程执行的方法
-(void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
-(void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait NS_AVAILABLE(10_5,2_0);

用法如下://点击屏幕开始执行下载方法

- (void)touchesBegan:(NSSet*)touches withEvent: (UIEvent*)event {   
[self performSelectorInBackground:@selector(download) withObject: nil];
}
//下载图片
- (void)download{
// 1.图片地址NSString*urlStr =@"http://d.jpg";
NSURL*url = [NSURL URLWithString: urlStr];
// 2.根据地址下载图片的二进制数据
NSData*data = [NSData dataWithContentsOfURL: url];
NSLog(@"---end");
// 3.设置图片
UIImage*image = [UIImage imageWithData: data];/
/ 4.回到主线程,刷新UI界面(为了线程安全)
[self performSelectorOnMainThread: @selector(downloadFinished:) withObject: image waitUntilDone:NO];
// [self performSelector:@selector(downloadFinished:) onThread:[NSThread mainThread] withObject: image waitUntilDone:YES];
}
- (void)downloadFinished:(UIImage*)image{
self.imageView.image = image;NSLog(@"downloadFinished---%@", [NSThread currentThread]);
}

GCD一个线程传递数据给另一个线程,如:

- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event{dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
NSLog(@"donwload---%@",  [NSThread currentThread]);
// 1.子线程下载图片
NSURL*url = [NSURLURLWithString:@"http://d.jpg"];
NSData*data = [NSData dataWithContentsOfURL: url];
UIImage*image = [UIImage imageWithData: data];
// 2.回到主线程设置图片
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"setting---%@ %@", [NSThread currentThread], image);         
  [self.button setImage: image forState:UIControlStateNormal];       
}); 
});
}

04.GCD的一些常用的函数?(group,barrier,信号量,线程同步)
GCD中实现线程同步的方式
dispatch_group
dispatch_group是GCD中经常使用的线程同步方式,具体用法如下:

dispatch_queue_t queue = dispatch_queue_create("cc.imguiqing", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group = dispatch_group_create();dispatch_group_async(group, queue, ^{        NSLog(@"task 1 on %@",[NSThread currentThread]);});
dispatch_group_async(group, queue, ^{        NSLog(@"task 2 on %@",[NSThread currentThread]);});
dispatch_group_async(group, queue, ^{        NSLog(@"task 3 on %@",[NSThread currentThread]);
});

可以看出,这个和普通的GCD任务相比,每个API都多了一个group参数.但是如果仅仅是像上面的方式使用,就没有什么必要了.我们使用Group的原因,更多是想要知道这个Group中的执行情况.借此来获得时机做一些逻辑操作.所以dispatch_group提供了两个API:
通知Group中的任务都执行完毕
dispatch_group_notify(group, queue, ^{ NSLog(@"all task done");});
阻塞式的等待Group中的任务都执行完毕
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);NSLog(@"since all done , I move on");
更常见的写法
上面的写法虽然简单,但是如果看过一些三方库的代码,发现那么用的并不多.更多的是利用dispatch_group_enter(group)和dispatch_group_leave(group)来包装任务,本质上两者没有区别,多说这些仅仅是让你别以后看代码的时候感到疑惑,
代码如下:

dispatch_queue_t queue = dispatch_get_global_queue(0,0);
dispatch_group_t group = dispatch_group_create();dispatch_group_enter(group);dispatch_async(queue, ^{       
NSLog( @"task 1 --- %@", [NSThread currentThread] );
dispatch_group_leave(group);} );
dispatch_group_enter(group);
dispatch_async(queue, ^{       
NSLog( @"task 2 --- %@", [NSThread currentThread] );dispatch_group_leave(group);} );
dispatch_group_notify(group, queue, ^{       
NSLog( @"all task done %@", [NSThread currentThread] );
} );

信号量
信号量可以理解为一个特殊的变量.程序对它的访问都是原子性的,我们通过PV操作来修改信号量.
使用代码简单说明:

dispatch_semaphore_t sem =dispatch_semaphore_create(0);
[networkManager requestWithDelay:5completion:^{dispatch_semaphore_signal(sem);//+1}];
dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
//-1NSLog(@"five sectonds");

信号量创建的时候, 可以给他指定一个值.dispatch_semaphore_signal(sem)对信号进行+1操作.dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER)对信号进行-1操作.当进行-1时,如果发现信号结果会小于0,那么线程进入阻塞状态.只有当信号>=0才能通过.
那么上面的代码段就容易明白了: 一直等到一个异步的网络请求结束,才继续执行NSLog(@"five sectonds");,也是就其他的逻辑
Barrier
相比上面两种方式,Barrier知道的人相对少一些.但是Barrier用起来相对上面两种更加简单.

dispatch_queue_t queue = dispatch_queue_create("cc.imguiqing", DISPATCH_QUEUE_CONCURRENT);dispatch_async(queue,^{       
NSLog(@"task 1 on %@",[NSThread currentThread]);});
dispatch_async(queue,^{       
NSLog(@"task 2 on %@",[NSThread currentThread]);});
dispatch_barrier_async(queue,^{       
NSLog(@"barrier ==========");});
dispatch_async(queue,^{       
NSLog(@"task 3 on %@",[NSThread currentThread]);
});

上面的代码,task 1和task 2会并发执行,然后执行barrier,最后是task 3,用图来说明:
[图片上传中。。。(1)]

这个 barrier就相当于一个栅栏,将不同的任务区分开来.从代码中也不难看出,这个barrier函数不需要依赖其它的变量,没有侵入性.所以非常好用.和Group也是非常好搭配.例如下面的代码:

dispatch_queue_t queue = dispatch_queue_create("cc.imguiqing", DISPATCH_QUEUE_CONCURRENT);
dispatch_group_t group =dispatch_group_create();
dispatch_group_async(group, queue, ^{       
for (int i =0; i < 500000000; i++) {}       
NSLog(@"task 1 on %@",[NSThread currentThread]);});
dispatch_barrier_async(queue,^{       
NSLog(@"======");});
dispatch_group_async(group, queue, ^{       
for (int i =0; i < 500000000; i++) {}       
NSLog(@"task 2 on %@",[NSThread currentThread]);});
dispatch_barrier_async(queue,^{       
NSLog(@"======");});
dispatch_group_async(group, queue, ^{       
NSLog(@"task 3 on %@",[NSThread currentThread]);});
dispatch_group_notify(group, queue, ^{       
NSLog(@"all task done");});
dispatch_group_wait(group,DISPATCH_TIME_FOREVER);
NSLog(@"since all done , I move on");

能保证task 1 2 3顺序执行,同时,由于使用了Group,也能知道执行结束的时机. 但是仅仅是为了说明问题,如果要顺序执行,那么还是使用GCD中同步队列更加合适.
注意点: 这个barrier函数只能用于并发队列,且不能是global queue.

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

推荐阅读更多精彩内容