遇到xib的知识
NSBundle
- (文档原话)Many of the methods you use to load resources from a bundle automatically locate the appropriate starting directory and look for resources in known places
- (blog摘抄)bundle是一个目录,其中包含了程序会使用到的资源.这些资源包含了如图像,声音,编译好的代码,nib文件(用户也会把bundle称为plug-in).对应bundle,cocoa提供了类NSBundle.
结合苹果的开发文档和别人blog,模糊地理解为bundle能提供一个方式(就是获取文件路径
)让我们从bundel里面读取我们需要的东西。文档列举了3中project类型
Application, Framework, plug-ins。这里我们会用除了这三个外的在程序上读取nib文件或者图片。
//读取nib文件的方法
-(NSArray *)loadNibNamed:(NSString *)*name*
owner:(id)*owner*
options:(NSDictionary *)*options*
返回一个nib里面所有view的数组。
注意:
1· 这个数组不包含Files owner或者代理对象。
总结:
- 这里引用的blog我都尝试跟着做了一遍,稍微有些名目。平时开发时常喜欢按着control键拉线,outlet翻译就是出口的意思,我感觉就是在xib的fileown关联文件之后,如果需要显示xib上的view时候,就需要使用outlet。如果不使用这个,就需要使用以上NSbundle的方法去引用xib文件的内容
- 其实无论是使用bundle的方法还是在xib引用file`s owner,最主要就是知道file·s owner是谁,这样就可以在该文件使用bundle方法引用xib内容,或者使用outlet。 对了 这里说的拉线,是关于.h文件和xib文件,也就是定义一个IBOutlet与xib关联。并不是说使用bundle就不用再xib里面对files owner和view关联!!
xib还可以动态桥接,这些以后有空补回来!
这里是GCD初入门学习
这篇东西好久没写了,上次有心思写博客的时候是过年左右吧,并不是应付面试学习,当是看的是GCD深入理解,里面的东西确实很多,而且越看越发现自己需要补的知识就越多,到了最后都忘记自己是在学iOS线程这东西了。如果看的也觉得忒多的话,我这里给两个比较简单明了,而且结合起来能有不错理解的blog。
(1)关于多线程你看我就够了
(2)死锁的五个案例
第一个blog里面关于死锁的原因没解释的很清楚,因此我自己又找了一个blog,后面的解释的很清楚,还看不懂我也没办法了。
Pthreads
一般我们这些初级的,还用不到这么底层的东西,所以直接跳过,有兴趣的可以在操作系统的内容里面看到。
NSThread
在我的说法里就是需要自己管理线程的整个生命周期,这个肯定能说有好有坏,一般好的就是说自己管理效率上或者自定义方面比较好嘛,不好的肯定就是相对于封装好的使用比较麻烦嘛。但是这东西我们很多时候也会用例如 [NSThread currentThread];
具体的使用方法,以及有什么方法调用,我也不贴了,自己进去文件里面看更加详细。
NSOperation和NSOperationQueue
GCD
终于到了重点了。Grand Central Dispatch。苹果为多核处理器提出并行运算提出来的方案,其实也就是为了让多核能更好的使用罢了。因为一个系统需要同时执行的进程估计会很多吧,多了一个,但其实远远还不够,而且还要考虑作业调度的问题。。。下面科普一些术语。
串行&并发
这些术语描述当任务相对于其它任务被执行,任务串行执行就是每次只有一个任务被执行,任务并发执行就是在同一时间可以有多个任务被执行。
同步&异步
一个同步函数只在完成了它预定的任务后才返回。
一个异步函数,刚好相反,会立即返回,预定的任务会完成但不会等它完成。因此,一个异步函数不会阻塞当前线程去执行下一个函数。
临界区
就是一段代码不能被并发执行,也就是,两个线程不能同时执行这段代码。
死锁
两个(有时更多)东西——在大多数情况下,是线程——所谓的死锁是指它们都卡住了,并等待对方完成或执行其它操作。第一个不能完成是因为它在等待第二个的完成。但第二个也不能完成,因为它在等待第一个的完成。
上下文切换
一个上下文切换指当你在单个进程里切换执行不同的线程时存储与恢复执行状态的过程。
线程安全
线程安全的代码能在多线程或并发任务中被安全的调用,而不会导致任何问题(数据损坏,崩溃,等)。线程不安全的代码在某个时刻只能在一个上下文中运行。一个线程安全代码的例子是 NSDictionary 。你可以在同一时间在多个线程中使用它而不会有问题。另一方面,NSMutableDictionary 就不是线程安全的,应该保证一次只能有一个线程访问它。
并发并行Concurrency vs Parallelism
并发: 一个很短的时间间隔内同时发生两个线程
并行:同时运行两个线程
创建队列
//获取主线程
dispatch_queue_t queue = dispatch_get_main_queue();
- 主队列:这是一个特殊的 串行队列。什么是主队列,大家都知道吧,它用于刷新 UI,任何需要刷新 UI 的工作都要在主队列执行,所以一般耗时的任务都要放到别的线程执行。
//一般的写法
dispatch_queue_t queue= dispatch_queue_create("tk.bourne.testQueue", NULL);
- 自己创建的队列:凡是自己创建的队列都是 串行队列。其中第一个参数是标识符,用于 DEBUG 的时候标识唯一的队列,可以为空。大家可以看xcode的文档查看参数意义。
更新:自己可以创建 串行队列, 也可以创建 并行队列。看下面的代码(代码已更新),它有两个参数,第一个上面已经说了,第二个才是最重要的。
第二个参数用来表示创建的队列是串行的还是并行的,传入 DISPATCH_QUEUE_SERIAL 或 NULL 表示创建串行队列。传入 DISPATCH_QUEUE_CONCURRENT 表示创建并行队列。
- 全局并行队列:这应该是唯一一个并行队列,只要是并行任务一般都加入到这个队列。
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
创建任务
同步任务:不会另开线程 (SYNC)
dispatch_sync(, ^{
//code here
NSLog(@"%@", [NSThread currentThread]);
});异步任务:会另开线程 (ASYNC)
dispatch_async(, ^{
//code here
NSLog(@"%@", [NSThread currentThread]);
});
示例:
NSLog("之前 - %@", NSThread.currentThread())
dispatch_sync(dispatch_get_main_queue(), {
NSLog("sync - %@", NSThread.currentThread())
})
NSLog("之后 - %@", NSThread.currentThread())
这里只会输出“之前” ,因为后两个输出都被阻塞,原因是为什么呢?
当前使用主线程执行UI以及输出“sync”这段,但是这两个任务放在了当前的主线程队列---front- 刷新UI---输出“sync”--rear
但是因为刷新UI需要等输出“sync”完成了才能继续,但是串行执行任务的原因输出“sync”又把当前线程阻塞了,所以刷新UI也不能执行了。
对列组
队列组可以将很多队列添加到一个组里,这样做的好处是,当这个组里所有的任务都执行完了,队列组会通过一个方法通知我们。下面是使用方法,这是一个很实用的功能。
//1.创建队列组
dispatch_group_t group = dispatch_group_create();
//2.创建队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
//3.多次使用队列组的方法执行任务, 只有异步方法
//3.1.执行3次循环
dispatch_group_async(group, queue, ^{
for (NSInteger i = 0; i < 3; i++) {
NSLog(@"group-01 - %@", [NSThread currentThread]);
}
});
//3.2.主队列执行8次循环
dispatch_group_async(group, dispatch_get_main_queue(), ^{
for (NSInteger i = 0; i < 8; i++) {
NSLog(@"group-02 - %@", [NSThread currentThread]);
}
});
//3.3.执行5次循环
dispatch_group_async(group, queue, ^{
for (NSInteger i = 0; i < 5; i++) {
NSLog(@"group-03 - %@", [NSThread currentThread]);
}
});
//4.都完成后会自动通知
dispatch_group_notify(group, dispatch_get_main_queue(), ^{
NSLog(@"完成 - %@", [NSThread currentThread]);
});
线程同步
- 互斥锁 :给需要同步的代码块加一个互斥锁,就可以保证每次只有一个线程访问此代码块。
@synchronized(self) {
//需要执行的代码块
}
延时执行
perform
// 3秒后自动调用self的run:方法,并且传递参数:@"abc"
[self performSelector:@selector(run:) withObject:@"abc" afterDelay:3];GCD 可以使用 GCD 中的 dispatch_after 方法
// 创建队列
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// 设置延时,单位秒
double delay = 3;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delay * NSEC_PER_SEC)), queue, ^{
// 3秒后需要执行的任务
});NSTimer
NSTimer 是iOS中的一个计时器类,除了延迟执行还有很多用法,不过这里直说延迟执行的用法
[NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(run:) userInfo:@"abc" repeats:NO];
单例模式
@interface Tool : NSObject
+ (instancetype)sharedTool;
@end
@implementation Tool
static id _instance;
+ (instancetype)sharedTool {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_instance = [[Tool alloc] init];
});
return _instance;
}
@end
从其他线程回到主线程的方法
我们都知道在其他线程操作完成后必须到主线程更新UI。所以,介绍完所有的多线程方案后,我们来看看有哪些方法可以回到主线程。
- NSThread
//Objective-C
[self performSelectorOnMainThread:@selector(run) withObject:nil waitUntilDone:NO]; - GCD
//Objective-C
dispatch_async(dispatch_get_main_queue(), ^{
});