高级面试题

多线程的底层实现
1> 首先搞清楚什么是线程、什么是多线程、多线程的使用场合
2> Mach是第一个以多线程方式处理任务的系统,所以多线程的底层实现机制是基于Mach的线程
3> GCD 和 NSOperationQueue 区别。
•NSThread:
–优势:NSThread 比其余两个轻量级,使用简单
–缺点:须要本身管理线程的生命周期、线程同步、加锁、睡眠以及唤醒等。线程同步对数据的加锁会有必定的系统开销

•NSOperation:
–不须要关心线程管理,数据同步的事情,能够把精力放在本身须要执行的操做上
–NSOperation是面向对象的

•GCD:
–Grand Central Dispatch是由苹果开发的一个多核编程的解决方案。iOS4.0+才能使用,是替代NSThread, NSOperation的高效和强大的技术
–GCD是基于C语言的
4> 分发源 和 分发队列 . dispatch source监听事件(线程间
通讯)。当这些事件发生时,它自动将一个block放入一个dispatch queue的执行例程中。
5> 开发中实现多线程的方案
C语言的POSIX接口:#include <pthread.h>
OC的NSThread
C语言的GCD接口(性能最好,代码更精简)
OC的NSOperation和NSOperationQueue(基于GCD)
6> 为何UI必须在主线程 [主线程又叫UI线程]
项目经理是主线程,程序员是子线程,那么程序员完成任务后须要通知经理【不然经理不知道,那么经理就没法整合代码了】
有时候能够在子线程刷新UI,【注意:只是有时候能够】为了不这种状况,咱们必须在主线程刷新UI,子线程会和主线程交流的,但何时交流是不肯定的,咱们没法知晓具体时间
7>线程间怎么通讯
1. GCD dispatch_async(dispatch_get_main_queue)回到主线程
2. performSelector:onThread:withObject:waitUntilDone:
   performSelectorOnMainThread:withObject:waitUntilDone:
1. NSMachPort(可选)

网络图片处理问题中怎么解决一个相同的网络地址重复请求的问题
利用字典(图片地址为key,下载操做为value)
这里其实问的是SDWebImage,关于图片处理,SDWebImage已经帮咱们处理过了,下载以前他会先到缓存中查找,若是有就会直接拿来用,没有就去下载



列举cocoa中常见对几种多线程的实现,并谈谈多线程安全的几种解决办法及多线程安全怎么控制?
1> 只在主线程刷新访问UI
2> 若是要防止资源抢夺,得用@synchronized进行加锁保护
3> 若是异步操做要保证线程安全等问题, 尽可能使用GCD(有些函数默认就是安全的)
4> 注意
1. dispatch_sync(dispatch_get_mian_queue)
     ^{  
1. nslog(@“-----”)

      }   
在主线程中执行就会形成死锁。
1. 2 的前提是1 已经执行完毕,可是1执行完毕的前提是2 执行完毕 ,由此就形成了死锁。
备注:sync是同步的,并且他表明的是当前线程【多是主线程也多是子线程】若是是表明主线程那么sync 会等到 后面block 执行完成才返回, sync 又再 dispatch_get_main_queue() 队列中,它是串行队列,sync 是后加入的,前一个是主线程,因此 sync 想执行 block 必须等待主线程执行完成,主线程等待 sync 返回,去执行后续内容。照成死锁,sync 等待mainThread 执行完成,mianThread 等待sync 函数返回。


GCD内部怎么实现的
1> iOS和OS X的核心是XNU内核,GCD是基于XNU内核实现的
2> GCD的API所有在libdispatch库中
3> GCD的底层实现主要有Dispatch Queue和Dispatch Source
Dispatch Queue :管理block(操做)
Dispatch Source :处理事件(好比线程间的通讯,新线程)

你为何要使用NSOperationQueue,实现了什么?请描述它和GCD的区别和相似的地方
1> GCD是纯C语言的API 封装在libdispatch库
     NSOperationQueue是基于GCD的OC版本封装
2> GCD只支持FIFO的队列
     NSOperationQueue能够很方便地调整执行顺序、设置最大并发数量
3> NSOperationQueue能够在轻松在Operation间设置依赖关系
     GCD须要写不少的代码才能实现
