GVKun编程网logo

将NSURLConnection弃用从Swift 1.2修复为2.0(nsurlsessionconfiguration)

9

在这篇文章中,我们将为您详细介绍将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)

将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 – If-None-Match和NSURLConnection

我的服务器正在为缓存支持设置etag标头元素.

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值并在请求标头中设置)?

解决方法

我遇到了同样的问题.对我来说,我使用默认缓存策略(NSURLRequestUseProtocolCachePolicy),它自动设置服务器将检查的“if-none-match”头字段.但是,将缓存策略设置为“NSURLRequestReloadIgnoringLocalCacheData”显然会删除该标头字段.

您是否尝试过其他缓存策略值以查看是否为您添加了该标头?

这里可以看到关于这些不同缓存策略值的精彩博客:http://nshipster.com/nsurlcache/

编辑:我发现了另一个堆栈溢出问题,证实了我上面所说的:NSURLCache and ETags

ios – Swift / https:NSURLSession / NSURLConnection HTTP加载失败

ios – Swift / https:NSURLSession / NSURLConnection HTTP加载失败

不幸的是今天早上我的XCode更新到版本7,我用http开发的iOS应用程序现在想要https.因此,在许多教程之后,我配置了我的MAMP服务器,以便使用https / ssl创建虚拟证书.现在在我的iOS应用中,URL如下所示:
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

我想知道如何解决这个问题.我在这里已经阅读了一些有用的答案,但有许多事情我仍然不明白,如果有人愿意帮助/解释我,我将非常感激.

解决方法

将其添加到您应用的Info.plist中
<key>NSAppTransportSecurity</key>  
    <dict>  
    <key>NSAllowsArbitraryLoads</key>  
    <true/>  
    </dict>

ios – 使用NSURLSession进行异步上传不起作用,但NSURLConnection同步

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吗?

在此先感谢您的帮助!

解决方法

你是对的,如果你只想让你的请求异步,你应该退出sendSynchronousRequest.虽然我们曾经推荐过sendAsynchronousRequest,有效的iOS 9,NSURLConnection正式弃用,并且应该支持NSURLSession.

一旦开始使用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

ios – 停止当前NSURLConnection

目前,每当mySearchBar.text改变时,我正在进行NSURLConnection.我遇到一个问题,如果用户输入文本太快,则responseData将被损坏.

所以,我想知道有没有办法检查是否仍然加载相同的NSURLConnection?如果是,如何删除当前连接并启动新连接?

解决方法

添加该NSURLConnection的属性,然后再开始新的连接,请执行以下操作:
[self.conn cancel];
self.conn = nil;

今天的关于将NSURLConnection弃用从Swift 1.2修复为2.0nsurlsessionconfiguration的分享已经结束,谢谢您的关注,如果想了解更多关于ios – If-None-Match和NSURLConnection、ios – Swift / https:NSURLSession / NSURLConnection HTTP加载失败、ios – 使用NSURLSession进行异步上传不起作用,但NSURLConnection同步、ios – 停止当前NSURLConnection的相关知识,请在本站进行查询。

本文标签: