在这篇文章中,我们将为您详细介绍将NSURLConnection弃用从Swift1.2修复为2.0的内容,并且讨论关于nsurlsessionconfiguration的相关问题。此外,我们还会涉及一
在这篇文章中,我们将为您详细介绍将NSURLConnection弃用从Swift 1.2修复为2.0的内容,并且讨论关于nsurlsessionconfiguration的相关问题。此外,我们还会涉及一些关于ios – If-None-Match和NSURLConnection、ios – Swift / https:NSURLSession / NSURLConnection HTTP加载失败、ios – 使用NSURLSession进行异步上传不起作用,但NSURLConnection同步、ios – 停止当前NSURLConnection的知识,以帮助您更全面地了解这个主题。
本文目录一览:- 将NSURLConnection弃用从Swift 1.2修复为2.0(nsurlsessionconfiguration)
- ios – If-None-Match和NSURLConnection
- ios – Swift / https:NSURLSession / NSURLConnection HTTP加载失败
- ios – 使用NSURLSession进行异步上传不起作用,但NSURLConnection同步
- ios – 停止当前NSURLConnection
将NSURLConnection弃用从Swift 1.2修复为2.0(nsurlsessionconfiguration)
我有一个用Swift 1.2编写的函数,用于检查地址或IP的可达性。这里是 :
func isHostConnected(hostAddress : String) -> Bool{ var response : NSURLResponse? let request = NSMutableURLRequest(URL: NSURL(string: hostAddress)!) request.timeoutInterval = 3 let data = NSURLConnection.sendSynchronousRequest(request, returningResponse: &response, error: nil) return ((response as? NSHTTPURLResponse)!.statusCode == 200)}
现在,NSURLConnection
根据Xcode的建议,我已经弃用了,我尝试使用编写它NSURLSession.dataTaskWithRequest
,这里是:
func isHostConnected(hostAddress : String) -> Bool{ let request = NSMutableURLRequest(URL: NSURL(string: hostAddress.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!)!) request.timeoutInterval = 3 let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration(), delegate: nil, delegateQueue: NSOperationQueue.mainQueue()) var responseCode = -1 session.dataTaskWithRequest(request, completionHandler: {(data : NSData?, response : NSURLResponse?, error : NSError?) -> Void in responseCode = (response as? NSHTTPURLResponse)!.statusCode })!.resume() return (responseCode == 200)}
上面的代码始终返回 false (其明显),因为它是completionHandler
在单独的Thread上执行的。
我担心的是,是否可以completionHandler()
像sendSynchronousRequest
通过阻止它那样在MainThread上运行它?
我有理由不在这里使用“苹果的可及性”。
任何建议都会有所帮助。:)
答案1
小编典典检查服务器上是否存在资源需要发送HTTP请求并接收响应。TCP通信可能会花费一些时间,例如,如果服务器繁忙,客户端和服务器之间的某些路由器无法正常工作,网络断开等。
这就是为什么总是首选异步请求的原因。即使您认为请求只需要几毫秒,由于某些网络问题,有时有时也可能只有几秒钟。而且-众所周知-
将主线程阻塞几秒钟是一个很大的禁忌。
话虽如此,您可以使用“计数信号量”或“调度组”来等待某些异步任务的完成。你应该 不是 在主线程中使用。阻塞主线程最多3秒钟是不可接受的!
func isHostConnected(hostAddress : String) -> Bool{ let request = NSMutableURLRequest(URL: NSURL(string: hostAddress.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!)!) request.timeoutInterval = 3 request.HTTPMethod = "HEAD" let session = NSURLSession(configuration: NSURLSessionConfiguration.defaultSessionConfiguration()) var responseCode = -1 let group = dispatch_group_create() dispatch_group_enter(group) session.dataTaskWithRequest(request, completionHandler: {(_, response, _) in if let httpResponse = response as? NSHTTPURLResponse { responseCode = httpResponse.statusCode } dispatch_group_leave(group) })!.resume() dispatch_group_wait(group, DISPATCH_TIME_FOREVER) return (responseCode == 200)}
备注:
- 将HTTP方法设置为“ HEAD”是一个小的优化,因为服务器仅发送响应头,而没有实际数据。
- 如果主机名不合法,
response
将是nil
,并且responseCode = (response as? NSHTTPURLResponse)!.statusCode
将崩溃。
ios – If-None-Match和NSURLConnection
iOS(6.1.4)应用程序使用本机NSURLConnection类将XML请求发送到服务器
服务器第一次发送响应时,标题中设置了etag
如果iOS应用程序向服务器发送完全相同的请求,我可以在服务器日志中看到NSURLConnection未填充if-none-match标头
…然后服务器响应200而不是304
用于请求的缓存策略是:
[request setCachePolicy:NSURLRequestReturnCacheDataElseLoad];
NSURLCache初始化为
[[NSURLCache sharedURLCache] setMemoryCapacity:1024*1024*10];
我的问题:
– NSURLConnection没有设置“if-none-match”头字段是否正常?
– 我是否需要自己设置此标题字段? (从缓存中获取响应,读取etag值并在请求标头中设置)?
解决方法
您是否尝试过其他缓存策略值以查看是否为您添加了该标头?
这里可以看到关于这些不同缓存策略值的精彩博客:http://nshipster.com/nsurlcache/
编辑:我发现了另一个堆栈溢出问题,证实了我上面所说的:NSURLCache and ETags
ios – Swift / https:NSURLSession / NSURLConnection HTTP加载失败
static var webServerLoginURL = "https://localhost:443/excogitoweb/mobile/loginM.PHP" static var webServerGetUserTasks = "https://localhost:443/excogitoweb/mobile/handleTasks.PHP" static var webServerGetUsers = "https://localhost:443/excogitoweb/mobile/handleUsers.PHP" static var webServerGetProjects = "https://localhost:443/excogitoweb/mobile/handleProjects.PHP"
如果我尝试在浏览器中访问它们,它们工作正常.
我习惯使用NSURLSession.sharedSession().dataTaskWithRequest()来访问数据库和PHP文件,现在它会引发标题中的错误.例如,这是引发错误的行:
if let responseJSON: [[String: String]] = (try? NSJSONSerialization.JSONObjectWithData(data!,options: NSJSONReadingOptions())) as? [[String: String]] { ... }
这是完整的错误消息:
2015-09-21 16:41:48.354 ExcogitoWeb[75200:476213] CFNetwork SSLHandshake Failed (-9824) 2015-09-21 16:41:48.355 ExcogitoWeb[75200:476213] NSURLSession/NSURLConnection HTTP load Failed (kcfStreamErrorDomainSSL,-9824) Fatal error: unexpectedly found nil while unwrapping an Optional value
我想知道如何解决这个问题.我在这里已经阅读了一些有用的答案,但有许多事情我仍然不明白,如果有人愿意帮助/解释我,我将非常感激.
解决方法
<key>NSAppTransportSecurity</key> <dict> <key>NSAllowsArbitraryLoads</key> <true/> </dict>
ios – 使用NSURLSession进行异步上传不起作用,但NSURLConnection同步
我需要从iPhone异步上传文件到 Python服务器端进程.我想异步执行请求,以便在工作时显示繁忙的动画.
请求需要包含用户名,密码和文件作为“multipart / form-data”.
我可以使用NSURLConnection同步工作,代码如下所示::
-(void) uploadDatabase{ Database *databasePath = [[Database alloc] init]; Nsstring *targetPath = [databasePath getPathToDatabaseInDirectory]; NSData *dbData = [NSData dataWithContentsOfFile:targetPath]; Nsstring *url = @"http://mydomain.com/api/upload/"; //Nsstring *username = [[NSUserDefaults standardUserDefaults] stringForKey:USERNAME]; Nsstring *username = @"user"; Nsstring *password = @"pass"; NSMutableuRLRequest *request = [self createRequestForUrl:url withUsername:username andPassword:password andData:dbData]; NSURLResponse *response; NSError *error; NSData *result = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error]; Nsstring *stringResult = [[Nsstring alloc] initWithData:result encoding:NSUTF8StringEncoding]; NSLog(@"**server info %@",stringResult);}
//请求构建
-(NSMutableuRLRequest*) createRequestForUrl: (Nsstring*)urlString withUsername:(Nsstring*)username andPassword:(Nsstring*)password andData:(NSData*)dbData {NSURL *url = [NSURL URLWithString:urlString]; NSMutableuRLRequest *request = [NSMutableuRLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60.0]; [request setHTTPMethod:@"POST"]; Nsstring *boundary = @"BOUNDARY_STRING"; Nsstring *contentType = [Nsstring stringWithFormat:@"multipart/form-data; boundary=%@",boundary]; [request addValue:contentType forHTTPHeaderField:@"Content-Type"]; NSMutableData *body = [NSMutableData data]; if(dbData != NULL) { //only send these methods when transferring data as well as username and password [body appendData:[[Nsstring stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[Nsstring stringWithFormat:@"Content-disposition: form-data; name=\"file\"; filename=\"dbfile\"\r\n"] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[NSData dataWithData:dbData]]; } [body appendData:[[Nsstring stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[Nsstring stringWithFormat:@"Content-disposition: form-data; name=\"username\"\r\n\r\n%@",username] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[Nsstring stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[Nsstring stringWithFormat:@"Content-disposition: form-data; name=\"password\"\r\n\r\n%@",password] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[Nsstring stringWithFormat:@"\r\n--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [request setHTTPBody:body]; return request;}
但是,当我尝试使用NSURLSession异步执行此操作时,它似乎无法正常工作. NSURLSession的代码如下所示:
-(void)uploadDatabase{ Database *databasePath = [[Database alloc] init]; Nsstring *targetPath = [databasePath getPathToDatabaseInDirectory]; NSURL *phonedbURL = [NSURL URLWithString:targetPath]; Nsstring *url = @"http://mydomain.com/api/upload/"; Nsstring *username = @"user"; Nsstring *password = @"pass"; NSMutableuRLRequest *request = [self createRequestForUrl:url withUsername:username andPassword:password andData:NULL]; NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration]; self.uploadSession = [NSURLSession sessionWithConfiguration:defaultConfigObject delegate:self delegateQueue:Nil]; NSLog(@"the url = %@",url); NSURLSessionUploadTask *uploadTask = [self.uploadSession uploadTaskWithRequest:request fromFile:phonedbURL]; [uploadTask resume];}
我正在努力看到我做的不同,尽管看起来这应该有效.
是否正确使用NSURLSession进行异步请求?我是NSURLSession的新手,所以我必须为NSURLSession请求而不是NSURLConnection更改我的NSURLMutableRequest吗?
在此先感谢您的帮助!
解决方法
一旦开始使用NSURLSession,您可能会发现自己被它吸引了.例如,可以使用[NSURLSessionConfiguration backgroundSessionConfiguration:],然后在应用程序进入后台后上传进度. (你必须编写一些委托方法,所以为了简单起见,我已经在下面进行了一个简单的前台上传.)这只是你的业务需求的问题,抵消了新的NSURLSession功能与它所需的iOS 7限制.
顺便说一句,任何关于iOS / MacOS中的网络请求的对话可能都是不完整的,没有引用AFNetworking.它极大地简化了这些多部分请求的创建,并且绝对值得调查.他们也有NSURLSession支持(但我没有使用他们的会话包装器,所以不能说它).但AFNetworking毫无疑问值得您考虑.您可以享受基于委托的API的丰富功能(例如,进度更新,可取消请求,操作之间的依赖关系等),提供更好的控制,使用方便的方法(如sendSynchronousRequest),但不会拖过你的杂草委托方法本身.
无论如何,如果您真的对如何使用NSURLSession进行上传感兴趣,请参阅下文.
如果你想通过NSURLSession上传,那么思考就会略有转变,即将NSMutableuRLRequest中的请求(及其标题)的配置与请求主体的创建(您现在在实例化时指定)分开NSURLSessionUploadTask).您现在指定为上载任务的一部分的请求正文可以是NSData,文件或流(我在下面使用NSData,因为我们正在构建一个多部分请求):
NSMutableuRLRequest *request = [NSMutableuRLRequest requestWithURL:url]; [request setHTTPMethod:@"POST"]; Nsstring *boundary = [self boundaryString]; [request addValue:[Nsstring stringWithFormat:@"multipart/form-data; boundary=%@",boundary] forHTTPHeaderField:@"Content-Type"]; NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; NSURLSession *session = [NSURLSession sessionWithConfiguration:configuration]; NSData *fileData = [NSData dataWithContentsOfFile:path]; NSData *data = [self createBodyWithBoundary:boundary username:@"rob" password:@"password" data:fileData filename:[path lastPathComponent]]; NSURLSessionUploadTask *task = [session uploadTaskWithRequest:request fromData:data completionHandler:^(NSData *data,NSURLResponse *response,NSError *error) { NSAssert(!error,@"%s: uploadTaskWithRequest error: %@",__FUNCTION__,error); // parse and interpret the response `NSData` however is appropriate for your app }]; [task resume];
并且发送的NSData的创建与您现有的代码非常相似:
- (NSData *) createBodyWithBoundary:(Nsstring *)boundary username:(Nsstring*)username password:(Nsstring*)password data:(NSData*)data filename:(Nsstring *)filename { NSMutableData *body = [NSMutableData data]; if (data) { //only send these methods when transferring data as well as username and password [body appendData:[[Nsstring stringWithFormat:@"--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[Nsstring stringWithFormat:@"Content-disposition: form-data; name=\"file\"; filename=\"%@\"\r\n",filename] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[Nsstring stringWithFormat:@"Content-Type: %@\r\n\r\n",[self mimeTypeForPath:filename]] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:data]; [body appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]]; } [body appendData:[[Nsstring stringWithFormat:@"--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[Nsstring stringWithFormat:@"Content-disposition: form-data; name=\"username\"\r\n\r\n%@\r\n",username] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[Nsstring stringWithFormat:@"--%@\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[Nsstring stringWithFormat:@"Content-disposition: form-data; name=\"password\"\r\n\r\n%@\r\n",password] dataUsingEncoding:NSUTF8StringEncoding]]; [body appendData:[[Nsstring stringWithFormat:@"--%@--\r\n",boundary] dataUsingEncoding:NSUTF8StringEncoding]]; return body; }
你硬编码边界和mime类型,这很好,但上面碰巧使用以下方法:
- (Nsstring *)boundaryString { Nsstring *uuidStr = [[NSUUID UUID] UUIDString]; // If you need to support iOS versions prior to 6,you can use // Core Foundation UUID functions to generate boundary string // // adapted from http://developer.apple.com/library/ios/#samplecode/SimpleURLConnections // // Nsstring *uuidStr; // // CFUUIDRef uuid = CFUUIDCreate(NULL); // assert(uuid != NULL); // // Nsstring *uuidStr = CFBridgingrelease(CFUUIDCreateString(NULL,uuid)); // assert(uuidStr != NULL); // // CFRelease(uuid); return [Nsstring stringWithFormat:@"Boundary-%@",uuidStr]; } - (Nsstring *)mimeTypeForPath:(Nsstring *)path { // get a mime type for an extension using MobileCoreServices.framework CFStringRef extension = (__bridge CFStringRef)[path pathExtension]; CFStringRef UTI = UTTypeCreatePreferredIdentifierForTag(kUTTagClassFilenameExtension,extension,NULL); assert(UTI != NULL); Nsstring *mimetype = CFBridgingrelease(UTTypecopyPreferredTagWithClass(UTI,kUTTagClassMIMEType)); assert(mimetype != NULL); CFRelease(UTI); return mimetype; }
ios – 停止当前NSURLConnection
所以,我想知道有没有办法检查是否仍然加载相同的NSURLConnection?如果是,如何删除当前连接并启动新连接?
解决方法
[self.conn cancel]; self.conn = nil;
今天的关于将NSURLConnection弃用从Swift 1.2修复为2.0和nsurlsessionconfiguration的分享已经结束,谢谢您的关注,如果想了解更多关于ios – If-None-Match和NSURLConnection、ios – Swift / https:NSURLSession / NSURLConnection HTTP加载失败、ios – 使用NSURLSession进行异步上传不起作用,但NSURLConnection同步、ios – 停止当前NSURLConnection的相关知识,请在本站进行查询。
本文标签: