面试知识点总汇

Objc
一.三大特性
1.封装_点语法
1> 本质
//如下代码有什么问题
- (void)setName:(NSString *)name {
  self.name = name;  
}
- (NSString *)name {
  return self.name;
}
 
点语法的本质是调用类的getter方法和setter方法,若是类中没有getter方法和setter方法就不能使用点语法。
 
2.继承
1> 如何实现多重继承
消息转发    forwardingTargetForSelector   methodSignatureForSelector   forwardInvocation
delegate和protocol  
类别   
 
3.多态
1> 什么是多态
  多态:不一样对象以本身的方式响应相同的消息的能力叫作多态。
  因为每一个类都属于该类的名字空间,这使得多态称为可能。类定义中的名字和类定义外的名字并不会冲突。类的实例变量和类方法有以下特色:
  • 和C语言中结构体中的数据成员同样,类的实例变量也位于该类独有的名字空间。
  • 类方法也一样位于该类独有的名字空间。与C语言中的方法名不一样,类的方法名并非一个全局符号。一个类中的方法名不会和其余类中一样的方法名冲突。两个彻底不一样的类能够实现同一个方法。
方法名是对象接口的一部分。对象收到的消息的名字就是调用的方法的名字。由于不一样的对象能够有同名的方法,因此对象必须能理解消息的含义。一样的消息发给不一样的对象,致使的操做并不相同。
  多态的主要好处就是简化了编程接口。它允许在类和类之间重用一些习惯性的命名,而不用为每个新加的函数命名一个新名字。这样,编程接口就是一些抽象的行为的集合,从而和实现接口的类区分开来。
  Objective-C支持方法名的多态,但不支持参数和操做符的多态。
 
2> OC中如何实现多态
     在Objective-C中是经过一个叫作selector的选取器实现的。在Objective-C中,selector有两个意思, 当用在给对象的源码消息时,用来指方法的名字。它也指那个在源码编译后代替方法名的惟一的标识符。 编译后的选择器的类型是SEL有一样名字的方法、也有一样的选择器。你可使用选择器来调用一个对象的方法。
     选取器有如下特色:
     * 全部同名的方法拥有一样的选取器
     * 全部的选取器都是不同的
     (1) SEL和@selector
          选择器的类型是 SEL。@selector指示符用来引用选择器,返回类型是SEL。
          例如:
         SEL responseSEL;      
                responseSEL = @selector(loadDataForTableView:);     
         能够经过字符串来获得选取器,例如:
               responseSEL = NSSelectorFromString(@"loadDataForTableView:");
         也能够经过反向转换,获得方法名,例如:
               NSString  *methodName = NSStringFromSelector(responseSEL);
     (2) 方法和选取器
         选取器肯定的是方法名,而不是方法实现。这是多态性和动态绑定的基础,它使得向不一样类对象发送相同的消息成为现实;不然,发送     消息和标准C中调用方法就没有区别,也就不可能支持多态性和动态绑定。
         另外,同一个类的同名类方法和实例方法拥有相同的选取器。
     (3) 方法返回值和参数类型
         消息机制经过选取器找到方法的返回值类型和参数类型,所以,动态绑定(例:向id定义的对象发送消息)须要同名方法的实现拥有相     同返回值类型和相同的参数类型;不然,运行时可能出现找不到对应方法的错误。
         有一个例外,虽然同名类方法和实例方法拥有相同的选取器,可是它们能够有不一样的参数类型和返回值类型。
3> 动态绑定
 
二.类和对象
1.category
1> 分类 拓展 协议中哪些能够声明属性?
均可以,但分类和协议建立的属性只至关于方法,可是内部没有对成员变量的操做(没法建立成员变量),拓展能够(私有成员变量)
代理中声明属性,没有实际建立成员变量,至关于声明了属性名对应的访问方法,遵照协议的类须要实现对应的访问器方法,不然运行报错
分类中声明属性,警告提示须要手动实现访问器方法(Swift中叫计算型属性),而分类中不能建立成员变量,能够在手写访问器方法中使用runtime的 objc_setAssociatedObject方法关联对象间接建立属性(静态库添加属性)
拓展里能够声明属性,直接可使用
2> 继承和类别的区别
1> 使用继承:
1.1> 添加新方法和父类方法一致,但父类方法仍须要使用
1.2> 添加新属性
2> 类别:
2.1> 针对系统提供的一些类,系统自己不提倡继承,由于这些类的内部实现对继承有所限制(NSString initWithFormat继承崩溃)
2.2> 类别能够将本身构建的类中的方法进行分组,对于大型的类,提升可维护性
3> 分类的做用
将类的实现分散到多个不一样文件或多个不一样框架中。
建立对私有方法的前向引用。
向对象添加非正式协议。
(非正式协议:即NSObject的分类,声明方法能够不实现,OC2.0之前protocal没有@optional,主要使用分类添加可选协议方法
oc中声明方法不实现,不调用则只警告不报错
正式协议的优势:可继承,泛型约束
如kvo的 observeValueForKeyPath属于nsobject的分类,且不须要调父类,说明可选实现该方法,没警告多是编译器规则过滤)
4> 分类的局限性
没法向类中添加新的实例变量,类别没有位置容纳实例变量。
名称冲突,即当类别中的方法与原始类方法名称冲突时,类别具备更高的优先级。类别方法将彻底取代初始方法从而没法再使用初始方法。
没法添加实例变量的局限可使用字典对象解决。
2.extension
3.protocol
 
三.Foundation
1.字符串
1> 字符串比较  
NSString *a = @“hello”;
NSString *b = [NSString stringWithFormat:@hello”];
if (a == b){
     nslog(@“a==b”);  }
if ([a isEqualToString: b]){
     nslog(@“a isEqualToString b”);  }
== 比较变量中保存的数值(地址)   速度快    内容同,可能地址不一样(常量区,堆区)
isEqualTo 比较字符串   很是耗时
 
2> 字符串截取
截取字符串”20 | http://www.baidu.com”中,”|”字符前面和后面的数据,分别输出它们。
NSString * str = @"20 | http://www.baidu.com";
NSArray *array = [str componentsSeparatedByString:@"|"]; //这是分别输出的截取后的字符串
for (int i = 0; i<[array count]; ++i) {
NSLog(@"%d=%@",i,[array objectAtIndex:i]);
}
 
3> 格式
NSString *str1 = [NSString stringWithFormat:@"a"b”];    //报错,a”后加b非法
NSString *str2 = [NSString stringWithFormat:@“a""b”];   //显示  ab
NSString *str3 = [NSString stringWithFormat:@“a\"b”];   //显示  a”b  反斜杠转义
 
 
2.NSArray和NSDictionary
1> iOS遍历数组/字典的方法
数组:  for循环  for in    enumerateObjectsUsingBlock(正序)    enumerateObjectsWithOptions:usingBlock:(多一个遍历选项,不保证顺序)
字典:
1. for(NSString *object in [testDic allValues])
2. for(id akey in [testDic allKeys]){
[sum appendString:[testDic objectForKey:akey]];  }
3. [testDic enumerateKeysAndObjectsUsingBlock:^(idkey,idobj,BOOL*stop) {
        [sum appendString:obj];  } ];
速度:  对于数组, 加强for最快,普通for和block速度差很少,加强最快是由于加强for语法会对容器里的元素的内存地址创建缓冲,遍历的时候直接从缓冲中取元素地址而不是经过调用方法来获取,因此效率高.这也是使用加强for时不能在循环体中修改容器元素的缘由之一(能够在循环体中添加标记,在循环体外修改元素)
对于字典,allValues最快,allKey和block差很少,缘由是allKey须要作objcetForKey的方法
3.NSValue NSNumber 
1> 归档视图尺寸,坐标
 
4.其余
nil Nil null NSNull 的区别
 
四.关键字
1.@property
1>readwrite,readonly,assign,retain,copy,nonatomic属性的做用
@property是一个属性访问声明,扩号内支持如下几个属性:
1.1> getter setter
getter=getterName,setter=setterName,设置setter与getter的方法名
1.2> weak assign strong copy
assign  用于非指针变量。用于基础数据类型 (例如NSInteger)和C数据类型(int, float, double, char, 等),另外还有id,其setter方法直接赋值,不进行任何retain操做
weak    用于指针变量,比assign多了一个功能,当对象消失后自动把指针变成nil,因为消息发送给空对象表示无操做,这样有效的避免了崩溃(野指针),为了解决原类型与循环引用问题
strong  用于指针变量,setter方法对参数进行release旧值再retain新值
copy    用于指针变量,setter方法进行copy操做,与retain处理流程同样,先旧值release,再copy出新的对象,retainCount为1。这是为了减小对上下文的依赖而引入的机制。copy是在你不但愿a和b共享一块内存时会使用到。a和b各自有本身的内存。
1.3> readwrite,readonly,设置可供访问级别
1.4> nonatomic,非原子性访问,不加同步,多线程并发访问会提升性能。注意,若是不加此属性,则默认是两个访问方法都为原子型事务访问。因此约定俗成只在主线程更新UI,防止多线程设置UI属性,出现资源抢夺现象
2> 如何避免循环引用 
两个对象相互强引用,都没法release,解决办法为一个使用strong,一个使用assign(weak)
3> delegate的属性为何使用assign/weak
避免出现循环引用,场景如UITableViewController强引用视图UITableView,而该视图的代理又是控制器,为避免循环引用,让delegate为弱引用
 
2.copy
1> copy的使用场景
当多个指针指向同一个对象时,为避免一个指针对对象的改动对其余指针的使用产生影响,使用copy来建立对象的副本
如页面间传值使用copy,A向B控制器传属性(属性为自定义对象),为避免因A的属性变化对B的属性产生影响
再如多人开发或封装库,在不明确传入值为可变仍是不可变的状况下,使用copy更安全
2> 什么是深拷贝浅拷贝
对于非容器类对象,不可变对象进行copy操做为浅拷贝,引用计数器加1,其余三种为深拷贝
对于容器类对象,基本和非容器类对象一致,但注意其深拷贝是对象自己是对象复制,其中元素仍为指针复制,系统将initWithArray方法归为了元素深拷贝,但其实若是元素为不可变元素,仍为指针复制,使用归解档能够实现真正的深拷贝,元素也是对象拷贝NSArray* trueDeepCopyArray = [NSKeyedUnarchiver unarchiveObjectWithData:
[NSKeyedArchiver archivedDataWithRootObject: array]];
3> 字符串何时使用copy,strong
属性引用的对象由两种状况,可变和不可变字符串
引用对象不可变状况下,copy和strong同样,copy为浅拷贝
引用对象可变状况下,若是但愿属性跟随引用对象变化,使用strong,但愿不跟随变化使用copy
4> 字符串所在内存区域
@“abc” 常量区   stringwithformat 堆区
5> mutablecopy和copy    @property(copy) NSMutableArray *arr;这样写有什么问题
mutablecopy返回可变对象,copy返回不可变对象
6> 如何让自定义类可使用copy修饰符
实现<NSCopying>协议,重写copyWithZone方法
 
3.全局&静态变量
1.全局变量和静态变量的区别
1> 修饰符 
     全局变量在声明源文件以外使用,须要extern引用一下;
     静态变量使用static来修饰
2> 存储地址
     二者都是存储在静态存储区,非堆栈上,它们与局部变量的存储分开
3> 生命周期
     二者都是在程序编译或加载时由系统自动分配的,程序结束时消亡
4> 外部可访问性                                
     全局变量在整个程序的任何地方都可访问,而静态变量至关于面向对象中的私有变量,他的可访问性只限定于声明它的那个源文件,即做用于仅局限于本文件中
 
五.runtime/消息转发机制
1> 什么是runtime
runtime是一套比较底层的纯C语言API, 属于1个C语言库, 包含了不少底层的C语言API。
在咱们平时编写的OC代码中, 程序运行过程时, 其实最终都是转成了runtime的C语言代码, runtime算是OC的幕后工做者,objc_msgSend
2> runtime干什么用,使用场景
runtime是属于OC的底层, 能够进行一些很是底层的操做(用OC是没法现实的, 很差实现)
在程序运行过程当中, 动态建立一个类(好比KVO的底层实现)  objc_allocateClassPair,class_addIvar,objc_registerClassPair
在程序运行过程当中, 动态地为某个类添加属性\方法, 修改属性值\方法(修改封装的框架)  objc_setAssociatedObject   object_setIvar
遍历一个类的全部成员变量(属性)\全部方法(字典转模型,归解档)  class_copyIvarList class_copyPropertyList  class_copyMethodList
2.消息机制
1> 消息转发的原理
当向一个对象发送消息时,objc_msgSend方法根据对象的isa指针找到对象的类,而后在类的调度表(dispatch table)中查找selector。若是没法找到selector,objc_msgSend经过指向父类的指针找到父类,并在父类的调度表(dispatch table)中查找selector,以此类推直到NSObject类。一旦查找到selector,objc_msgSend方法根据调度表的内存地址调用该实现。 经过这种方式,message与方法的真正实如今执行阶段才绑定。
    为了保证消息发送与执行的效率,系统会将所有selector和使用过的方法的内存地址缓存起来。每一个类都有一个独立的缓存,缓存包含有当前类本身的 selector以及继承自父类的selector。查找调度表(dispatch table)前,消息发送系统首先检查receiver对象的缓存。
 缓存命中的状况下,消息发送(messaging)比直接调用方法(function call)只慢一点点点点。
2> SEL isa super cmd 是什么
sel: 一种类型,表示方法名称,相似字符串(可互转)
isa:在方法底层对应的objc_msgSend调用时,会根据isa找到对象所在的类对象,类对象中包含了调度表(dispatch table),该表将类的sel和方法的实际内存地址关联起来
super_class:每个类中还包含了一个super_class指针,用来指向父类对象
_cmd在Objective-C的方法中表示当前方法的selector,正如同self表示当前方法调用的对象实例
IMP定义为 id (*IMP) (id, SEL, …)。这样说来, IMP是一个指向函数的指针,这个被指向的函数包括id(“self”指针),调用的SEL(方法名),再加上一些其余参数.说白了IMP就是实现方法
3> 动态绑定
—在运行时肯定要调用的方法
动态绑定将调用方法的肯定也推迟到运行时。在编译时,方法的 调用并不和代码绑定在一块儿,只有在消实发送出来以后,才肯定被调用的代码。经过动态类型和动态绑定技术,您的代码每次执行均可以获得不一样的结果。运行时因 子负责肯定消息的接收者和被调用的方法。运行时的消息分发机制为动态绑定提供支持。当您向一个动态类型肯定了的对象发送消息时,运行环境系统会经过接收者 的isa指针定位对象的类,并以此为起点肯定被调用的方法,方法和消息是动态绑定的。并且,您没必要在Objective-C 代码中作任何工做,就能够自动获取动态绑定的好处。您在每次发送消息时,特别是当消息的接收者是动态类型已经肯定的对象时,动态绑定就会例行而透明地发生。
 
六.内存管理
1.内存区域
1>堆和栈的区别
管理方式:对于栈来说,是由编译器自动管理,无需咱们手工控制;对于堆来讲,释放工做由程序员控制,容易产生memory leak。
申请大小:
栈是向低地址扩展的数据结构,是一块连续的内存的区域,栈顶的地址和栈的最大容量是系统预先规定好的,能从栈得到的空间较小。
堆是向高地址扩展的数据结构,是不连续的内存区域,由于系统是用链表来存储的空闲内存地址的,天然是不连续的,而链表的遍历方向是由低地址向高地址。堆的大小受限于计算机系统中有效的虚拟内存,所以堆得到的空间比较灵活,也比较大。
碎片问题:
对于堆来说,频繁的new/delete势必会形成内存空间的不连续,从而形成大量的碎片,使程序效率下降。对于栈来说,则不会存在这个问题,由于栈是先进后出的队列,他们是如此的一一对应,以致于永远都不可能有一个内存块从栈中间弹出
分配方式:
堆都是动态分配的,没有静态分配的堆。栈有2种分配方式:静态分配和动态分配。静态分配是编译器完成的,好比局部变量的分配。动态分配由alloca函数进行分配,可是栈的动态分配和堆是不一样的,他的动态分配是由编译器进行释放,无需咱们手工实现。
分配效率:
栈是机器系统提供的数据结构,计算机会在底层对栈提供支持:分配专门的寄存器存放栈的地址,压栈出栈都有专门的指令执行,这就决定了栈的效率比较高。堆则是C/C++函数库提供的,它的机制是很复杂的。
2> iOS内存区域
2.1> 栈区
由编译器自动分配释放,存放函数的参数值,局部变量的值等.其操做方式相似于数据结构中的栈.
2.2> 堆区
通常由程序员分配释放,若程序员不释放,程序结束时由系统回收
2.3> 全局区(静态区)
全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域,未初始化的全局变量和未初始化的静态变量相邻的另外一块区域.
全局区分为未初始化全局区: .bss段 和初始化全局区: data段.
2.4> 常量区
常量字符串就是放在常量区
2.5> 代码区
存放函数体的二进制代码
 
2. 字符串的内存管理
建立字符串的内存空间  堆  常量区
3. 你是如何优化内存管理
1> 使用ARC
2> 延迟加载   懒加载    
3> 重用   在正确的地方使用reuseIndentifier  
4> 缓存    NSCache 保存计算数据
5> 处理内存警告      移除对缓存,图片 object 和其余一些能够重建立的 objects 的强引用
 5.1> app delegate 中使用 `applicationDidReceiveMemoryWarning:` 的方法
 5.2> 自定义 UIViewController 的子类 (subclass) 中覆盖 `didReceiveMemoryWarning`
 5.3> 在自定义类中注册并接收 UIApplicationDidReceiveMemoryWarningNotification 的通知 
6> 重用大开销对象  NSDateFormatter 和 NSCalendar    懒加载/单例  _formatter.dateFormat = @"EEE MMM dd HH:mm:ss Z yyyy”; 设置和建立速度同样慢
7> 自动释放池  手动添加自动释放池
8> 是否缓存图片 imageNamed  imageWithContentOfFile
9> 混编
10> 循环引用  delegate block nstimer
11>  移除 kvo  nsnotificationcenter   并未强引用,只记录内存地址,野指针报错  UIViewController自动移除  通常在dealloc中
13> performselector 延迟操做   [NSObject cancelPreviousPerformRequestsWithTarget:self]
 
4. 循环引用
delegate属性的内存策略 
block循环引用   实际场景
5. autorelease的使用
1> 工厂方法为何不释放对象
不少类方法为了在代码块结束时引用的对象不会因无强引用而被释放内存采用自动释放的方式,当其最近的自动释放池释放时该对象才会释放.
2> ARC下autorelease的使用场景
ARC中手动添加autoreleasepool可用于提早释放使用自动释放策略的对象,防止大量自动释放的对象堆积形成内存峰值太高.
3> 自动释放池如何工做
自动释放池时栈结构,每一个线程的runloop运行时都会自动建立自动释放池,程序员能够代码手动建立自动释放池,自动释放的对象会被添加到最近的(栈顶)自动释放池中,系统自动建立的自动释放池在每一个运行循环结束时销毁释放池并给池中全部对象发release消息,手动建立释放池在所在代码块结束时销毁释放池并发消息统一release
  
避免内存峰值
SDWebimage中加载gif图片  大循环
栈结构 栈顶
统一发release消息
5> ARC和MRC的混用
5.1> MRC>ARC
把MRC的代码转换成ARC的代码,删除内存管理操做(手动)
xcode提供了自动将MRC转换成ARC的功能,操做菜单栏edit -> Refacotor(重构) -> Convert to Objective-C ARC
5.2> ARC>MRC
在ARC项目中继续使用MRC编译的类,在编译选项中标识MRC文件便可"-fno-objc-arc"
在MRC项目中继续使用ARC编译的类在编译选项中标识MRC文件便可"-fobjc-arc
6> NSTimer的内存管理
如下代码有什么问题?
@interface SvCheatYourself () {
    NSTimer *_timer;
}

@end

@implementation SvCheatYourself

- (id)init {
    self = [super init];
    if (self) {
        _timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(testTimer:) userInfo:nil repeats:YES];
    }
    return self;
}

- (void)dealloc {
    [_timer invalidate];
}

- (void)testTimer:(NSTimer*)timer{
    NSLog(@"haha!");
}
@end
1)timer都会对它的target进行retain,对于重复性的timer,除非手动关闭,不然对象不会释放,场景:导航控制器关联的控制器没法销毁
2)NSTimer要加到异步线程中,防止线程繁忙致使定时器失准
3)timer必须加入到runloop中才会有效,主线程runloop默认开启,异步线程手动启动
4)注意runloop模式
 
7>  ARC 的实现原理
在程序预编译阶段,将 ARC 的代码转换为非 ARC 的 代码,自动加入 release、autorelease、retain
 
3.跨平台
3> OC和C框架对象引用
oc和c 桥接 三个桥接关键字都是干么的 __bridge  不更改归属权  __bridge_transfer 全部权给OC   __bridge_retain 解除OC的全部权
 
ios5/6/7/8 内存方面的区别
 
ios5.自动引用计数 (ARC)
ios6.UICollectionView ( 内存重用机制,图片展现瀑布流实现 )  在didReceiveMemoryWarning中处理内存(6以前在ViewDidUnload中)  http://blog.csdn.net/likendsl/article/details/8199350
ios7.iOS7之后强制使用ARC
ios8
 
4.MRC
 
七.数据传递
1.block
1> block属性为何用copy?
栈->堆
2> block使用注意什么?
循环引用 
__block 修饰局部变量,这个变量在 block 内外属于同一个地址 上的变量,能够被 block 内部的代码修改
3> block的主要使用场景 ?
动画
数组字典排序遍历
回调状态
错误控制
多线程GCD
4>block原理
block属性是指向结构体的指针,
 
2.Delegate
4> 何时用delegate,何时用Notification
delegate针对one-to-one关系,而且reciever能够返回值给sender,notification 能够针对one-to-one/many/none,reciever没法返回值给sender.因此,delegate用于sender但愿接受到 reciever的某个功能反馈值,notification用于通知多个object某个事件。
5> delegate和block
block使代码更紧凑,便于阅读,delegate能够设置必选和可选的方法实现,相比block
block能够访存局部变量. 不须要像之前的回调同样,把在操做后全部须要用到的数据封装成特定的数据结构, 你彻底能够直接访问局部变量.
 
3.KVC和KVO
1> 如何调用私有变量      如何修改系统的只读属性      KVC的查找顺序
KVC在某种程度上提供了访问器的替代方案。不过访问器方法是一个很好的东西,以致于只要是有可能,KVC也尽可能再访问器方法的帮助下工做。为了设置或者返回对象属性,KVC按顺序使用以下技术:
①检查是否存在-<key>、-is<key>(只针对布尔值有效)或者-get<key>的访问器方法,若是有可能,就是用这些方法返回值;
检查是否存在名为-set<key>:的方法,并使用它作设置值。对于 -get<key>和 -set<key>:方法,将大写Key字符串的第一个字母,并与Cocoa的方法命名保持一致;
②若是上述方法不可用,则检查名为-_<key>、-_is<key>(只针对布尔值有效)、-_get<key>和-_set<key>:方法;
③若是没有找到访问器方法,能够尝试直接访问实例变量。实例变量能够是名为:<key>或_<key>;
④若是仍为找到,则调用valueForUndefinedKey:和setValue:forUndefinedKey:方法。这些方法的默认实现都是抛出异常,咱们能够根据须要重写它们。
2> 什么是键-值,键路径是什么
模型的性质是经过一个简单的键(一般是个字符串)来指定的。视图和控制器经过键来查找相应的属性值。在一个给定的实体中,同一个属性的全部值具备相同的数据类型。键-值编码技术用于进行这样的查找—它是一种间接访问对象属性的机制。
键路径是一个由用点做分隔符的键组成的字符串,用于指定一个链接在一块儿的对象性质序列。第一个键的性质是由先前的性质决定的,接下来每一个键的值也是相对于其前面的性质。键路径使您能够以独立于模型实现的方式指定相关对象的性质。经过键路径,您能够指定对象图中的一
个任意深度的路径,使其指向相关对象的特定属性。
 
3> 什么是KVC
3> 什么是KVO
 