4> NSOperationQueue支持KVO,能够监测operation是否正在执行(isExecuted)、是否结束(isFinished),是否取消(isCanceld)
建一个Person类:
@interface Person : NSObject
@property (copy, nonatomic) NSString *name;
@property(assign, nonatomic) int;
在控制器中: age;
Person *p = [[Person alloc]init];
p.name = @"jack";
p.age = 18;
// 注册KVO
[p addObserver:self forKeyPath:@“name" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
p.name = @"rose";
self.person = p;
p的name属性发生变化就会调用这个方法
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    NSLog(@"%@",change);
}
补充
// 注册KVO
(void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
//解除KVO
• (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;
值得注意的是:不要忘记解除注册,不然会致使资源泄露。

5> GCD的执行速度比NSOperationQueue快

任务之间不太互相依赖:GCD
任务之间有依赖\或者要监放任务的执行状况:NSOperationQueue

在使用GCD以及block时要注意些什么?它们两是一回事儿么?block在ARC中和传统的MRC中的行为和用法有没有什么区别,须要注意些什么?
block 底层: 结构体指针
block 原理 :没有__block修饰的变量是值传递(闭包)
                   有__block修饰的变量地址传递  【有__block 修饰的变量咱们才能在block内部修改它   做用 : 1  逆传值    从控制器A 跳转到 控制器B,而A须要B里边的东西,这个时候就用到逆传值了
1. 保存代码
2. 回调
Block的使用注意:
block的内存管理
防止循环retian
      为何会循环retain(在block块里使用self,会对self有个强指针)
      通常用copy修饰block来将block从栈中移到堆中,若是用copy,则self会对block有一个强指针,而在block中又使用了self,那么block会对self有一个强指针。
MRC:__block
ARC:__weak\__unsafe_unretained
1. 对Block无论是retain、copy、release都不会改变引用计数retainCount,retainCount始终是1
在异步线程中下载不少图片,若是失败了,该如何处理?请结合RunLoop来谈谈解决方案.(提示:在异步线程中启动一个RunLoop从新发送网络请求,下载图片)
1>   从新下载图片(屡次下载)
2>下载完毕,利用RunLoop的输入源回到主线程刷新UIImageView(performSelectorOnMainThread)
关于RunLoop
RunLoop从字面上看是运行循环的意思,准确的说是线程中的循环。
有些线程执行的任务是一条直线,起点到终点——-如简单HelloWorld,运行打印完,它的生命周期便结束了

而另外一些线程要干的活则是一个圆,不断循环,直到经过某种方式将它终止。—操做系统,一直运行直到你关机,圆型的线程就是经过run loop不停的循环实现的。

首先循环体的开始须要检测是否有须要处理的事件,若是有则去处理,若是没有则进入睡眠以节省CPU时间。 因此重点即是这个须要处理的事件,在RunLoop中,须要处理的事件分两类,一种是输入源,一种是定时器,
定时器
好理解就是那些须要定时执行的操做
输 入源分三类:
performSelector源
基于端口(Mach port)的源
自定义的源。
RunLoop有一个观察者Observer的概念,能够往RunLoop中加入本身的 观察者以便监控着RunLoop的运行过程
 另外RunLoop中还有一个运行模式的概念,每个运行循环必然运行在某个模式下,而模式的存在是为了过滤事件源和观察者的,只有那些和当前 RunLoop运行模式一致的事件源和观察者才会被激活。


在一个线程中咱们须要作的事情并不单一,如须要处理定时钟事件,须要处理用户的触控事件,须要接受网络远端发过来的数据,将这些须要作的事情通通注 册到事件源中,每一次循环的开始便去检查这些事件源是否有须要处理的数据,有的话则去处理。 
拿具体的应用举个例子,NSURLConnection网络数据请求,默认是异步的方式,其实现原理就是建立以后将其做为事件源加入到当前的 RunLoop,而等待网络响应以及网络数据接受的过程则在一个新建立的独立的线程中完成,当这个线程处理到某个阶段的时候好比获得对方的响应或者接受完 了网络数据以后便通知以前的线程去执行其相关的delegate方法。

每个线程都有其对应的RunLoop,可是默认非主线程的RunLoop是没有运行的,须要为RunLoop添加至少一个事件源,而后去run它。通常状况下咱们是没有必要去启用线程的RunLoop的,除非你在一个单独的线程中须要长久的检测某个事件。
Run loop同时也负责autorelease pool的建立和释放
在使用手动的内存管理方式的项目中,会常常用到不少自动释放的对象,若是这些对象不可以被即时释放掉,会形成内存占用量急剧增大。Run loop就为咱们作了这样的工做,每当一个运行循环结束的时候,它都会释放一次autorelease pool,同时pool中的全部自动释放类型变量都会被释放掉。


Run loop的优势
一个run loop就是一个事件处理循环,用来不停的监听和处理输入事件并将其分配到对应的目标上进行处理。若是仅仅是想实现这个功能,你可能会想一个简单的while循环不就能够实现了吗,用得着费老大劲来作个那么复杂的机制?显然,苹果的架构设计师不是吃干饭的,你想到的他们早就想过了。
首先,NSRunLoop是一种更加高明的消息处理模式,他就高明在对消息处理过程进行了更好的抽象和封装,这样才能使得你不用处理一些很琐碎很低层次的具体消息的处理,在NSRunLoop中每个消息就被打包在input source或者是timer source(见后文)中了。
其次,也是很重要的一点,使用run loop可使你的线程在有工做的时候工做,没有工做的时候休眠,这能够大大节省系统资源。

Run loop相关知识点

Run loop接收输入事件来自两种不一样的来源:输入源(input source)和定时源(timer source)。两种源都使用程序的某一特定的处理例程来处理到达的事件。图-1显示了run loop的概念结构以及各类源。






 Socket的实现原理及Socket之间是如何通讯的
Socket用于网络中进程通信
 通常基于TCP/IP,UDP,常连接,时时保持通信(取决于协议)
TCP/IP 【端对端: 一个对一个】比较安全,不会出现丢包现象,只要发了就必定会收到
UDP     【广播式协议: 一对多】容易出现丢包现象,只管发,无论你收没收到
长链接与短链接  
长链接 指在一个TCP链接上能够连续发送多个数据包,在TCP链接保持期间,若是没有数据包发送,须要双方发检测包以维持此链接,通常须要本身作在线维持。 
长链接操做过程: 
  链接→数据传输→保持链接(心跳)→数据传输→保持链接(心跳)→……→关闭链接; 
短链接 是指通讯双方有数据交互时,就创建一个TCP链接,数据发送完成后,则断开此TCP链接,通常银行都使用短链接。
短链接操做步骤是: 
  链接→数据传输→关闭链接;  
何时用长链接,短链接?
长链接多用于操做频繁,点对点的通信,并且链接数不能太多状况
每一个TCP链接都须要三步握手,这须要时间,若是每一个操做都是先链接,再操做的话那么处理速度会下降不少,
因此每一个操做完后都不断开,下次次处理时直接发送数据包就OK了,不用创建TCP链接。

通常银行都使用短链接。

例如:数据库的链接用长链接, 
若是用短链接频繁的通讯会形成socket错误,并且频繁的socket 建立也是对资源的浪费。
 http协议的实现 
HTTP的概念: 全称是Hypertext Transfer Protocol,超文本传输协议
(1)规定客户端和服务器之间的数据传输格式
(2)让客户端和服务器能有效地进行数据沟通

为何选择使用HTTP:
(1)简单快速  由于HTTP协议简单,因此HTTP服务器的程序规模小,于是通讯速度很快
(2)灵活  HTTP容许传输任意类型的数据
(3)HTTP 0.9和1.0使用非持续链接  限制每次链接只处理一个请求,服务器对客户端的请求作出响应后,立刻断开链接,这种方式能够节省传输时间
HTTP的通讯过程
(1)请求:客户端向服务器索要数据


请求行:包含了请求方法、请求资源路径、HTTP协议版本
GET /MJServer/resources/images/1.jpg HTTP/1.1


请求头:包含了对客户端的环境描述、客户端请求的主机地址等信息
1.  192.168.1.105:8080 // 客户端想访问的服务器主机地址
2. er-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.9) Firefox/30.0// 客户端的类型,客户端的软件环境
Accept: text/html, */*// 客户端所能接收的数据类型
Accept-Language: zh-cn // 客户端的语言环境
Accept-Encoding: gzip // 客户端支持的数据压缩格式
请求体:客户端发给服务器的具体数据,好比文件数据

(2)响应:服务器返回客户端相应的数据
状态行:包含了HTTP协议版本、状态码、状态英文名称
1. TP/1.1 200 OK
响应头:包含了对服务器的描述、对返回数据的描述
1. rver: Apache-Coyote/1.1 // 服务器的类型
Content-Type: image/jpeg // 返回数据的类型
1. t-Length: 56811 // 返回数据的长度
2. e: Mon, 23 Jun 2014 12:54:52 GMT // 响应的时间
实体内容:服务器返回给客户端的具体数据,好比文件数据       

 iOS中发送HTTP请求的方案
在iOS中,常见的发送HTTP请求(GET和POST)的解决方案有
(1)苹果原生(自带)
NSURLConnection:用法简单,最古老最经典最直接的一种方案
NSURLSession:iOS 7新出的技术,功能比NSURLConnection更增强大
CFNetwork:NSURL*的底层,纯C语言
(2)第三方框架
ASIHttpRequest:外号“HTTP终结者”,功能极其强大,惋惜早已中止更新
AFNetworking:简单易用,提供了基本够用的经常使用功能
ASI和AFN架构对比

说明:AFN基于NSURL,ASI基于CFHTTP,ASI的性能更好一些。



怎么保证多人开发进行内存泄露的检查
使用Analyze进行代码的静态分析(检测有无潜在的内存泄露)
经过profile –> leak检查在程序运行过程当中有无内存泄露     
使用ARC

2.非自动内存管理状况下怎么作单例模式.
建立单例设计模式的基本步骤 ·
>声明一个单例对象的静态实例,并初始化为nil。 
• satic Person * Person= nil;
>建立一个类的类工厂方法里面加锁实现【能够用NSLock/ NSCondiction/@synchronized 这里咱们直接用dispatch_once由于里面自动加锁并且只调用一次】
类方法: +(instance)sharePerson;
>重写allocWithZone:方法和copyWithZone:方法,确保用户在直接分配和初始化对象时,不会产 生另外一个对象。 
>重写release、autorelease、retain、retainCount方法, 以此确保单例的状态。 
具体以下:
#import <foundation foundation.h="">
@interface Singleton : NSObject
+(instancetype) shareInstance ;
@end

#import "Singleton.h"
@implementation Singleton
• atic Singleton* _instance = nil;
+(instancetype) shareInstance
{
    static dispatch_once_t onceToken ;
    dispatch_once(&onceToken, ^{
        _instance = [[super allocWithZone:NULL] init] ;
    }) ;
    return _instance ;
}
+(id) allocWithZone:(struct _NSZone *)zone
{
    return [Singleton shareInstance] ;
}
-(id) copyWithZone:(struct _NSZone *)zone
{
    return [Singleton shareInstance] ;
}
@end

#import <foundation foundation.h="">
#import "Singleton.h"

• t main(int argc, const char * argv[]) {
    @autoreleasepool {

• ngleton* obj1 = [Singleton shareInstance] ;
• Log(@"obj1 = %@.", obj1) ;
• ngleton* obj2 = [Singleton shareInstance] ;
• Log(@"obj2 = %@.", obj2) ;

• ngleton* obj3 = [[Singleton alloc] init] ;
• Log(@"obj3 = %@.", obj3) ;

• ngleton* obj4 = [[Singleton alloc] init] ;
• Log(@"obj4 = %@.", [obj4 copy]) ;
    }
    return 0;
}</foundation>
输出结果是同样的,即获取的对象是同样的


3.对于类方法(静态方法)默认是autorelease的。全部类方法都会这样吗?
1> 系统自带的绝大数类方法返回的对象,都是通过autorelease的

4.block在ARC中和MRC中的用法有什么区别,须要注意什么
1>无论是ARC和MRC,block都应该用copy操做来持有
2>应注意避免循环引用
ARC: __weak、__unscafe_unretained
MRC:__block

5.什么状况下会发生内存泄漏和内存溢出?
1> 内存泄露:该释放的没有释放内存泄露会最终会致使内存溢出!
2>内存溢出:当程序在申请内存时,没有足够的内存空间供其使用,出现out of memory;好比申请了一个int,但给它存了long才能存下的数,那就是内存溢出。

6.[NSArray arrayWithobject:<id>] 这个方法添加对象后,须要对这个数组作释放操做吗?
    不须要 这个对象被放到自动释放池中 

7.Json数据的解析,和解析数据的时候有内存泄露吗?有的话 如何解决        
JSON解析的方案
苹果原生  NSJSONSerialization (无需导入包,IOS5支持,低版本IOS不支持)
1. NSError *error;
2. //加载一个NSURL对象
3. NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@" http://m.weather.com.cn/data/101180601.html"]];
4. //将请求的url数据放到NSData对象中
5. NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
6. //IOS5自带解析类NSJSONSerialization从response中解析出数据放到字典中
7. NSDictionary *weatherDic = [NSJSONSerialization JSONObjectWithData:response options:NSJSONReadingMutableLeaves error:&error];


第三方【TouchJson、 SBJson 、JSONKit】
TouchJson (需导入包:#import “TouchJson/JSON/CJSONDeserializer.h")

1. //获取API接口
2. NSURL *url = [NSURL URLWithString:@" http://m.weather.com.cn/data/101010100.html"];
3. //定义一个NSError对象,用于捕获错误信息
4. NSError *error;          NSString *jsonString = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
5. //将解析获得的内容存放字典中,编码格式为UTF8,防止取值的时候发生乱码
6. NSDictionary *rootDic = [[CJSONDeserializer deserializer] deserialize:[jsonString dataUsingEncoding:NSUTF8StringEncoding] error:&error];
7. //由于返回的Json文件有两层,去第二层内容放到字典中去
8. NSDictionary *weatherInfo = [rootDic objectForKey:@"weatherinfo"];
9. NSLog(@"weatherInfo--->%@",weatherInfo);
10. //取值打印
11. txtView.text = [NSString stringWithFormat:@"今天是 %@  %@  %@  的天气情况是:%@  %@ ",[weatherInfo objectForKey:@"date_y"],[weatherInfo objectForKey:@"week"],[weatherInfo objectForKey:@"city"], [weatherInfo objectForKey:@"weather1"], [weatherInfo objectForKey:@"temp1"]];
    14          
SBJson  (需导入包:#import "SBJson/SBJson.h")
1. NSURL *url = [NSURL URLWithString:@" http://m.weather.com.cn/data/101180701.html"];
2. NSError *error = nil;
3. NSString *jsonString = [NSString stringWithContentsOfURL:url encoding:NSUTF8StringEncoding error:&error];
4. SBJsonParser *parser = [[SBJsonParser alloc] init];
    5          
1. NSDictionary *rootDic = [parser objectWithString:jsonString error:&error];
2. NSDictionary *weatherInfo = [rootDic objectForKey:@"weatherinfo"];
3. txtView.text = [NSString stringWithFormat:@"今天是 %@  %@  %@  的天气情况是:%@  %@ ",[weatherInfo objectForKey:@"date_y"],[weatherInfo objectForKey:@"week"],[weatherInfo objectForKey:@"city"], [weatherInfo objectForKey:@"weather1"], [weatherInfo objectForKey:@"temp1"]];
4. }
JSONKit 不支持ARC(需导入包:#import “JSONKit/JSONKit.h")
1. //若是json是“单层”的,即value都是字符串、数字,可使用objectFromJSONString
2. NSString *json1 = @"{\"a\":123, \"b\":\"abc\"}";
1. Dictionary *data1 = [json1 objectFromJSONString];

    //若是json有嵌套,即value里有array、object,若是再使用objectFromJSONString,程序可能会报错(测试结果代表:使用由网络或获得的php/json_encode生成的json时会报错,但使用NSString定义的json字符串时,解析成功),最好使用objectFromJSONStringWithParseOptions:  
1. String *json2 = @"{\"a\":123, \"b\":\"abc\", \"c\":[456, \"hello\"], \"d\":{\"name\":\"张三\", \"age\":\"32\"}}";

1. Dictionary *data2 = [json2 objectFromJSONStringWithParseOptions:JKParseOptionLooseUnicode];
    // 记住释放用来保存解析后数据的数组
1. son2 release];

1. 自动释放池底层怎么实现
自动释放池以栈的形式实现:当你建立一个新的自动释放池时,它将被添加到栈顶。当一个对象收到发送autorelease消息时,它被添加到当前线程的处于栈顶的自动释放池中,当自动释放池被回收时,它们从栈中被删除, 而且会给池子里面全部的对象都会作一次release操做.
自动释放池何时会进行回收:在那个大括号执行完毕就会释放回收


KVO内部实现原理
KVO是基于runtime机制实现的
当某个类的对象第一次被观察时, 系统就会在运行期动态地建立该类的一个派生类【就是子类】,在这个派生类中重写基类中任何被观察属性的 setter 方法。 
 NSKVONotifying_Person)◊派生类在被重写的 setter 方法实现真正的通知机制(Person


上图中的NSKVONotifitying_Person就是动态建立的派生类


是否能够把比较耗时的操做放在NSNotificationCenter中
若是在异步线程发的通知,那么能够执行比较耗时的操做;
若是在主线程发的通知,那么就不能够执行比较耗时的操做

3.Foundation对象与Core Foundation对象有什么区别
1> Foundation对象是OC的,Core Foundation对象是C对象
2> Foundation对象和Core Foundation对象是能够互相转换的,数据类型之间的转换
ARC:__bridge_retained、__bridge_transfer
非ARC: __bridge

4.不用中间变量,用两种方法交换A和B的值
A = A + B
• = A - B
• = A - B
或者
A = A^B;
B = A^B;
A = A^B;

6.什么是动态,举例说明
1> 在程序运行过程才执行的操做
2>动态绑定    
3>runtime

7.runtime实现的机制是什么,怎么用,通常用于干吗. 你还能记得你所使用的相关的头文件或者某些方法的名称吗? 
做用
获取类里面的全部成员变量【归档】
为类动态添加成员变量,
动态改变类的方法实现,
为类动态添加新的方法等 
须要导入<objc/message.h><objc/runtime.h>
runtime,运行时机制,它是一套C语言库
• OC代码,最终都是转成了runtime库的东西,好比类转成告终构体等数据类型,方法转成函数,平时调方法都是转成了objc_msgSend函数(因此说OC有个消息发送机制)[p setName:]; --- > objc_msgSend(p, selector(setName:),);
• 拿到全部成员变量,进行归档。Class_copyIvarList([Person class], &count)
• swizzel;  imageWithName,里面判断若是是iOS7,在name图片名后拼接“_os7”,而后image = [UIImage  ImageName:name];不是iOS7,直接image = [UIImage  ImageName:name];返回image便可;可是若是没有用分类方法处理图片,要么一个一个换成ImageWithName,要么swizzle将ImageName方法的实现换成IamgeWithName;表面上调用ImageNamed, 实际上用的ImageWithName。
2.为了不数组不能存nil.给可变数组(Foundation)弄个分类
也能够若是是字符串再添加,避免数组越界;换objectAtIndex;
总结:


CoreText 【就是富文本—用NSAttributedString这个类来作富文本】
随意修改文本的样式
图文混排(纯C语言)
国外:Niumb
Core Image(滤镜处理)
• 能调节图片的各类属性(饱和度, 色温, 色差等) 美图秀秀用到这个

9.NSNotification和KVO的区别和用法是什么?
何时应该使用通知,何时应该使用KVO,它们的实现上有什么区别吗?若是用protocol和delegate(或者delegate的Array)来实现相似的功能可能吗?若是可能,会有什么潜在的问题?若是不能,为何?(虽然protocol和delegate这种东西面试已经面烂了…)
通知比较灵活(1个通知能被多个对象接收, 1个对象能接收多个通知), 

代理比较规范,可是代码多(默认是1对1)可是也能有多个代理,就是让代理都遵照同一份协议

KVO性能很差(底层会动态产生新的类),只能监听某个对象属性的改变, 不推荐使用(1个对象的属性能被多个对象监听,  1个对象能监听多个对象的其余属性)

更详细参考:
http://blog.csdn.net/dqjyong/article/details/7685933

谈谈你对KVC 与 KVO 理解
KVC,便是指 NSKeyValueCoding,一个非正式的 Protocol,提供一种机制来间接访问对象的属性。KVO 就是基于 KVC 实现的关键技术之一。

KVC 运用的技术
• C运用了一个isa- swizzling技术。isa-swizzling就是类型混合指针机制。KVC主要经过isa- swizzling,来实现其内部查找定位的。
isa指针,如其名称所指,(就是is a kind of的意思),指向维护分发表的对象的类。该分发表实际上包含了指向实现类中的方法的指针,和其它数据。
KVC实例:
一个对象拥有某些属性。好比说,一个 Person 对象有一个 name 和一个 address 属性。以 KVC 说法,Person 对象分别有一个 value 对应他的 name 和 address 的 key。 key 只是一个字符串,它对应的值能够是任意类型的对象。从最基础的层次上看,KVC 有两个方法:一个是设置 key 的值,另外一个是获取 key 的值。以下面的例子
void changeName(Person *p, NSString *newName)
{

    // using the KVC accessor (getter) method
    NSString *originalName = [p valueForKey:@"name"];

    // using the KVC  accessor (setter) method.
    [p setValue:newName forKey:@"name"];

    NSLog(@"Changed %@'s name to: %@", originalName, newName);

}
如今,若是 Person 有另一个 key 配偶(spouse),spouse 的 key 值是另外一个 Person 对象,用 KVC 能够这样写:


void logMarriage(Person *p)
{

    // just using the accessor again, same as example above
    NSString *personsName = [p valueForKey:@"name"];

    // this line is different, because it is using
    // a "key path" instead of a normal "key"
    NSString *spousesName = [p valueForKeyPath:@" spouse.name"];

    NSLog(@"%@ is happily married to %@", personsName, spousesName);

}
key 与 key path 要区分开来,key 能够从一个对象中获取值,而 key path 能够将多个 key 用点号 “.” 分割链接起来,好比:
[p valueForKeyPath:@" spouse.name"];
至关于这样……
[[p valueForKey:@"spouse"] valueForKey:@"name"];

Key-Value Observing (KVO) 创建在 KVC 之上,它可以观察一个对象的 KVC key path 值的变化。
优势 
当 有属性改变,KVO会提供自动的消息通知。这样的架构有不少好处。首先,开发人员不须要本身去实现这样的方案:每次属性改变了就发送消息通知。这是KVO机制提供的最大的优势。由于这个方案已经被明肯定义,得到框架级支持,能够方便地采用。开发人员不须要添加任何代码,不须要设计本身的观察者模型,直接能够在工程里使用。其次,KVO的架构很是的强大,能够很容易的支持多个观察者观察同一个属性,以及相关的值。
使用方法
1. 注册,指定被观察者的属性
2. 实现回调方法
3. 移除观察
注意
只有符合KVC标准的对象才能使用kvo
KVO实例:
假设一个场景,股票的价格显示在当前屏幕上,当股票价格更改的时候,实时显示更新其价格。
1.定义DataModel,

1. @interface StockData : NSObject {
2.     NSString * stockName;
3. float price;
4. }
5. @end
6. @implementation StockData
7. @end

2.定义此model为Controller的属性,实例化它,监听它的属性,并显示在当前的View里边
[cpp] view plaincopy

• - (void)viewDidLoad
• {
• [super viewDidLoad];
    4      
1. stockForKVO = [[StockData alloc] init];
2. [stockForKVO setValue:@"searph" forKey:@"stockName"];
3. [stockForKVO setValue:@"10.0" forKey:@"price"];
4. [stockForKVO addObserver:self forKeyPath:@"price" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];
    9      
1. myLabel = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 100, 30 )];
2. myLabel.textColor = [UIColor redColor];
3. myLabel.text = [stockForKVO valueForKey:@"price"];
4. [self.view addSubview:myLabel];
    14         
•         UIButton * b = [UIButton buttonWithType:UIButtonTypeRoundedRect];
• b.frame = CGRectMake(0, 0, 100, 30);
• [b addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpInside];
• [self.view addSubview:b];
    19      
1. }

3.当点击button的时候,调用buttonAction方法,修改对象的属性

[cpp] view plaincopy

1. -(void) buttonAction
2. {
3. [stockForKVO setValue:@"20.0" forKey:@"price"];
4. }

1. 实现回调方法
[cpp] view plaincopy

1. -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
2. {
3. if([keyPath isEqualToString:@"price"])
4. {
5. myLabel.text = [stockForKVO valueForKey:@"price"];
6. }
7. }

5.增长观察与取消观察是成对出现的,因此须要在最后的时候,移除观察者

• - (void)dealloc
• {
• [super dealloc];
• [stockForKVO removeObserver:self forKeyPath:@"price"];
• [stockForKVO release];
• }

KVB:Key Value Binding  键值绑定【补充内容】
KVB实现的两个基本方法
• 为对象添加观察者OBserver  --  addObserver:forKeyPath:options:context:
• )观察者OBserver收到信息的处理函数 -- observerValueForKeyPath:ofObject:change:context:

KVO和KVB最明显的使用场景就是在一些界面实现变化很强的敌方。例如股票走向、售票余数等,可及时更改参数变化状况。





CAAnimation的层级结构

若是使用CAAnimation
建立CAAnimation对象
设置CAAnimation对象的属性
添加CAAnimation对象到CALayer上,CALayer就会自动执行这个动画

UIButton与UITableView的层级结构
层级结构  label  UIImage  NSObjcet->UIResponder->UIView->UIControl->UIButton
内部的子控件结构    cell 分割线  UIView->UIScrollView>UITableView
  设置scroll view的contensize能在Viewdidload里设置么,为何
1. ,可能不太安全。子控制器的frame在viewDidLoad和ViewWillAppear时可能不同,若是scrollView的contentSize = 375 是基于子控制器的View(等于),当子控制器变小时,contentSize就变小了。




按钮或者其它UIView控件的事件传递的具体过程

UIResponder有一个nextResponder属性,经过该属性能够组成一个响应者链,事件或消息在其路径上进行传递
若是UIResponder没有处理传给它的事件,会将未处理的消息转发给本身的nextResponder




控制器View的生命周期及相关函数是什么?你在开发中是如何用的?
• 1.首先判断控制器是否有视图,若是没有就调用loadView方法建立:经过storyboard或者代码;
• 2.随后调用viewDidLoad,能够进行下一步的初始化操做;只会被调用一次;
• 3.在视图显示以前调用viewWillAppear;该函数能够屡次调用;
• 4.视图viewDidAppear

• 3.在视图显示以前调用viewWillDisappear;该函数能够屡次调用;
如须要);
• 5.在布局变化先后,调用viewWill/DidLayoutSubviews处理相关信息;
6.viewWillDisappear ViewDidDisappear   
8.父子关系  
1.控制器 子控制器调用navigationController 会看一下当前控制器是否在一个导航控制器里面,在就把这个导航控制器拿过来,没有就看一下父控制器是否在导航控制器里,再拿来
2.旋转屏幕默认只有window的rootViewController才会旋转,只有具有父子关系,子控制器才会触发旋转方法。
1. NSRunLoop的实现机制,及在多线程中如何使用

NSRunLoop是IOS消息机制的处理模式
>做用:控制NSRunLoop里面线程的执行和休眠,
>NSRunLoop 就是一直在循环检测,从线程start到线程end,检测inputsource(如点击,双击等操做)异步事件,检测timesource同步事件,检测到输入源会执行处理函数,首先会产生通知,core function向线程添加runloop observers来监听事件,意在监听事件发生时来作处理。
>3.runloopmode是一个集合,包括监听:事件源,定时器,以及需通知的runloop observers

1.  只有在为你的程序建立次线程的时候,才须要运行run loop。对于程序的主线程而言,run loop是关键部分。Cocoa提供了运行主线程run loop的代码同时也会自动运行run loop。IOS程序UIApplication中的run方法在程序正常启动的时候就会启动run loop。若是你使用xcode提供的模板建立的程序,那你永远不须要本身去启动run loop
2.  在多线程中,你须要判断是否须要run loop。若是须要run loop,那么你要负责配置run loop并启动。你不须要在任何状况下都去启动run loop。好比,你使用线程去处理一个预先定义好的耗时极长的任务时,你就能够毋需启动run loop。Run loop只在你要和线程有交互时才须要


3简单说一下APP的启动过程,从main文件开始提及
    程序启动分为两类:1.有storyboard 2.没有storyboard
有storyboard状况下:
1.main函数
2.UIApplicationMain
• 建立UIApplication对象
• 建立UIApplication的delegate对象
3.根据Info.plist得到最主要storyboard的文件名,加载最主要的storyboard(有storyboard)
• 建立UIWindow
• 建立和设置UIWindow的rootViewController
• 显示窗口

没有storyboard状况下:
1.main函数
2.UIApplicationMain
• 建立UIApplication对象
• 建立UIApplication的delegate对象
3.delegate对象开始处理(监听)系统事件(没有storyboard)
• 程序启动完毕的时候, 就会调用代理的application:didFinishLaunchingWithOptions:方法
• 在application:didFinishLaunchingWithOptions:中建立UIWindow
• 建立和设置UIWindow的rootViewController
• 显示窗口

4把程序本身关掉和程序进入后台,远程推送的区别
1. 关掉后不执行任何代码, 不能处理事件
2. 应用程序进入后台状态不久后转入挂起状态。在这种状态下,应用程序不执行任何代码,并有可能在任意时候从内存中删除。只有当用户再次运行此应用,应用才会从挂起状态唤醒,代码得以继续执行
3.或者进入后台时开启多任务状态,保留在内存中,这样就能够执行系统容许的动做
4.远程推送是由远程服务器上的程序发送到APNS,再由APNS把消息推送至设备上的程序,当应用程序收到推送的消息会自动调用特定的方法执行事先写好的代码
5(void)application:(UIApplication*)application   didReceiveRemoteNotification:(NSDictionary*)userInfo 

{// alert   // 前台
 
if (application.applicationState == UIApplicationStateActive) { 

        UILocalNotification *notification=[[UILocalNotification alloc] init]; 
        
if(notification!=nil){ 
NSDate*date=[NSDate dateWithTimeIntervalSinceNow:10]; 


         notification.fireDate=date ; 
          
notification.timeZone=[NSTimeZone defaultTimeZone];
           
notification.alertBody= [[userInfo objectForKey:@"aps"] objectForKey:@"alert"]; 

notification.soundName= UILocalNotificationDefaultSoundName;  

notification.userInfo = userInfo;

[[UIApplicationsharedApplication] scheduleLocalNotification:notification]; 
[self playSound]; 



5本地通知和远程推送通知对基本概念和用法?





键盘呼出时的通知

  // 注册通知
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChange) name:UITextViewTextDidChangeNotification object:textView];
       // 监听键盘的弹出的隐藏
    // 监听键盘弹出和退下
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWillShow:) name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(keyboardWillHide:) name:UIKeyboardWillHideNotification object:nil];
-(void)keyboardWillShow:(NSNotification *)noti
{
    // 取出键盘弹出的时间
    CGFloat duration = [noti.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];

    // 取出键盘高度
    CGRect keyBoardRect = [noti.userInfo[UIKeyboardFrameEndUserInfoKey] CGRectValue];
    CGFloat keyBoardHeight = keyBoardRect.size.height;

1. IView animateWithDuration:duration delay:0.0 options:7 << 16 animations:^{
        self.toolBar.transform = CGAffineTransformMakeTranslation(0, -keyBoardHeight);

    } completion:^(BOOL finished) {

    }];

}

-(void)keyboardWillHide:(NSNotification *)noti
{
    // 取出键盘隐藏的时间
    CGFloat duration = [noti.userInfo[UIKeyboardAnimationDurationUserInfoKey] doubleValue];
    // 清空transform
    [UIView animateWithDuration:duration animations:^{
        self.toolBar.transform = CGAffineTransformIdentity;
    }];

1. IView animateWithDuration:duration delay:0.0 options:7 << 16 animations:^{
         self.toolBar.transform = CGAffineTransformIdentity;

    } completion:^(BOOL finished) {

    }];

}

copy、retain、assign、strong、weak怎样用,如何区别,原子性和非原子性的区别
 声明property的语法为:@property (参数1,参数2) 类型 名字;

其中参数主要分为三类:

读写属性: (readwrite/readonly)
setter语意:(assign/retain/copy)
原子性: (atomicity/nonatomic)

各参数意义以下:

readwrite: 产生setter\getter方法
readonly: 只产生简单的getter,没有setter。
assign: 默认类型,setter方法直接赋值,而不进行retain操做  通常基本数据类型用该属性声明,好比,int, BOOL。
retain: setter方法对参数进行release旧值,再retain新值。 该属性与 strong 一致;只是可读性更强一些。
copy: setter方法进行Copy操做,与retain同样        与 strong 的区别是声明变量是拷贝对象的持有者。
nonatomic: 禁止多线程,变量保护,提升性能
weak:该属性与 strong 一致;只是可读性更强一些。

若是使用多线程,有时会出现两个线程互相等待对方致使锁死的状况(在没有(nonatomic)的状况下,即默认(atomic),会防止这种线程互斥出现,可是会消耗必定的资源。因此若是不是多线程的程序,打上(nonatomic)便可

十、block写一个方法,该方法能够快速查找到离某个视图最近的父视图
十二、代理为何要用weak
防止循环引用
在MRC的时候是用assign来修饰,在ARC以后用
unsafe_unretained,做用是跟weak相似的。主要是为了防止循环引用。好比A引用了B,B引用了C,C又引用了A,这样循环引用以后,若是用strong强引用来修饰,这个代理就永远释放不掉了。
1四、pickerView的使用
和tableView差很少  记得遵照协议和代理
//数据源的代理方法
-(NSInteger)numberOfComponentsInPickerView:(UIPickerView *)pickerView//返回显示的列数  
-(NSInteger) pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component //返回当前列显示的行数 
//代理方法
-(NSString*)pickerView:(UIPickerView *)pickerView titleForRow:(NSInteger)row forComponent:(NSInteger)component
//返回当前行的内容,此处是将数组中数值添加到滚动的那个显示栏上
1五、极光推送(JPUSH)的使用流程及原理

1. ush iOS Push 包括 2 个部分,APNs 推送(代理),与 JPush 应用内消息。
红色部分是 APNs 推送,JPush 代理开发者的应用(须要基于开发者提供的应用证书),向苹果 APNs 服务器推送。由 APNs Server 推送到 iOS 设备上。
蓝色部分是 JPush 应用内推送部分,即 App 启动时,内嵌的 JPush SDK 会开启长链接到 JPush Server,从而 JPush Server 能够推送消息到 App 里。
应用内消息
应用内消息:JPush iOS SDK 提供的应用内消息功能,在 App 在前台时可以收到推送下来的消息。App 可以使用此功能来作消息下发动做。
此消息不通过 APNs 服务器,彻底由 JPush 提供功能支持。



JPush APNs 有神魔用
iOS 平台上,只有 APNs 这个官方的推送通道,是能够随时送达的。通常开发者都是本身部署应用服务器向 APNs Server 推送。
JPush APNs 作推送代理,其意义又在哪里呢?JPush APNs 相比直接向 APNs 推送有什么好处呢?
    •    减小开发及维护成本:
    ◦    应用开发者不须要去开发维护本身的推送服务器与 APNs 对接。
    ◦    集成了 JPush iOS SDK 后没必要本身维护更新 device token。
    ◦    经过 JPush 的 Web Portal 直接推送,也能够调用JPush的 HTTP 协议 API 来完成,开发工做量大大减小。
    •    减小运营成本:
    ◦    极光推送支持一次推送,同时向 Android, iOS, WinPhone 三个平台。支持统一的 API 与推送界面。
    ◦    极光推送提供标签、别名绑定机制,以及提供了很是细分的用户分群方式,运营起来很是简单、直观。
    •    提供应用内推送:
    ◦    除了使得 APNs 推送更简单,也另外提供应用内消息推送。这在相似于聊天的场景里颇有必要。




1六、MJExtion如何使用,若是写的model里有这个属性,后台数据没有,程序会不会崩
MJExtension很强大,几乎支持现有全部的模型、字典、json数据转换,并且效率很是高
MJExtension很是好用可是容易被忽略的功能:无论你的模型属性有几百个,只须要加一句宏MJCodingImplementation,就能实现归档解档,不用再编写恶心的encodeWithCoder:和initWithCoder:了
经过plist来建立一个模型
1.( filename 文件名(仅限于mainBundle中的文件)
(instancetype)objectWithFilename:(NSString *)filename;
2.(file 文件全路径)
+(instancetype)objectWithFile:(NSString *)file;
经过字典数组来建立一个模型数组
(NSMutableArray *)objectArrayWithKeyValuesArray:(id)keyValuesArray;


1九、如何改变代码块儿里的值  

2二、深拷贝和浅拷贝的区别,如何实现深拷贝
浅拷贝    只是对指针的拷贝,拷贝后两个指针指向同一个内存空间
深拷贝    不但对指针进行拷贝,并且对指针指向的内容进行拷贝,经深拷贝后的指针是指向两个不一样地址的指针
2四、经常使用的第三方框架,他们解决了哪些问题
       1.AFNetworking
       2.MBProgressHUD
       3.MJExtension
       4.MJRefresh
       5.SDWebImage
       6.UMSocial_sdk<友盟分享>

2五、ios开发传值方式有哪些
       1.设置委托
        2.extern   @interface以前定义extern NSString *strZhi;
        3.对象的property属性传值
          4.方法的参数传值
          5.静态方法传值
          6.用给 指向 指针的指针 赋值 的方式传值
          7.NSNotification (观察者模式)
          8.单例
1. 3 NSUserDefaults
 .h
#define myAvgcost @"myavgcost"
.m
[[NSUserDefaults standardUserDefaults] setObject:p_Avgcost_arr forKey:myAvgcost];//写道磁盘
传到另外一个类
NSArry *myAvgcost_arr=[[NSUserDefaults standardUserDefaults] arrayForKey:myAvgcost];
          10.delegate
              主要是要把共享的数据设置为XXDelegate的一个成员变量;
              而后在须要的地方经过以下方法得到一个XXDelegate的对象,以下:
              XXDelegate*app = (XXDelegate *) [[UIApplicationsharedApplication] delegate];
              每次获取delegate并非建立一个新app,每一个app只有一个delegate。



2六、ios怎么作到性能优化


30、介绍一下MVC以及动态方法和静态方法的区别
 1.静态的方法在整个应用程序其间存储在内存中,速度快,但占用内存. 
  2.动态的方法在先声明类实例才能调用类中的方法
   3.通常使用频繁的方法用静态方法,用的少的方法用动态的。静态的速度快,占内存。动态的速度相对慢些,但调用完后,当即释放类,能够节省内存,
4.静态方法主要的问题就是数据同步的问题。若是你的静态方法的类中不保存私有变量那么什么问题都不会有的。最好是包要操做的数据所有以参数的方式传到方法中去
1. 静态方法是类方法,调用时不须要建立类实例。
2. 静态方法是静态绑定到子类,不是被继承
7.从面向对象的角度来看: 
静态方法面向的是类的操做,而实力方法面向的是对象.
8.静态方法修改的是类的状态,而对象修改的是各个对象的状态,这点也是它们重要的区别

9.类的实例化调用是在类的生命周期中存在,当类没有了之后,对应的实例也就没有了,对应的方法也就没有了,静态类否则,只要你引用了那个静态类的命名空间,他就会一直存在,直到你退出系统。

3一、谈谈MVC在CocoaTouch中的实现

 M-Model(模型)是应用系统中与视图对应部分的数据;
V-View(视图)是应用系统中用户看到并与之交互的界面;
C-Controller(控制器)在应用系统中起到控制器做用,用来接受用户事件、显示数据、与视图进行交互等。

3二、有两个字符串@“hello”,@“world”你有几种方法将它俩拼接在一块儿

//方法1.
1. ring = [NSString initWithFormat:@"%@,%@", string1, string2 ];
//方法2.
1. ring = [string1 stringByAppendingString:string2];
2. 方法3 .
string = [string stringByAppendingFormat:@"%@,%@",string1, string2];
//截取字符串
• (NSString *)substringFromIndex:(NSUInteger)from;
• (NSString *)substringToIndex:(NSUInteger)to;
• (NSString *)substringWithRange:(NSRange)range;
3三、一个列表有足够多得显示区域,滑动了一下,如何判断是向上滑动仍是向下滑动。
偏移量
• (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView {
    oldY = scrollView.contentOffset.y;
}

• (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
   if( scrollView.contentOffset.y > oldY) {
  向下
}else{
向上

3四、有这样一段json数据{“title”:“null”},转成字典以后将title对应的value赋值在一个label.text上,会出现什么问题


3五、请简单描述一下ios中的KVO实现方式

3六、如何判断一个字典中是否含有某个key
       1.for in   2.遍历器  3.dictionary.allkeys  containt 
3七、属性readwrite,readonly,assign,copy,nonatomic各是什么做用?在哪些状况下用

3八、OC建立线程的方法是什么?若是在主线程中执行代码,方法是什么?若是想演示执行代码,方法又是什么

3九、#import,# include@class有什么区别?

40、OC中书写一个单例模式,使用GCD书写单例

4一、说明weak与_weak的做用及经常使用在何时


4六、通知跟代理的区别分别写一个通知及代理





//自我发挥
1.是否有本身的设备
2.作过什么项目
3.参与整个项目开发的有多少人,除了跟本身的团队沟通,有跟后台沟经过么
相关文章
相关标签/搜索