引入:读AFNetworking ~> '0.5.1'
一、NSAutoreleasePool
虽然ARC引入之后NSAutoReleasePool的使用有了很大变化,但是了解NSAutoReleasePool的机制还是十分必要的,下面主要说一下:
NSAutoReleasePool * pool = [NSAutoReleasePool alloc] init];
//do something
[[NSRunLoop currentRunLoop] run];
[pool drain];
之后,
[pool drain]
和[pool release]
的区别:
release,在引用计数环境下,由于NSAutoReleasePool是一个不可以被retain的类型,所以release会直接dealloc pool对象。当pool被dealloc的时候,pool向所有在pool中的对象发出一个release的消息,如果一个对象在这个pool中autorelease了多次,pool对这个对象的每一次autorelease都会release。在GC环境下release是一个no-op操作(代表没有操作,是一个占据进行很少的空间但是指出没有操作的计算机指令)。
drain,在引用计数环境下,它的行为和release是一样的。在GC的环境下,这个方法调用objc_collect_if_needed出发GC。
因此,重点是:在GC环境下,release是一个no-op,所以除非你不希望在GC环境下出发GC,你都应该使用drain而不是使用release来释放pool。
引入:
- (void)setCancelled:(BOOL)isCancelled {
[self willChangeValueForKey:@"isCancelled"];
_cancelled = YES;
[self didChangeValueForKey:@"isCancelled"];
self.state = AFHTTPOperationFinishedState;
}
二、键-值编码(KVC)、KVO、NSNotificationCenter
键-值编码 KVC
setValue:forKey:通过名称(字符串)设置任何属性的值,字符串可在运行时修改
[aObject setValue:theValue forKey:theKey];
valueForKey:从对象中获取属性的值
NSString *aString = [aObject valueForKey:theKey];
其实与getter,setter一样,但更加灵活。
键-值观察 Key-Value Observing, KVO
控制器获知何时更新视图
- 反复检查模型观察是否有任何更改
- 创建计时器,定期从模型中获取最新值,并提供给视图
- 浪费资源:时间,CPU,电池
- 等待模型向控制器通知变化
- 允许对象注册为 当另一个对象 更改它的一个属性的值时收到通知
- 注册更改通知
- 当属性修改时,需要被通知的对象(观察者)
- 被观察者的属性名称
- 当一个变化发生时,观察者应该被告知的信息
- [optional]包含一个指针或引用,当属性值发生变化时,指针或对象引用应该被传递到运行的方法中
- 注册(添加)通知
[aProduct addObserver:self
forKeyPath:@"productName"
options:(NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld)
context:nil];
当一个对象被注册为另一个对象的一个观察者时,该对象(如:观察者)将接收observeValueForKeyPath:ofObject:change:context:消息
属性发生变化的对象
发生变化的属性对象
一个包含变化信息的NSDictionary
当此消息被调用时,context变量将传递进去
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if([keyPath isEqualToString:@"productName"])
{
NSString *newName = [change objectForKey:NSKeyValueChangeNew];
//通知响相应视图根据newName变量的值进行更新
}
}
- NSDictionary包含不同的信息和其他键
- NSKeyValueObservingOptionNew 属性要被设置的值
- NSKeyValueObservingOptionOld 属性之前的值
- 将变化通知给观察者
使用了Objective-C的属性@property,当setter被调用时,Cocoa自动通知任何已注册的观察者
不使用属性,或重写了setter,需要手动通知系统
对self对象调用willChangeValueForKey与didChangeValueForKey,跟踪新值,旧值
重写setter,同时允许KVO工作
- (void) setProductName:(NSString *)newProductName
{
[self willchangeValueForKey:@"productName"];
productName = newProductName;
[self didChangeValueForKey:@"productName"];
}
使用NSNotification进行通知
某些相关联的事情发生,使用广播通知
按下Home键
- NSNotification对注册对象发送广播通知,由NSNotificationCenter管理,是单例对象
相应Home键按下 - 注册通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(applicationEnteredBackground:) UIApplicationDidEnterBackgroundNotification object:nil];
- 当
UIApplicationDidEnterBackgroundNotification
传递出去,注册的对象将运行applicationenteredBackground:
方法,此方法定义在该对象所属类中
- (void)applicationEnteredBackground:(NSNotification *)notification
{
//进入后台,进行处理
}
- 不希望接收到消息
[[NSNotificationCenter defaultCenter] removeObserver:self]
引入:
在阅读AFN的源码的时候,发现只有(HTTP、Image)RequestOperation和AFRestClient。RequestOperation很好理解就是一项请求操作,里面包括了NSURLConnection的代理方法,在这里进行网络请求,得到服务器返回的数据,但是在这里并没有执行这个操作,只是把这个请求操作封装好了。(这个时候我就想应该会在某个地方调用
[operation start]
这个方法来获取数据,但是我搜索整个库,发现并没有地方调用这个操作,这就很纳闷了)AFN是怎么开始开始请求的呢,后面发现在AFRestClient里面用到了这个operation,AFRestClient先是对请求头,请求方法和请求参数进行了一次封装,然后就是执行相应的RequestOperation,但是这里也没有调用[operation start]
,只是调用了[self.operationQueue addOperation:operation]
这时候去查资料,才有了下面的内容
AFHTTPRequestOperation *operation = [AFJSONRequestOperation operationWithRequest:request success:success failure:failure];
[self.operationQueue addOperation:operation];
三、Operation
- 系统自动将NSOperationqueue中的NSOperation对象取出,将其封装的操作放到一条新的线程中执行。
提示:队列的取出是有顺序的,与打印结果并不矛盾。这就好比,选手A,B,C虽然起跑的顺序是先A,后B,然后C,但是到达终点的顺序却不一定是A,B在前,C在后。 - 只要NSBlockOperation封装的操作数 > 1,就会异步执行操作
- NSOperationQueue的作⽤:NSOperation可以调⽤start⽅法来执⾏任务,但默认是同步执行的
- 如果将NSOperation添加到NSOperationQueue(操作队列)中,系统会自动异步执行NSOperation中的操作
- 添加操作到NSOperationQueue中,自动执行操作,自动开启线程
- 操作对象默认在主线程中执行,只有添加到队列中才会开启新的线程。即默认情况下,如果操作没有放到队列中queue中,都是同步执行。只有将NSOperation放到一个NSOperationQueue中,才会异步执行操作。
- 当我们把operation添加到队列中去后,就相当于把operation交给了系统,然后由系统决定它的执行顺序。
从网上摘抄了一篇非常详细的Operation介绍
四、AFNetworking的内容
- AFHTTPRequestOperation(NSOperation)
封装一整套请求操作,有NSURLConnection的代理方法,得到服务器返回的数据,还有对抽象类NSOperation的具体实现,是下面图片链接请求和JSON数据请求的基类
- AFImageCache(NSCache)
对图片进行缓存和获取缓存图片,使用的是图片链接+图片的尺寸当做key缓存的
- AFImageRequestOperation(AFHTTPRequestOperation)
单独对网络图片请求进行封装,对图片进行简单的处理,同时在请求到图片后,对图片进行缓存
- AFJSONRequestOperation(AFHTTPRequestOperation)
处理返回结果,把结果JSON格式化,首先是判断没有错误,然后判断是否包含正确的状态码,如果不包含,自定义error,再判断是否包含正确
MIMEType
,如果不包含,自定义error,再判断如果错误,返回failure块,包含请求,响应,错误,如果返回结果长度为0,直接返回success,最后异步处理正常情况,请求成功,有数据,如果系统版本大于4.3,使用系统自带的NSJSONSerialization
,对返回数据JSON化,如果小于4.3,使用第三方框架JSONKit,对返回数据JSON化,处理成功返回success(request, response, JSON)
,处理失败返回failure(request, response, JSONError)
- AFNetworkActivityIndicatorManager(NSObject)
对状态栏网络信号小菊花的简单封装,开始和结束动画
- AFRestClient(NSObject)
真正开始请求网络的地方,包含get、post、pull、delete请求方法,也可以取消网络请求,设置请求头
- NSData + AFNetworking
NSData的扩展,包括base64编码,压缩和解压,使用的是zlib压缩函式库
- NSMutableURLRequest + AFNetworking
NSMutableURLRequest的扩展,提供对请求体的处理方法
- NSString + AFNetworking
NSString的扩展,提供对请求链接url使用当初ASI里面的方法编码
CFURLCreateStringByAddingPercentEscapes
- UIImage + AFNetworking
UIImage扩展,对UIImage进行裁剪,带圆角的裁剪
- UIImageView + AFNetworking
UIImageView的扩展,提供给我们之间使用的,设置网络图片链接给UIImageView来展示图片,如果有缓存改图片,之间去缓存图片,取消网络请求
简单整理,如果错误,欢迎指正,谢谢~
持续更新