4> kvo的实现机制
当某个类的对象第一次被观察时,系统就会在运行时动态地建立该类的一个派生类,在这个派生类中重写原类中被观察属性的setter方法,派生类在被重写的setter方法实现真正的通知机制(Person->NSKVONotifying_Person).
派生类重写了 class 方法以“欺骗”外部调用者它就是起初的那个类。而后系统将这个对象的isa指针指向这个新诞生的派生类,所以这个对象就成为该派生类的对象了,于是在该对象上对setter的调用就会调用重写的setter,从而激活键值通知机制。此外,派生类还重写了dealloc方法来释放资源。
5> KVO计算属性   设置依赖键
监听的某个属性可能会依赖于其它多个属性的变化(相似于swift,能够称之为计算属性),无论所依赖的哪一个属性发生了变化,都会致使计算属性的变化,此时该属性若是不能经过set方法来监听(如get中进行计算
- (NSString *)accountForBank {

    return [NSString stringWithFormat:@“%@ for %@", self.accountName, self.bankCodeEn];
}
),则能够设置依赖键,两种方法:
1>
+ (NSSet *)keyPathsForValuesAffectingValueForKey:(NSString *)key {

    NSSet *keyPaths = [super keyPathsForValuesAffectingValueForKey:key];

    if ([key isEqualToString:@"accountForBank"]) {

        keyPaths = [keyPaths setByAddingObjectsFromArray:@[@"accountName", @"bankCodeEn"]];
    }

    return keyPaths;
}
 
2>
+ (NSSet *)keyPathsForValuesAffectingAccountForBank {

    return [NSSet setWithObjects:@"accountBalance", @"bankCodeEn", nil];
}
 
6> KVO集合属性   
可对可变集合的元素改变进行监听(如添加、删除和替换元素),使用集合监听对象
 
使用KVO
重写class
 
5> kvo使用场景
①实现上下拉刷新控件 contentoffset
②webview混合排版 contentsize
③监听模型属性实时更新UI
 
4.栈结构&队列
栈结构先进后出,iOS中有navigationcontroller的子控制器,autoreleasepool
队列先进先出,
 
八.其余
1.int和NSInteger的区别 
NSInteger表示当前cpu下整型所占最大字节,不一样CPU的long型所占字节不一样,32位int4 long4,64位int4,long8
2.import和include
import能够避免重复包含
3.@class   
避免循环引用头文件
 
UI
一.控件
1.属性
1> frame和bounds的区别
        frame:可表示尺寸和位置,与父视图坐标系的关系,位置以本身的左上角为原点,可用于形变和位移
bounds:可表示尺寸和位置,与自身视图坐标系的关系,大多数状况(滚动视图的子视图等除外)以本身的中心点为原点,可用于形变
center:只表示位置,表示本身中心的坐标,可用于位移
2> trasform
修改位移\形变\旋转,transform不一样于board\center\frame,前者中记录的是形变的数据,不发生形变其值是空的,因此咱们须要新建结构体,用CGAffineTransform(仿射变换)函数给对象结构体属性赋值,然后者是控件的固有属性,内存数据是始终存在的,当咱们用他们作移动等操做时,是改变其值,因此是结构体赋值三步曲,不用CG的函数
使用情景区别: transform通常用于有来有回的变化,而frame是有去无回
2.UIScrollView
1> contentsize、contentoffset、contentinset的区别
内容视图的尺寸 
内容视图当前位置相对滚动视图frame的偏移量
内容视图相对滚动视图frame的展现原点
 
3.UITableview
1> 自定义高度
1.1>新建一个继承自UITableViewCell的类
1.2>重写initWithStyle:reuseIdentifier:方法
1.3>添加全部须要显示的子控件(不须要设置子控件的数据和frame,  子控件要添加到contentView中)
1.4>进行子控件一次性的属性设置(有些属性只须要设置一次, 好比字体\固定的图片)
1.5>提供2个模型
数据模型: 存放文字数据\图片数据
frame模型: 存放数据模型\全部子控件的frame\cell的高度
1.6>cell拥有一个frame模型(不要直接拥有数据模型)
1.7>重写frame模型属性的setter方法: 在这个方法中设置子控件的显示数据和frame
2> 自定义高度原理
A 手动计算
1>  因为heightForRow比cellForRow方法先调用,建立frame模型包含微博模型,重写微博模型赋值set方法,提早计算cell子控件的frame并保存,heightForRow方法中取出frame模型中保存的高度,实现自定义高度cell
2>  设置最大尺寸、文本属性,根据文本内容计算正文内容展现尺寸
3>  cellForRow中建立自定义cell包含frame属性,重写frame属性set方法建立cell子控件并赋值frame模型保存的子控件尺寸 
B. 自动计算
1>  首先设置行高使用autolayout自动计算并预估高度
2>  在stroboard中对cell内容进行自动布局,注意设置图片距离底部约束,cellForRow中建立storyboard中对应标记的自定义cell
3>  因为正文内容的不肯定性,设置label多行,拖线图片高度约束,根据图片有无,设置代码设置高度约束
 
4.UICollectionView
1> 如何实现瀑布流,流水布局
1.1> 使用UICollectionView
1.2> 使用自定义的FlowLayout
1.3> 须要在layoutAttributesForElementsInRect中设置自定义的布局(item的frame)
1.4> 在 prepareLayout中计算布局
1.5> 遍历数据内容,根据索引取出对应的attributes(使用layoutAttributesForCellWithIndexPath),根据九宫格算法设置布局
1.6> 细节1: 实时布局,重写shouldInvalidateLayoutForBoundsChange(bounds改变从新布局,scrollview的contentoffset>bounds)
1.7> 细节2: 计算设置itemsize(保证内容显示完整,uicollectionview的content size是根据itemize计算的),根据列最大高度/对应列数量求出,最大高度累加获得
1.8> 细节3: 追加item到最短列,避免底部良莠不齐.
 
2> 和UITableView的使用区别
1)必须使用下面的方法进行Cell类的注册:
- (void)registerClass:forCellWithReuseIdentifier:
- (void)registerClass:forSupplementaryViewOfKind:withReuseIdentifier:
- (void)registerNib:forCellWithReuseIdentifier:
2)collectionView与tableView最大的不一样点,collectionView必需要使用本身的layout(UICollectionView Layout
如:
    UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
    flowLayout.itemSize = CGSizeMake(52, 52);               // cell大小
    flowLayout.minimumInteritemSpacing = 1;                 // cell间距
    flowLayout.minimumLineSpacing = 1;                      // cell行距
    flowLayout.sectionInset = (UIEdgeInsets){81,1,1,1};     // cell边距

 

建立collectionView须要带Layout的初始化方法:
- (id)initWithFrame:(CGRect)frame collectionViewLayout:(UICollectionViewLayout *)layout;
 
5.UIImage
1> 有哪几种加载方式
1.1> 二进制    imageWithData
1.2> Bundle    imageWithName  
1.3> 本地路径   imageWithContentOfFile
1.4> 
 
6.webview
1>解决webview的内存占用和泄露
 
7.描述九宫格算法
1>   1> 根据格子宽appW高appH和每行格数totalCol计算格子间隙marginX
CGFloat marginX = (self.view.frame.size.width - totalCol * appW)/(totalCol + 1);
2>   2> 根据序号i和每行格数totalCol计算行号列号   
  int row = i / totalCol;
  int col = i % totalCol;

3>   3> 根据格子间隙、格子宽高和行号列号计算x,yhtml

CGFloat appX = marginX + col * (appW + marginX);
CGFloat appY = row * (appH + marginY);
 
8. 实现图片轮播图
1>  1> UIScrollView设置contentSize,添加图片并设置frame,设置分页
2>  2> 添加分页控制器,在UIScrollView滚动代理方法中根据contentOffset计算当前页数并设置
      3> 设置定时器,主动改变contentOffset,设置定时器的模式进行并发操做(终极方案定时器放在异步线程)
 
 
 
二.生命周期
1> 应用的生命周期
///  各个程序运行状态时代理的回调:
- (BOOL)application:(UIApplication *)application willFinishLaunchingWithOptions:(NSDictionary *)launchOptions  //告诉代理进程启动但还没进入状态保存
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions   //告诉代理启动基本完成程序准备开始运行
- (void)applicationWillResignActive:(UIApplication *)application   //当应用程序将要入非活动状态执行,在此期间,应用程序不接收消息或事件,好比来电话了
- (void)applicationDidBecomeActive:(UIApplication *)application    //当应用程序入活动状态执行,这个恰好跟上面那个方法相反
- (void)applicationDidEnterBackground:(UIApplication *)application  // 当程序被推送到后台的时候调用。因此要设置后台继续运行,则在这个函数里面设置便可
- (void)applicationWillEnterForeground:(UIApplication *)application   //当程序从后台将要从新回到前台时候调用,这个恰好跟上面的那个方法相反。
- (void)applicationWillTerminate:(UIApplication *)application   //当程序将要退出是被调用,一般是用来保存数据和一些退出前的清理工做。

 

2> 视图的生命周期
loadView  // - 默认调用super方法,根据控制器建立方式加载视图,重写后将根据重写方法建立视图
viewDidLoad  // -视图加载完成
viewWillAppear-UIViewController  // -对象的视图即将加入窗口时调用;
viewDidApper-UIViewController  // -对象的视图已经加入到窗口时调用;
viewWillDisappear-UIViewController  // -对象的视图即将消失、被覆盖或是隐藏时调用;
viewDidDisappear-UIViewController   // - 对象的视图已经消失、被覆盖或是隐藏时调用;
viewVillUnload  //-当内存太低时,须要释放一些不须要使用的视图时,即将释放时调用;
viewDidUnload  //-当内存太低,释放一些不须要的视图时调用。

 

3>  load initialize方法的区别
  +(void)load +(void)initialize
执行时机 在程序运行后当即执行 在类的方法第一次被调时执行
若自身未定义,是否沿用父类的方法?
类别中的定义 全都执行,但后于类中的方法 覆盖类中的方法,只执行一个
4> 建立控制器、视图的方式
4.1> 建立控制器的方式
1)经过代码的方式加载viewController
UIViewController *controller = [[UIViewController alloc] init];
2)经过stroyboard来加载viewController
2.1) 加载storyboard中箭头指向的viewController
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil]; //加载箭头指向的viewController
CZViewController *controller = [storyboard instantiateInitialViewController];
2.2) 加载storyboard中特定标示的viewController(storyboard能够有多个controller)
UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
CZViewController *controller = [storyboard instantiateViewControllerWithIdentifier:@"two"];
3)经过xib加载viewController
3.1) 传统方法
3.1.1)建立Xib,并指定xib的files owner为自定义控制器类(为了能连线关联管理IB的内容)
3.1.2)xib中要有内容,且xib中描述的控制器类的view属性要与xib的view控件完成关联(关联方法两种,一种是control+files owner拖线到xib中搭建的指定view控件,另外一种是指定xib中的view拖线到@interface)
3.1.3)从xib加载viewController
CZViewController *controller = [[CZViewController alloc] initWithNibName:@"CZOneView" bundle:nil];
3.2)bundle中取出xib内容
CZViewController *vc = [[NSBundle mainBundle] loadNibNamed:@"Two" owner:nil options:nil].lastObject;
4.2> 建立视图的方式
1.用系统的loadView方法建立控制器的视图
2.若是指定加载某个storyboard文件作控制器的视图,就会加载storyboard里面的描述去建立view
3.若是指定读取某个xib文件作控制器的视图,就根据指定的xib文件去加载建立
4.若是有xib文件名和控制器的类名前缀(也就是去掉controller)的名字同样的   xib文件 就会用这个xib文件来建立控件器的视图 例:控件器的名为 MJViewController  xib文件名为 MJView.xib   若是xib文件名后有一个字不同就不会去根据它去建立如:MJView8.xib
5.找和控制器同名的xib文件去建立
6.若是以上都没有就建立一个空的控制器的视图;
 
