1、CFNetwork
CFNetwork 是基于 OS 层 BSDSocket 封装(纯 C),用于网络通信,早期的网络请求框架 ASIHTTPRequest 就是基于 CFNetwork 进行的封装。
主要使用的 API:CFSocket 用于底层的通信,CFStream 用于数据的读写。
2、基本使用
2.1 下载图片
-
下载图片
#import <CFNetwork/CFNetwork.h> @interface ViewController () @property (weak, nonatomic) IBOutlet UIImageView *imageV; @property (nonatomic, strong) NSMutableData *imageData; @end @implementation ViewController - (IBAction)requestImage:(id)sender { [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; [NSThread detachNewThreadSelector:@selector(startRequest) toTarget:self withObject:nil]; } - (void)startRequest { // url CFStringRef urlStr = CFSTR("http://pics.sc.chinaz.com/files/pic/pic9/201605/apic20649.jpg"); // GET 请求 CFStringRef method = CFSTR("GET"); // 构造 url CFURLRef url = CFURLCreateWithString(kCFAllocatorDefault, urlStr, NULL); // http 请求 CFHTTPMessageRef request = CFHTTPMessageCreateRequest(kCFAllocatorDefault, method, url, kCFHTTPVersion1_1); CFRelease(url); // 创建一个读取流,读取网络数据 CFReadStreamRef readStream = CFReadStreamCreateForHTTPRequest(kCFAllocatorDefault, request); CFRelease(request); // 设置流的 context,这里将 self 传入,用于回调 CFStreamClientContext ctx = {0, (__bridge void *)(self), NULL, NULL, NULL}; // 设置回调事件,用于监听网络事件 // kCFStreamEventNone,(没有事件发生) // kCFStreamEventOpenCompleted,(流被成功打开) // kCFStreamEventHasBytesAvailable,(有数据可以读取) // kCFStreamEventCanAcceptBytes,(流可以接受写入数据(用于写入流)) // kCFStreamEventErrorOccurred,(在流上有错误发生) // kCFStreamEventEndEncountered ,(到达了流的结束位置) CFOptionFlags event = kCFStreamEventHasBytesAvailable | kCFStreamEventEndEncountered; CFReadStreamSetClient(readStream, event, myCallBack, &ctx); // 打开输入流 CFReadStreamOpen(readStream); // 将流加入到 runloop 中 CFReadStreamScheduleWithRunLoop(readStream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); // 开启 runloop CFRunLoopRun(); } // 回调函数 void myCallBack(CFReadStreamRef stream, CFStreamEventType type, void *clientCallBackInfo) { ViewController *selfClass = (__bridge ViewController *)clientCallBackInfo; if (type == kCFStreamEventHasBytesAvailable) { UInt8 buff[255]; CFIndex length = CFReadStreamRead(stream, buff, 255); if (!selfClass.imageData) { selfClass.imageData = [NSMutableData data]; } [selfClass.imageData appendBytes:buff length:length]; } if (type == kCFStreamEventEndEncountered) { [UIApplication sharedApplication].networkActivityIndicatorVisible = NO; [selfClass requestImageComplete]; // 关闭流 CFReadStreamClose(stream); // 将流从 runloop 中移除 CFReadStreamUnscheduleFromRunLoop(stream, CFRunLoopGetCurrent(), kCFRunLoopCommonModes); } } - (void)requestImageComplete { UIImage *image = [UIImage imageWithData:self.imageData]; self.imageV.image = image; } @end