今天看到有人分享了一些面试题,发现自己好多都说不出来,再过几个月就要开始找工作了。趁此机会总结一下吧。
类别(category)与类扩展
类别的作用:在不修改原来类的基础上,为一个类扩展方法(一般是系统的类),如果与本类中的方法重名 会覆盖本类中方法(因为类别中不能使用super))。不建议在类别中添加成员变量,不过 仍然可以利用 runtime 实现setter 和 getter 方法 进行添加。
@interface ClassName (CategoryName)
@property (nonatomic, strong) NSString *str;
@end
//实现文件
#import "ClassName + CategoryName.h"
#import <objc/runtime.h>
static void *strKey = &strKey;
@implementation ClassName (CategoryName)
-(void)setStr:(NSString *)str
{
objc_setAssociatedObject(self, & strKey, str, OBJC_ASSOCIATION_COPY);
}
-(NSString *)str
{
return objc_getAssociatedObject(self, &strKey);
}
@end
类扩展:是category的一个特例 也可以叫做匿名分类。它的作用是为一个类添加一些私有的成员变量和方法。类扩展可以定义在.m文件中,也可以定义在.h文件中。
assgin
直接赋值,引用计数不变 ,一般用在 声明基础数据类型的成员变量
copy
深拷贝 声明NSString 用在不希望声明的NSString 不跟随赋值的字符串变化时, 用copy 拷贝的是内容 不是指针。
retain
浅拷贝 拷贝的是指针 不是内容 (会随着赋值字符串的改变而改变)
strong
强引用 持有对象 引用计数加一 当所用引用它的对象都释放,才会释放。
weak
弱引用 无法持有对象 在创建完 就会被释放 因为没有任何强指针引用它
有IBOutlet修饰的对象上多引入一个强指针
atomic / nonatomic
atomic是Objc使用的一种线程保护技术,基本上来讲,是防止在写未完成的时候被另外一个线程读取,造成数据错误。而这种机制是耗费系统资源的,所以在iPhone这种小型设备上,如果没有使用多线程间的通讯编程,那么nonatomic是一个非常好的选择。
nonatomic:只是简单的返回这个值。
线程
在iOS中有三种创建线程的方法(http://www.jianshu.com/p/0b0d9b1f1f19#)
(1)NSThread 轻量级 是经过苹果封装后的 一些属性调用起来很方便 但是生命周期还需要我们手动管理
// 创建
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:nil];
// 启动
[thread start];
或者
[NSThread detachNewThreadSelector:@selector(run:) toTarget:self withObject:nil];
常见方法
//取消线程
- (void)cancel;
//启动线程
- (void)start;
//判断某个线程的状态的属性
@property (readonly, getter=isExecuting) BOOL executing;
@property (readonly, getter=isFinished) BOOL finished;
@property (readonly, getter=isCancelled) BOOL cancelled;
//设置和获取线程名字
-(void)setName:(NSString *)n;
-(NSString *)name;
//获取当前线程信息
+ (NSThread *)currentThread;
//获取主线程信息
+ (NSThread *)mainThread;
//使当前线程暂停一段时间,或者暂停到某个时刻
+ (void)sleepForTimeInterval:(NSTimeInterval)time;
+ (void)sleepUntilDate:(NSDate *)date;
(2)GCD
合理利用CPU内核 自动管理线程的生命周期(创建线程、调度任务、销毁线程)
任务与队列
任务:有两种执行方式
>同步执行(sync):会阻塞当前线程 等待block中的任务执行完 然后才会继续执行
>异步执行(async):不会阻塞当前线程,当前线程会直接往下执行
队列:用于存放任务
放到队列里面的任务,GCD都会FIFO(先进先出)的取出来,不同的是
>串行队列:取出之后放到一个线程中执行
>并行队列:分别放到不同的线程中
GCD会根据系统资源控制并行的数量,所以任务很多的时候 并不会让所有任务同时执行。
(3)NSOPeration
是对GCD的封装
NSOperation:对应GCD的任务
NSOperationQueue:对应GCD的队列
NSOperation不能封装任务 但他的子类 NSInvocationOperation和NSBlockOperation可以
NSInvocationOperation
//1.创建NSInvocationOperation对象
NSInvocationOperation *operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(run) object:nil];
//2.开始执行
[operation start];
NSBlockOperation
//1.创建NSBlockOperation对象
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"%@", [NSThread currentThread]);
}];
//2.开始任务
[operation start];
并发执行:他会在主线程和其他多个线程执行
//1.创建NSBlockOperation对象
NSBlockOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
NSLog(@"%@", [NSThread currentThread]);
}];
//添加多个Block
for (NSInteger i = 0; i < 5; i++) {
[operation addExecutionBlock:^{
NSLog(@"第%ld次:%@", i, [NSThread currentThread]);
}];
}
//2.开始任务
[operation start];
懒加载 :用到的时候再去加载(getter)