5> UIWindow
是一种特殊的UIView,一般在一个程序中只会有一个UIWindow,但能够手 动建立多个UIWindow,同时加到程序里面。UIWindow在程序中主要起到三个做用:
一、做为容器,包含app所要显示的全部视图
二、传递触摸消息到程序中view和其余对象
三、与UIViewController协同工做,方便完成设备方向旋转的支持
 
三.多控制器管理
1.
 
四.核心绘图
6> View和layer的区别
图层不会直接渲染到屏幕上,UIView是iOS系统中界面元素的基础,全部的界面元素都是继承自它。它自己彻底是由CoreAnimation来实现的。它真正的绘图部分,是由一个CALayer类来管理。UIView自己更像是一个CALayer的管理器。一个UIView上能够有n个CALayer,每一个layer显示一种东西,加强UIView的展示能力。
6.1>均可以显示屏幕效果
6.2> 若是须要用户交互就要用UIVIew,其可接收触摸事件(继承UIResponder),而CALayer不能接收触摸事件
6.3> 若是没有用户交互可选用CALayer,由于其所在库较小,占用的资源较少
7> new和alloc init的区别
采用new的方式只能采用默认的init方法完成初始化,采用alloc的方式能够用其余定制的初始化方法。
 
五.动画
1> ios界面切换 
 
2>  iOS中各类动画的类型&特色&使用场景
CAPropertyAnimation
CAAnimation的子类,也是个抽象类,要想建立动画对象,应该使用它的两个子类:CABasicAnimation和CAKeyframeAnimation
属性解析:
keyPath:经过指定CALayer的一个属性名称为keyPath(NSString类型),而且对CALayer的这个属性的值进行修改,达到相应的动画效果。好比,指定@”position”为keyPath,就修改CALayer的position属性的值,以达到平移的动画效果
 
CABasicAnimation
CAPropertyAnimation的子类
属性解析 :
fromValue:keyPath相应属性的初始值
toValue:keyPath相应属性的结束值
随着动画的进行,在长度为 duration的持续时间内,keyPath相应属性的值从fromValue渐渐地变为toValue
若是 fillMode=kCAFillModeForwards和removedOnComletion=NO,那么在动画执行完毕后,图层会保持显示动画执行后的状态。但在实质上,图层的属性值仍是动画执行前的初始值,并无真正被改变。好比,CALayer的position初始值为(0,0),CABasicAnimation的fromValue为(10,10),toValue为(100,100),虽然动画执行完毕后图层保持在(100,100)这个位置,实质上图层的position仍是为(0,0)
 
CAKeyframeAnimation
CApropertyAnimation的子类,跟CABasicAnimation的区别是:CABasicAnimation只能从一个数值(fromValue)变到另外一个数值(toValue),而CAKeyframeAnimation会使用一个NSArray保存这些数值
属性解析:
values:就是上述的NSArray对象。里面的元素称为”关键帧”(keyframe)。动画对象会在指定的时间(duration)内,依次显示values数组中的每个关键帧
path:能够设置一个CGPathRef\CGMutablePathRef,让层跟着路径移动。path只对CALayer的anchorPoint和position起做用。若是你设置了path,那么values将被忽略
keyTimes:能够为对应的关键帧指定对应的时间点,其取值范围为0到1.0,keyTimes中的每个时间值都对应values中的每一帧.当keyTimes没有设置的时候,各个关键帧的时间是平分的
CABasicAnimation可看作是最多只有2个关键帧的CAKeyframeAnimation
 
CAAnimationGroup
CAAnimation的子类,能够保存一组动画对象,将CAAnimationGroup对象加入层后,组中全部动画对象能够同时并发运行
属性解析:
animations:用来保存一组动画对象的NSArray
默认状况下,一组动画对象是同时运行的,也能够经过设置动画对象的 beginTime属性来更改动画的开始时间
 
CATransition
CAAnimation的子类,用于作转场动画,可以为层提供移出屏幕和移入屏幕的动画效果。iOS比Mac OS X的转场动画效果少一点
UINavigationController就是经过CATransition实现了将控制器的视图推入屏幕的动画效果
属性解析 :
type:动画过渡类型
subtype:动画过渡方向
startProgress:动画起点(在总体动画的百分比)
endProgress:动画终点(在总体动画的百分比)
 
UIView动画
UIKit直接将动画集成到UIView类中,当内部的一些属性发生改变时,UIView将为这些改变提供动画支持
执行动画所须要的工做由 UIView类自动完成,但仍要在但愿执行动画时通知视图,为此须要将改变属性的代码放在[UIView beginAnimations:nil context:nil]和[UIView commitAnimations]之间
 
Block动画
 
帧动画
  
