#父类实现深拷贝时,子类如何实现深度拷贝.父类没有实现深拷贝时,子类如何实现深度拷贝.#
<(1)深拷贝同浅拷贝的区别: 浅拷贝是指针拷贝,对一个对象进行浅拷贝, 相当于对指向对象的指针进行复制,产生一个新的指向这个对象的指针,那么就是两个指针指向同一个对象,这个对象销毁后两个指针都应该置空.深拷贝是对一个对象进行拷贝,相当于对对象进行复制,产生一个新的对象,那么就有两个指针分别指向两个对象.当一个对象改变或者被销毁后拷贝出来的新对象不受影响.
(2)实现深拷贝需要实现NSCoying协议, 实现- (id)copyWithZone:(NSZone *)zone 方法.当对一个property属性含有copy修饰符的时候, 在进行赋值操作的时候实际上就是调用这个方法.
(3)父类实现深拷贝之后, 子类只要重写copyWithZone方法, 在方法内部调用父类的copyWithZone方法,之后实现自己的属性的处理
(4)父类没有实现深拷贝, 子类除了需要对自己的属性进行处理, 还要对父类的属性进行处理.>
#KVO, NSNotification, delegate及block区别
<(1)KVO就是cocoa框架实现的观察者模式, 一般同KVC搭配使用, 通过KVO可以监测一个值的变化, 比如View的高度变化. 是一对多的关系, 一个值的变化会通知所有的观察者.
(2)NSNotification是通知, 也是一对多的使用场景. 在某些情况下, KVO和NSNotification一样的, 都是状态变化之后告知对方. NSNotification的特点, 就是需要被观察者先主动发出通知, 然后观察者注册监听后再来进行响应, 比KVO多了发送通知的一步, 但是其优 点是监听不局限于属性的变化, 还可以对多种多样的状态变化进行监听, 监听范围广, 使用也更灵活.
(3) delegate 是代理, 就是我不想做的事情交给别人做. 比如🐶需要吃🍚,就通过delegate通知主人, 主人就会给他做饭,盛饭,倒水,这些操作, 这些狗都不需要关心, 只需要调用delegate (代理人) 就可以了, 由其他类完成所需要的操作. 所以delegate是一对一关系.
(4)block是delegate的另一种形式, 是函数式编程的一种形式. 使用场景跟delegate一样, 相比delegate更灵活, 而且代理的实现更直观.
(5) KVO一般的使用场景是数据, 需求是数据变化, 比如股票价格变化, 我们一般使用KVO (观察者模式).delegate一般的使用场景是行为, 需求是需要别人帮我做一件事情, 比如买卖股票, 我们一般使用delegate.
(6)Notification 一般是进行全局通知, 比如利好消息一出, 通知大家去买入. delegate是强关联, 就是委托和代理双方互相知道, 你委托别人买股票你就需要知道经纪人, 经纪人也不知道自己的客户.Notification是弱关联, 利好消息发出, 你不需要知道是谁发出也可以做出相应的反应, 同理发消息的人也不需要知道接收的人也可以正常发出消息.>
#将一个函数在主线程执行的4种方法#
<(1) GCD方法, 通过向主线程队列发送一个block块, 使block里的方法可以在主线程中执行.dispatch_asyanc(dispatch_get_main_queue( ), ^{
需要执行的方法 });
(2) NSOperation 方法
NSOperationQueue *mainQueue = [NSOperationQueue mainQueue]; 主队列
NSBlockOperation *operation = [NSBlockOperation blockOpertionWithBlock:^{
需要执行的方法
}];
[mainQueue addOperation:operation];
(3) NSThread 方法
[self performSelector:@selector(method) onThread:[NSThread mainThread] withObject:nil waitUntilDone:YES modes:nil];
[self performSelectorOnMainThread:@selector(method) withObject:nil];
(4) RunLoop方法
[NSRunLoop mainRunLoop] performSelector:@selector(method) withObject:nil];>
#如何让计时器调用一个类方法#
<(1) 计时器只能调用实例方法,但是可以在这个实例方法里面调用静态方法.
(2) 使用计时器需要注意, 计时器一定要加入RunLopp中, 并且选好model才能运行.scheduleTimerWithTimeInterval方法创建一个计时器并加入到RunLoop中所以可以直接使用.
(3) 如果计时器的reoeats选择YES说明这个计时器会重复执行, 一定要在合适的时机调用计时器的invalid. 不能在dealloc中调用,因为一旦设置为repeats 为YES, 计时器会强持有self, 导致dealloc永远都不会被调用,这个类就永远无法被释放. 比如可以在viewDidDisappear中调用, 这样当类需要被回收的时候就可以正常进入dealloc中了.
[NSTimer scheduledTimerWithTimerInterval:1 target:self selector:@selector(timerMethod ) userInfo:nil repeats:YES];
- (void)timerMethod
{
调用类方法
[[self class] staticMethod];
}
- (void)invalid
{
[timer invalid];
tiemr = nil ;
}>
#如何重写类方法#
< (1) 在子类中实现一个同基类名字一样的静态方法
(2) 在调用的时候不要使用类名调用, 而是使用[self class]的方式调用. 原理, 用类名调用是早绑定, 在编译期绑定, 用[self class] 是晚绑定, 在运行时决定调用你是个方法.>
#NSTimer创建后, 会在哪个线程运行#
< (1) 用scheduledTimerWithTimerInterval创建的, 在哪个线程创建就会被加入哪个线程的RunLoop中运行在哪个线程.
(2) 自己创建的Timer, 加入到哪个线程的RunLoop中就运行在哪个线程.>
#id和NSObject *的区别#
< (1) id是一个 objc_object 结构体指针, 定义是typedef struct objc_object *id
(2) id可以理解为指向对象的指针. 所有oc的对象 id都可以指向, 编译器不会做类检查, id调用任何存在的方法都不会再编译阶段报错, 当然如果这个 id指向的对象没有这个方法, 该崩溃还是会崩溃.
(3) NSObject *指向的必须是NSObject的子类, 调用的也只能是NSObject里面的方法否则就要做强制类型转换.
(4) 不是所有的OC对象都是NSObject的子类, 还有一些是继承自NSProxy.NSObject *可以指向的类型是id的子集.>
#iOS 核心框架#
< (1) CoreAnimation
(2) CoreGraphics
(3) CoreLocation
(4) AVFoundation
(5) Foundation>
#iOS 核心机制
<(1) UITableView 的重用机制
(2) ObjC内存管理机制; 自动释放池, ARC如何实现
(3) RunLoop 的运行机制
(4) RunRime 的运行机制
(5) Block的定义 特性 内存区域 如何实现
(6) Responder Chain
(7) NSOperation
(8)GCD>
#数据结构#
<(1) 8大排序算法
(2) 二叉树实现
(3) 二分查找实现>
#面向对象编程#
<(1) 封装.继承.多态
(2) 设计模式6个原则
(3) 设计一个类的功能, 如何划分类的权利 (单一职责)
(4) 接口隔离
(5) 如果有一个鸟类, 有飞的动作, 一个鸵鸟继承它是合适的吗(里氏替换)
(6) 类之间的依赖如何依赖耦合度最小(依赖倒转)(高层依赖低层,低层不能依赖高层.依赖接口,不能依赖具体的类.)
(7) 如果A要调用C函数, 但C是B的成员类, 应该如何设计? (迪米特法则)
(8) 如何设计类, 能做到只增加代码, 而不修改代码,有哪些经验 (开放封闭)通过设计模式解决.>
#计算机技术#
<(1) 计算机网络: TCP/TP , HTTPCDN, SPDY
(2) 计算机安全: RSA, AES, DES
(3) 操作系统: 线程, 进程, 堆栈, 死锁, 调度算法>
#iOS新特性 新技术#
<(1) iOS7 UIDynamic , SpritKit , 新布局, 扁平化
(2) iOS8 应用程序扩展, HealthKit, SceneKit, CoreLocation, TouchID, PhotoKit
(3) iOS9
(4) Apple Watch>
#第三方库#
<(1) SDWebImage
(2) AFNetwork
(3) JSONKit(已经不用了)
(4) wax>