iOS开发 ☞ OS_dispatch_data
来源:互联网 发布:命名实体识别算法 编辑:程序博客网 时间:2024/05/17 02:03
有时在请求网络数据时并没有返回NSData,而是返回OS_dispatch_data
NSData实际上是仅仅提供接口的类簇,并且有很多种特别的实现,推断OS_dispatch_data是这样一种实现NSData is actually a class cluster which just provides the interface, and there are multiple special implementations for it around. It appears that OS_dispatch_data is such a special implementations made to pass data objects around blocks
OS_dispatch_data 是 dispatch_data_t (在iOS7和Mavericks上)可以用NSData无缝桥接,你可以很轻松的通过向下转型获得NSDataOS_dispatch_data is dispatch_data_t which has toll-free bridging with NSData on iOS 7 and Mavericks. You can simply cast it to NSData *.So, in your case you can write:NSData *dataCast = self.message.data;NSString *dataString = [[NSString alloc] initWithData:dataCast encoding:NSUTF8StringEncoding];
一件小事引发的血案:当我们使用原生API发送一个Get请求时,首先想到下面的方法
NSURLSession *session = [NSURLSession sharedSession]; NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:@"XXXX"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { }];[task resume];
如果使用AFN则使用下面的方法
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; manager.responseSerializer = [AFHTTPResponseSerializer serializer]; manager.responseSerializer.acceptableContentTypes = [manager.requestSerializer setCachePolicy:NSURLRequestReloadIgnoringLocalCacheData]; [manager GET:@"XXXX" parameters:nil progress:^(NSProgress * _Nonnull downloadProgress) { } success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { }];
但是上面返回的确是OS_dispatch_data,而下面的responseObject返回的确是NSData,虽然OS_dispatch_data可以无缝桥接转换,但我们都知道AFN3.0封装的就是NSURLSession,那么从这一点入手,分析问题。
首先,分析一下是否是请求头的问题,
发现不一样的是User-Agent 和 Accept-Language 虽然这个并不会影响返回数据,但是还是看看AFN的源码吧
userAgent = [NSString stringWithFormat:@"%@/%@ (%@; iOS %@; Scale/%0.2f)", [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleExecutableKey] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleIdentifierKey], [[NSBundle mainBundle] infoDictionary][@"CFBundleShortVersionString"] ?: [[NSBundle mainBundle] infoDictionary][(__bridge NSString *)kCFBundleVersionKey], [[UIDevice currentDevice] model], [[UIDevice currentDevice] systemVersion], [[UIScreen mainScreen] scale]];
// Accept-Language HTTP Header; see http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.4 NSMutableArray *acceptLanguagesComponents = [NSMutableArray array]; [[NSLocale preferredLanguages] enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) { float q = 1.0f - (idx * 0.1f); [acceptLanguagesComponents addObject:[NSString stringWithFormat:@"%@;q=%0.1g", obj, q]]; *stop = q <= 0.5f; }]; [self setValue:[acceptLanguagesComponents componentsJoinedByString:@", "] forHTTPHeaderField:@"Accept-Language"];
与此同时 ,我无聊的将请求改为这样:
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; config.HTTPAdditionalHeaders = @{ @"User-Agent":@"XXX/3.5.0 (iPhone; iOS 10.0; Scale/2.00)", @"Accept-Language":@"zh-Hans-US;q=1, en;q=0.9" }; NSURLSession *session = [NSURLSession sessionWithConfiguration:config];NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:@"XXXX"] completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { }];[task resume];
显然,这与请求头毫无关系,那么就看看AFN是如何封装的吧
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request uploadProgress:(nullable void (^)(NSProgress *uploadProgress)) uploadProgressBlock downloadProgress:(nullable void (^)(NSProgress *downloadProgress)) downloadProgressBlock completionHandler:(nullable void (^)(NSURLResponse *response, id _Nullable responseObject, NSError * _Nullable error))completionHandler { __block NSURLSessionDataTask *dataTask = nil; url_session_manager_create_task_safely(^{ dataTask = [self.session dataTaskWithRequest:request]; }); [self addDelegateForDataTask:dataTask uploadProgress:uploadProgressBlock downloadProgress:downloadProgressBlock completionHandler:completionHandler]; return dataTask;}
上面是AFN最内层方法,里面有我们想得到的dataTask = [self.session dataTaskWithRequest:request]; 瞬间恍然大悟,于是无聊的将网络请求更改为这样:
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; config.HTTPAdditionalHeaders = @{ @"User-Agent":@"XXXX/3.5.0 (iPhone; iOS 10.0; Scale/2.00)", @"Accept-Language":@"zh-Hans-US;q=1, en;q=0.9" }; NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:nil]; NSURLSessionDataTask *task = [session dataTaskWithURL:[NSURL URLWithString:@"XXXX"]]; [task resume];
遵守NSURLSessionDataDelegate,定义一个NSMutableData变量存储下载的NSData,实现下面的代理方法
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler{ self.allData = [NSMutableData data]; completionHandler(NSURLSessionResponseAllow);}- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{ [self.allData appendData:data];}- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{ NSLog(@"result: %@", self.allData);}
1 0
- iOS开发 ☞ OS_dispatch_data
- iOS开发 ☞ YY_Model
- iOS开发 ☞ MJRefresh
- iOS开发 ☞ UIWebView
- iOS开发 ☞ NSNotification
- iOS开发 ☞ AFNetWorking
- iOS开发 ☞ IPv6
- iOS开发 ☞ UITabbar
- iOS开发 ☞ NSTimer
- iOS开发 ☞ 单元测试
- iOS开发 ☞ Git使用
- iOS开发 ☞ UILable详解
- iOS开发 ☞ NSString详解
- iOS开发 ☞ NSMutableAttributedString详解
- iOS开发 ☞ UINavigationController详解
- iOS开发 ☞ Quartz2D详解
- iOS开发 ☞ Commen Sense
- iOS开发 ☞ Simulator(模拟器)
- ios 静态库(.a)文件相关流程及-ObjC, -all_load, -force_load
- iOS开发之懒加载2
- OPENCV边缘提取
- 用筛选法求n以内的素数
- Linux下不同运维人员共用root 账户权限审计
- iOS开发 ☞ OS_dispatch_data
- 学习笔记之简单的自动部署用户的脚本
- Codeforces735C Tennis Championship
- 使用LocalBroadcastManager
- RelativeLayout属性记录
- Java FutureTask 源码解析
- [Google Guava] 1.1-使用和避免null
- 【Unity】2D Sprite九宫格(NineSliced)
- 基于slideout.js实现的移动端侧边栏滑动特效