六.事件处理
1> 描述响应者链条
当触摸事件发生时,压力转为电信号,iOS系统将产生UIEvent对象,记录事件产生的时间和类型,而后系统将事件加入到一个由UIApplication管理的事件队列中。
UIApplication会从事件队列中取出最前面的事件,并将事件分发下去以便处理,一般,先发送事件给应用程序的主窗口(keyWindow)
主窗口会在视图层次结构中找到一个最合适的视图来处理触摸事件(从父到子,从后到前),这也是整个事件处理过程的第一步
找到合适的视图控件后,就会调用视图控件的touches方法来做具体的事件处理
4.Runloop
1> 每一个线程上都有一个runloop,主线程默认开启,辅助线程须要手动开启,主要用于
  1. 使用端口或自定义输入源来和其余线程通讯
  2. 使用线程的定时器
  3. Cocoa中使用任何performSelector…的方法
  4. 使线程周期性工做
2> runloop的工做流程
 
七.屏幕适配
 
多线程
一.资源抢夺
2> 资源抢夺解决方案
@sychronized{ }
dispatch_barrier_async
NSLock NSCondition
dispatch_semaphore_wait
 
二.iOS多线程技术
3> 对比iOS中的多线程技术
3.1> pthread
pthread跨平台,使用难度大,须要手动管理线程生命周期
pthread_create建立线程,传参线程标记,线程属性,初始函数,函数参数
3.2> NSThread
NSThread须要手动管理线程生命周期和
3.3> GCD
 
3.4> NSOperation
 
GCD是纯C语言的API,NSOperationQueue是基于GCD的OC版本封装
3.2> GCD仅仅支持FIFO队列,只能够设置队列的优先级,而NSOperationQueue中的每个任务均可以被从新设置优先级(setQueuePriority:),从而实现不一样操做的执行顺序调整
3.3> GCD不支持异步操做之间的依赖关系设置。若是某个操做的依赖另外一个操做的数据,使用NSOperationQueue可以设置依赖按照正确的顺序执行操做(addDependency:)。GCD则没有内建的依赖关系支持(只能经过Barrior和同步任务手动实现)。
3.4> NSOperationQueue方便中止队列中的任务(cancelAllOperations, suspended),GCD不方便中止队列中的任务.
3.5> NSOperationQueue支持KVO,能够监测operation是否正在执行(isExecuted)、是否结束(isFinished),是否取消(isCanceld)
3.6> GCD的执行速度比NSOperationQueue快
3.7> NSOperationQueue可设置最大并发数量(节电),GCD具备dispatch_once(只执行一次,单例)和dispatch_after(延迟执行)功能
3.8> NSObject分类(perform)和NSThread遇到对象分配须要手动内存管理,手动管理线程生命周期
3.9> NSThread查看线程
3.10> NSObject分类线程通讯
 
4> 原子属性
原子属性采用的是"多读单写"机制的多线程策略
"多读单写"缩小了锁范围,比互斥锁的性能好
规定只在主线程更新UI,就是由于若是在多线程中更新,就须要给UI对象加锁,防止资源抢占写入错误,可是这样会下降UI交互的性能,因此ios设计让全部UI对象都是非线程安全的(不加锁),并规定只在主线程中更新UI,规避多线程抢占资源问题
 
三.其余
1> 多线程优缺点
优势:
使应用程序的响应速度更快,用户界面在进行其余工做的同时仍始终保持活动状态;
优化任务执行,适当提升资源利用率(cpu, 内存);
缺点:
线程占用内存空间,管理线程须要额外的CPU开销,开启大量线程,下降程序性能;
增长程序复杂度,如线程间通讯,多线程的资源共享等;
2> 在多线程中使用通知须要注意什么问题?
 
3> iOS中的延迟操做
1> 
[self performSelector:@selector(clearCache) withObject:nil afterDelay:duration];

 2> java

dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(2.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{..});
 
网络
一.网络基础
1.数据解析
1> XML解析方式
SAX 方式解析
-只读
-速度快
-从上向下
-经过5个代理方法解析,每一个代理方中都须要写一些代码!
-若是要实现SAX解析,思路最重要!
-适合比价大的XML的解析
DOM解析的特色
-一次性将XML所有加载到内存,以树形结构
-好处,能够动态的修改,添加,删除节点
-内存消耗很是大!尤为横向节点越深!
-iOS默认不支持 DOM 解析!
-在 MAC 端,或者服务器端开发,都基本上使用 DOM 解析
-在 iOS 端若是须要使用 DOM 方式解析,可使用第三方框GData/KissXML(XMPP)
-适合比较小的 XML 文件
-在 MAC 中,苹果提供了一个 NSXML 的类,可以作 DOM 解析,在 iOS 不能使用!
2>  json&xml的区别
1)解码难度: json的解码难度基本为零,xml须要考虑子节点和父节点
2)数据体积&传输速度: json相对于xml来说,数据体积小,json的速度远远快于xml
3)数据交互: json与JavaScript的交互更加方面,更容易解析处理,更好的数据交互
4)数据描述: xml对数据描述性比较好
 
2.网络协议
1>TCP如何防止乱序和丢包
    TCP数据包的头格式中有两个概念,Sequence Number是数据包的序号,用来解决网络包乱序(reordering)问题。Acknowledgement Number就是ACK——用于确认收到,用来解决不丢包的问题。
    位码即tcp标志位,有6种标示:SYN(synchronous创建联机)        ACK(acknowledgement 确认) PSH(push传送) FIN(finish结束) RST(reset重置) URG(urgent紧急)Sequence number(顺序号码) Acknowledge number(确认号码).
   SeqNum的增长是和传输的字节数相关的,TCP传输数据时,A主机第一次传输1440个字节,seq=1,那么第二次时seq = 1441,B拼接数据就是根据seq进行拼接的,seq数字不断累加避免了乱序.B主机收到第一次数据包之后会返回ack = 1441.
    A主机收到B的ack = 1441时,就知道第一个数据包B已收到. 若是B没有收到第一次的数据包,那么B再收到A的数据包时,他就会发ack = 1回去,A收到B的回复,发现B没有收到第一次数据包,就会重发第一次数据包,这样就能够防止丢包.
 
2>描述一下三次握手
 
   第一次握手:创建链接时,客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认;
   第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时本身也发送一个SYN包(syn=k),即SYN+ACK包,此时服务器进入SYN_RECV状态;
   第三次握手:客户端收到服务器的SYN+ACK包,向服务器发送确认包ACK(ack=k+1),此包发送完毕,客户端和服务器进入ESTABLISHED状态,完成三次握手。完成三次握手,客户端与服务器开始传送数据.
 
3> TCP与UDP的区别:
3.1>基于链接与无链接;
3.2>对系统资源的要求(TCP较多,UDP少);
3.3>UDP程序结构较简单;
3.4>流模式与数据报模式 ;
3.5>TCP保证数据正确性,UDP可能丢包,TCP保证数据顺序,UDP不保证。
 
4>http和scoket通讯的区别
http是客户端用http协议进行请求,发送请求时候须要封装http请求头,并绑定请求的数据,服务器通常有web服务器配合(固然也非绝对)。 http请求方式为客户端主动发起请求,服务器才能给响应,一次请求完毕后则断开链接,以节省资源。服务器不能主动给客户端响应(除非采起http长链接技术)。iPhone主要使用类是NSUrlConnection。
scoket是客户端跟服务器直接使用socket“套接字”进行链接,并无规定链接后断开,因此客户端和服务器能够保持链接通道,双方均可以主动发送数据。通常在游戏开发或股票开发这种要求即时性很强而且保持发送数据量比较大的场合使用。主要使用类是CFSocketRef。
 
5> HTTP请求经常使用的几种方式
GET :获取指定资源
POST :2M  向指定资源提交数据进行处理请求,在RESTful 风格用于新增资源
HEAD :获取指定资源头部信息
PUT :替换指定资源(不支持浏览器操做)
DELETE: 删除指定资源
 
3.网络传输
1>DNS是如何工做的
DNS是domain name server的简称,每一个网络的计算机都有ip,可是很差记,因此用域名替代(如www.baidu.com),在 Internet 上真实在辨识机器的仍是 IP,因此当使用者输入Domain Name 后,浏览器必需要先去一台有 Domain Name 和IP 对应资料的主机去查询这台电脑的 IP,而这台被查询的主机,咱们称它为 Domain Name Server,简称DNS,例如:当你输入www.pchome.com.tw时,浏览器会将www.pchome.com.tw这个名字传送到离他最近的 DNS Server 去作辨识,若是查到,则会传回这台主机的 IP,进而跟它索取资料,但若是没查到,就会发生相似 DNS NOT FOUND 的情形,因此一旦DNS Server当机,就像是路标彻底被毁坏,没有人知道该把资料送到那里
 
