AFNetworking-UIKit

AFNetworkActivityIndicatorManager

http://www.cnblogs.com/machao/p/5813054.html
http://blog.sunnyxx.com/2014/03/09/objc_kvo_secret/
https://stackoverflow.com/questions/3018242/when-to-use-willchangevalueforkey-and-didchangevalueforkey
https://github.com/garnett/DLIntrospection
https://stackoverflow.com/questions/6317889/what-does-synchronized-do

  • 系统提供的方法仅仅支持显示和关闭。如何保证网络开始的时候在转,结束之后停止就是本类解决的问题。
  • 接收了AFNetworking的三个通知来确定当前网络状态,AFNetworkingTaskDidResumeNotification, AFNetworkingTaskDidSuspendNotification, AFNetworkingTaskDidCompleteNotification
  • 提醒中包含了具体的请求信息,通过
    1
    2
    3
    4
    5
    6
    7
    static NSURLRequest * AFNetworkRequestFromNotification(NSNotification *notification) {
    if ([[notification object] respondsToSelector:@selector(originalRequest)]) {
    return [(NSURLSessionTask *)[notification object] originalRequest];
    } else {
    return nil;
    }
    }

来提取具体是哪个Request以及请求是否有效

  • 此类仅在iOS使用。如何保证在MAC下不会引用到此库?#import <TargetConditionals.h>,然后将主要逻辑放在 #if TARGET_OS_IOS 即可
  • NS_ASSUME_NONNULL_BEGIN和NS_ASSUME_NONNULL_END表示区域内的代码都默认NONNULL
  • NS_EXTENSION_UNAVAILABLE_IOS(“reason”) 这个宏在 NSObjcRuntime.h里面。表示此类不能扩展, 除此之外NS_ASSUME_NONNULL_BEGIN, YES, NO , MAX, ABS等都在这个header中
  • 整个类实际上操作的是系统的API[[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:networkActivityIndicatorVisible];

UIActivityIndicatorView (AFNetworking), UIRefreshControl (AFNetworking)

- (void)setAnimatingWithStateOfTask:(nullable NSURLSessionTask *)task;通过这个方法来自动控制uiactivityIndicatorView的动画

  • 如果自己做的话,想到就是监听notification.但是因为是一个category,监听到哪个object,是否监听到UIActivityIndicatorView问题在哪
  • 分类中不能重写方法,因为会影响所有使用分类的人https://www.zhihu.com/question/26454432
    如果在调用的时候就给当前UIActivityIndicatorView添加notificationobserver, 感觉也可以,用dispatch_once保证只调用一次.
  • 但是单独用一个observer的类代码逻辑会更干净,只用了一个getter拿到这个类
1
2
3
4
5
6
7
8
- (AFActivityIndicatorViewNotificationObserver *)af_notificationObserver {
AFActivityIndicatorViewNotificationObserver *notificationObserver = objc_getAssociatedObject(self, @selector(af_notificationObserver));

if (notificationObserver == nil) {
notificationObserver = [[AFActivityIndicatorViewNotificationObserver alloc] initWithActivityIndicatorView:self];
objc_setAssociatedObject(self, @selector(af_notificationObserver), notificationObserver, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
return notificationObserver;
}

UIWebView (AFNetworking)

原因是UIWebView只定义了一个loadRequest的方法来自定义request请求, 他开放的两个方法的目的是给更多的可定制性出来。
最开始的时候有库是做的假进度条。这个相当于直接把AFNetworking的进度拿来用。
实质实际上是请求request之后拿到text,再调用了uiwebview的loadData方法

1
2
3
4
5
6
7
8
9
10
11
- (void)loadRequest:(NSURLRequest *)request
progress:(NSProgress * _Nullable __autoreleasing * _Nullable)progress
success:(nullable NSString * (^)(NSHTTPURLResponse *response, NSString *HTML))success
failure:(nullable void (^)(NSError *error))failure;

- (void)loadRequest:(NSURLRequest *)request
MIMEType:(nullable NSString *)MIMEType
textEncodingName:(nullable NSString *)textEncodingName
progress:(NSProgress * _Nullable __autoreleasing * _Nullable)progress
success:(nullable NSData * (^)(NSHTTPURLResponse *response, NSData *data))success
failure:(nullable void (^)(NSError *error))failure;

UIImageView (_AFNetworking)

  • NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; [request addValue:@"image/*" forHTTPHeaderField:@"Accept"];
    添加Accept,只指定接收某一部分的内容
  • 使用af_activeImageDownloadReceipt,一个AFImageDownloadReceipt来标识当前请求的图片。AFImageDownloadReceipt存在的原因是用来标识不同请求,因为有可能同一个url也相当于不同请求,所以不能单纯的用nsurlsessiondask

UIButton(AFNetworking)

category中enum的key
四个不同的动态属性

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
static char AFImageDownloadReceiptNormal;
static char AFImageDownloadReceiptHighlighted;
static char AFImageDownloadReceiptSelected;
static char AFImageDownloadReceiptDisabled;

static const char * af_imageDownloadReceiptKeyForState(UIControlState state) {
switch (state) {
case UIControlStateHighlighted:
return &AFImageDownloadReceiptHighlighted;
case UIControlStateSelected:
return &AFImageDownloadReceiptSelected;
case UIControlStateDisabled:
return &AFImageDownloadReceiptDisabled;
case UIControlStateNormal:
default:
return &AFImageDownloadReceiptNormal;
}
}

AFAutoPurgingImageCache(NSObject)

  • AFImageRequestCache(子类),AFImageCache(父类)定义了imagecache的基本方法
1
2
3
4
5
6
7
8
9
@interface AFCachedImage : NSObject

@property (nonatomic, strong) UIImage *image;
@property (nonatomic, strong) NSString *identifier;
@property (nonatomic, assign) UInt64 totalBytes;
@property (nonatomic, strong) NSDate *lastAccessDate;
@property (nonatomic, assign) UInt64 currentMemoryUsage;

@end
  • 直接根据UIImage就可以算出图片的bitmap大小
1
2
3
4
CGSize imageSize = CGSizeMake(image.size.width * image.scale, image.size.height * image.scale);
CGFloat bytesPerPixel = 4.0;
CGFloat bytesPerRow = imageSize.width * bytesPerPixel;
self.totalBytes = (UInt64)bytesPerPixel * (UInt64)bytesPerRow;
  • dispatch_barrier https://zhangping.gitbooks.io/duo_xian_cheng-4-0/content/day02/dispatchbarrier_async.html
  • 添加图片的时候做了两件事情,一个是把当前的大小加进去(dispatch_barrier_async)。一个是算一下总大小。如果大于purged_image_size那么就根据lastAccessDate来排序,然后根据没有使用的来一点点删除掉
  • 具体的缓存就是通过一个字典来实现,都放在了内存中

AFImageDownloader

下载图片分五部

  • Append the success and failure blocks to a pre-existing request if it already exists
  • Attempt to load the image from the image cache if the cache policy allows it
  • Create the request and set up authentication, validation and response serialization
  • Store the response handler for use when the request completes
  • Either start the request or enqueue it depending on the current active request count