2> POST请求常见的数据格式
 
二.网络安全/加密
 
三.数据存储
1.数据存储技术
1> 数据存储的几种方式 
XML属性列表(plist)归档
Preference(偏好设置)
NSKeyedArchiver归档(NSCoding)
SQLite3
Core Data
2> 各自特色
Plist:
属性列表是一种XML格式的文件,拓展名为plist
若是对象是NSString、NSDictionary、NSArray、NSData、NSNumber等类型,就可使用writeToFile:atomically:方法直接将对象写到属性列表文件中
   将一个NSDictionary对象归档到一个plist属性列表中
// 将数据封装成字典
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:@"母鸡" forKey:@"name"];
// 将字典持久化到Documents/stu.plist文件中
[dict writeToFile:path atomically:YES];
 
面试考点:
1.    plist的根节点 只能是NSDictionary和NSArray,因此存储内容必须转为对象类型
2.    使用场景  功能动态更新 应用级别数据更新  XML的替代品
 
偏好设置:
每一个应用都有个NSUserDefaults实例,经过它来存取偏好设置
好比,保存用户名、字体大小、是否自动登陆
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:@"itcast" forKey:@"username"];
[defaults setFloat:18.0f forKey:@"text_size"];
[defaults setBool:YES forKey:@"auto_login"];
 
面试考点:
1.    使用场景 保存应用信息
2.    特色  不会自动删除,itune同步,不适合存大数据
3.    使用单例模式、
4.    直接存取结构体,基本数据类型,无需转换
5.    即时操做注意同步
 
归档:
若是对象是NSString、NSDictionary、NSArray、NSData、NSNumber等类型,能够直接用NSKeyedArchiver进行归档和恢复
不是全部的对象均可以直接用这种方法进行归档,只有遵照了NSCoding协议的对象才能够
NSCoding协议有2个方法:
encodeWithCoder:
每次归档对象时,都会调用这个方法。通常在这个方法里面指定如何归档对象中的每一个实例变量,可使用encodeObject:forKey:方法归档实例变量
initWithCoder:
每次从文件中恢复(解码)对象时,都会调用这个方法。通常在这个方法里面指定如何解码文件中的数据为对象的实例变量,可使用decodeObject:forKey方法解码实例变量
// 归档一个NSArray对象到Documents/array.archive
NSArray *array = [NSArray arrayWithObjects:@”a”,@”b”,nil];
[NSKeyedArchiver archiveRootObject:array toFile:path];
 
  使用archiveRootObject:toFile:方法能够将一个对象直接写入到一个文件中,但有时候可能想将多个对象写入到同一个文件中,那么就要使用NSData来进行归档对象
  归档(编码)
// 新建一块可变数据区
NSMutableData *data = [NSMutableData data];
// 将数据区链接到一个NSKeyedArchiver对象
NSKeyedArchiver *archiver = [[[NSKeyedArchiver alloc] initForWritingWithMutableData:data] autorelease];
// 开始存档对象,存档的数据都会存储到NSMutableData中
[archiver encodeObject:person1 forKey:@"person1"];
[archiver encodeObject:person2 forKey:@"person2"];
// 存档完毕(必定要调用这个方法)
[archiver finishEncoding];
// 将存档的数据写入文件
[data writeToFile:path atomically:YES];
 
l    恢复(解码)
// 从文件中读取数据
NSData *data = [NSData dataWithContentsOfFile:path];
// 根据数据,解析成一个NSKeyedUnarchiver对象
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
Person *person1 = [unarchiver decodeObjectForKey:@"person1"];
Person *person2 = [unarchiver decodeObjectForKey:@"person2"];
// 恢复完毕
[unarchiver finishDecoding];
 
利用归档实现深复制
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:person1];
// 解析data,生成一个新的Person对象
Student *person2 = [NSKeyedUnarchiver unarchiveObjectWithData:data];
 
       面试考点:
1.    特色: 存入Document,itune同步,不会自动删除,可存放大型用户数据
2.    使用场景: 用户产生的数据,如游戏,操做记录等等
3.    可保存自定义对象,须要遵照NSCoding协议,实现对应的encodeWithCoder  initWithCoder 方法
4.    和NSData的配合
4.1> 多对象单目录存储
4.2> 字典/数组内容的深拷贝
5.    不能直接存基本类型和结构体,须要转成对象  NSValue NSNumber
 
2> 沙盒目录结构
2.1> Library Caches Preferences
2.2> Documents
2.3> tmp
3>  如何读取沙盒中plist的内容
1>   3.1> 读取沙盒并拼接plist的文件路径   
       
NSString *path = [[NSBundle mainBundle] pathForResource:@"app.plist" ofType:nil];
 3.2> 根据plist根节点类型读取plist文件
NSArray *apps = [NSArray arrayWithContentsOfFile:path];
 
2.数据库技术(SQLite&CoreData)
1> SQLite和CoreData的区别
1.1> CoreData能够在一个对象更新时,其关联的对象也会随着更新,至关于你更新一张表时,其关联的其余表的也回随着更新
1.2> CoreData提供更简单的性能管理机制,能够限制查询记录的总数,这个类会自动更新其缓存
1.3> 多表查询方面,CoreData没有SQL直观,没有相似外链接,左链接等操做.
 
四.Html5/oc&js互调
// oc>js:
[self.webView stringByEvaluatingJavaScriptFromString:“window.location.href = xxx”];
// js>oc: 利用hmtl中js的重定向技术
<Script> window.location.href = www.baidu.com//method:dosomething </Script> 
// 使用方法截取重定向
(BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
 
五.iOS网络框架
1> NSURLConnection和NSURLSession的区别
1.1> 异步请求不须要NSOperation包装
1.2> 支持后台运行的网络任务(后台上传下载)
1.3> 根据每一个Session作配置(http header,Cache,Cookie,protocal,Credential),再也不在整个App层面共享配置
1.4> 支持网络操做的取消和断点续传(继承系统类,从新main方法)
1.5> 改进了受权机制的处理
 
项目
1.实用技术
2.知名第三方框架
3.开发技巧
1> description方法
 
Swift
1> Swift和OC的区别
1.1> Swift没有地址/指针的概念
1.2> 泛型
1.3> 类型严谨 对比oc的动态绑定
 
6.设计模式
1> 经常使用的设计模式
  代理  观察者  工厂  单例   策略
2> 代理属性的内存策略是什么,为何?
3> 观察者模式的使用场景
4> 工厂模式(类方法)为何没有释放对象? autorelease工做原理? arc下还须要手动使用autorelease吗?为何?什么场景?
5> 手写单例
6> 策略  cell多种响应效果   代理方法
 
(一)代理模式
 应用场景:当一个类的某些功能须要由别的类来实现,可是又不肯定具体会是哪一个类实现。
 优点:解耦合
 敏捷原则:开放-封闭原则
 实例:tableview的 数据源delegate,经过和protocol的配合,完成委托诉求。
 列表row个数delegate
 自定义的delegate
 
 (二)观察者模式
 应用场景:通常为model层对controller和view进行的通知方式,不关心谁去接收,只负责发布信息。
 优点:解耦合
 敏捷原则:接口隔离原则,开放-封闭原则
 实例:Notification通知中心,注册通知中心,任何位置能够发送消息,注册观察者的对象能够接收。
kvo,键值对改变通知的观察者,平时基本没用过。
 
(三) MVC模式
 应用场景:是一中很是古老的设计模式,经过数据模型,控制器逻辑,视图展现将应用程序进行逻辑划分。
 优点:使系统,层次清晰,职责分明,易于维护
 敏捷原则:对扩展开放-对修改封闭
 实例:model-即数据模型,view-视图展现,controller进行UI展示和数据交互的逻辑控制。

 (四)单例模式
 应用场景:确保程序运行期某个类,只有一份实例,用于进行资源共享控制。
 优点:使用简单,延时求值,易于跨模块
 敏捷原则:单一职责原则
 实例:[UIApplication sharedApplication]。
 注意事项:确保使用者只能经过 getInstance方法才能得到,单例类的惟一实例。
java,C++中使其没有公有构造函数,私有化并覆盖其构造函数。
object c中,重写allocWithZone方法,保证即便用户用 alloc方法直接建立单例类的实例,返回的也只是此单例类的惟一静态变量。

 (五)策略模式
 应用场景:定义算法族,封装起来,使他们之间能够相互替换。
 优点:使算法的变化独立于使用算法的用户
 敏捷原则:接口隔离原则;多用组合,少用继承;针对接口编程,而非实现。
 实例:排序算法,NSArray的sortedArrayUsingSelector;经典的鸭子会叫,会飞案例。
 注意事项:1,剥离类中易于变化的行为,经过组合的方式嵌入抽象基类
2,变化的行为抽象基类为,全部可变变化的父类
3,用户类的最终实例,经过注入行为实例的方式,设定易变行为
 防止了继承行为方式,致使无关行为污染子类。完成了策略封装和可替换性。

 (六)工厂模式
 应用场景:工厂方式建立类的实例,多与proxy模式配合,建立可替换代理类。
 优点:易于替换,面向抽象编程,application只与抽象工厂和易变类的共性抽象类发生调用关系。
 敏捷原则:DIP依赖倒置原则
 实例:项目部署环境中依赖多个不一样类型的数据库时,须要使用工厂配合proxy完成易用性替换
 注意事项:项目初期,软件结构和需求都没有稳定下来时,不建议使用此模式,由于其劣势也很明显,
 增  加了代码的复杂度,增长了调用层次,增长了内存负担。因此要注意防止模式的滥用。
 
2> MVVM和rectivecocoa
 
 
六.框架
1.SDWebimage
1> SDWebimage的缓存机制
  1. UIImageView+WebCache: setImageWithURL:placeholderImage:options: 先显示 placeholderImage ,同时由SDWebImageManager 根据 URL 来在本地查找图片。
  2. SDWebImageManager: downloadWithURL:delegate:options:userInfo: SDWebImageManager是将UIImageView+WebCache同SDImageCache连接起来的类, SDImageCache: queryDiskCacheForKey:delegate:userInfo:用来从缓存根据CacheKey查找图片是否已经在缓存中
  3. 若是内存中已经有图片缓存, SDWebImageManager会回调SDImageCacheDelegate : imageCache:didFindImage:forKey:userInfo:
  4. 而 UIImageView+WebCache 则回调SDWebImageManagerDelegate:  webImageManager:didFinishWithImage:来显示图片。
  5. 若是内存中没有图片缓存,那么生成 NSInvocationOperation 添加到队列,从硬盘查找图片是否已被下载缓存。
  6. 根据 URLKey 在硬盘缓存目录下尝试读取图片文件。这一步是在 NSOperation 进行的操做,因此回主线程进行结果回调 
    notifyDelegate:
  7. 若是上一操做从硬盘读取到了图片,将图片添加到内存缓存中(若是空闲内存太小,会先清空内存缓存)。SDImageCacheDelegate 回调 imageCache:didFindImage:forKey:userInfo:进而回调展现图片。
  8. 若是从硬盘缓存目录读取不到图片,说明全部缓存都不存在该图片,须要下载图片,回调 
    imageCache:didNotFindImageForKey:userInfo:
  9. 共享或从新生成一个下载器 SDWebImageDownloader 开始下载图片。
  10. 图片下载由 NSURLConnection 来作,实现相关 delegate 来判断图片下载中、下载完成和下载失败。
  11. connection:didReceiveData: 中利用 ImageIO 作了按图片下载进度加载效果。
  12. connectionDidFinishLoading: 数据下载完成后交给 SDWebImageDecoder 作图片解码处理。
  13. 图片解码处理在一个 NSOperationQueue 完成,不会拖慢主线程 UI。若是有须要对下载的图片进行二次处理,最好也在这里完成,效率会好不少。
  14. 在主线程 notifyDelegateOnMainThreadWithInfo: 宣告解码完成,imageDecoder:didFinishDecodingImage:userInfo: 回调给 SDWebImageDownloader。
  15. imageDownloader:didFinishWithImage: 回调给 SDWebImageManager 告知图片下载完成。
  16. 通知全部的 downloadDelegates 下载完成,回调给须要的地方展现图片。
  17. 将图片保存到 SDImageCache 中,内存缓存和硬盘缓存同时保存。
  18. 写文件到硬盘在单独 NSInvocationOperation 中完成,避免拖慢主线程。
  19.  若是是在iOS上运行,SDImageCache 在初始化的时候会注册notification 到 UIApplicationDidReceiveMemoryWarningNotification 以及  UIApplicationWillTerminateNotification,在内存警告的时候清理内存图片缓存,应用结束的时候清理过时图片。
  20. SDWebImagePrefetcher 能够预先下载图片,方便后续使用。
 
位运算
NSCache
特色: a> 线程安全的 b> 当内存不足的时候,自动释放 c> 缓存数量和缓存成本
区别NSMutableDictionary
1> 不能也不该该遍历  2> NSCache对key强引用,NSMutableDictionary对key进行copy
 
2.AFN
1>实现原理
AFN的直接操做对象AFHTTPClient不一样于ASI,是一个实现了NSCoding和NSCopying协议的NSObject子类。 AFHTTPClient是一个封装了一系列操做方法的“工具类”,处理请求的操做类是一系列单独的,基于NSOperation封装 的,AFURLConnectionOperation的子类。AFN的示例代码中经过一个静态方法,使用dispatch_once()的方式建立 AFHTTPClient的共享实例,这也是官方建议的使用方法。在建立AFHTTPClient的初始化方法中,建立了OperationQueue并 设置一系列参数默认值。在getPath:parameters:success:failure方法中建立NSURLRequest,以 NSURLRequest对象实例做为参数,建立一个NSOperation,并加入在初始化发方中建立的NSOperationQueue。以上操做都 是在主线程中完成的。在NSOperation的start方法中,以此前建立的NSURLRequest对象为参数建立NSURLConnection 并开启连结。
 
2> 传递指针 如何使一个方法返回多个返回值
传参指针变量的地址,方法内部经过*运算符使用该地址能够修改该地址保存的内容(引用对象的地址),当外部再次使用该指针变量取出引用对象时,引用对象已经在方法内部发生了改变,指针变量指向其余数据,至关于方法的返回值(经方法处理后生成的外部可以使用的结果数据).
 
七.项目
1.编译连接
1> id和instancetype的区别 
instancetype只能作返回值,编译时判断真实类型,不符合发警告
特殊状况: 关联类型返回方法,如类方法alloc或new开头,实例方法中,以autorelease,init,retain,或self开头
 
2.静态库
如何给静态库添加属性   分类+runtime
如何调用私有方法  performselector  category(前向引用)
 
3.混编
arc mrc混编
c c++混编
 
4.加密
 
5.iOS更新
ios6 7 8的区别
 
5.日期处理
字符串操做  append  format  substring  rangeofstring    nsrange    http://www.cnblogs.com/neworiginou/archive/2012/11/14/2770038.html
 
6.性能优化
1> 如何进行性能优化
1.1> 内存优化的点   重用  懒加载
1.2> 渲染优化  尽可能使用不透明的图   把 views 设置为透明
1.3> 在ImageView设置前,尽可能先调整好图片大小   尤为放在uiscrolliview中自动缩放耗能
1.4> 避免使用过大的xib     和分镜的区别  一次性加载
1.5> 不要阻塞主线程     除渲染,触摸响应等    尽可能异步处理  如存储,网络       异步线程通知    
1.6> 缓存    网络响应,图片,计算结果(行高)    网络响应NSUrlconnection默认缓存request,设置策略  非网络请求 使用nscache nsdictionary
1.7> 避免反复处理数据   在服务器端和客户端使用相同的数据结构
1.8> 选择正确的数据格式  json  速度快 解析方便   xml  sax方式逐行解析 解析大文件不占用内存和损失性能
1.9> 优化tableview  重用cell 缓存行高 cell子视图尽可能少且不透明  
1.10> 选择正确的数据存储选项  plist nscoding NSUserDefaults sqlite coredata
 
八.算法
1.交换数值的几种方法   中间变量    加减法    异或
2.oc/c实现经常使用排序
3.
  
二叉树
链表
写一个单链表,要求能够插入数据和删除单个数据
 
递归