NSURLConnection 在 iOS 4.3 中完美运行,但在 iOS 5 / iOS 6 中却不行

Posted

技术标签:

【中文标题】NSURLConnection 在 iOS 4.3 中完美运行,但在 iOS 5 / iOS 6 中却不行【英文标题】:NSURLConnection works perfectly in iOS 4.3 but not in iOS 5 / iOS 6 【发布时间】:2013-06-02 16:02:08 【问题描述】:

我在使用 NSURLConnection 时遇到了一些非常奇怪的问题,所以希望您能帮助我。

我想做的是使用 NSURLConnection 从给定的 URL 下载一些数据。

我创建了自己的帮助类,它接收数据路径,下载它,并在下载完成时通过委托通知调用者。

这东西在我的装有 ios 4.3 的 iPhone 上运行良好。但是,在 iOS 5 或 iOS6 上进行测试时,从未调用过 connection:(NSURLConnection *)connection didReceiveData:(NSData *)data 方法,因此我没有得到想要的结果。

类 .h 文件包含:

#import <Foundation/Foundation.h>

@protocol NIAsyncDownloaderDelegate
@required
- (void) asyncDownloaderDataDownloadComplete:(NSData *)data withError:(bool) error;
@end

@interface NIAsyncImageDownloader : NSObject <NSURLConnectionDataDelegate>

    NSURLConnection *theConnection;
    NSMutableData* myData;

    NSURL *downloadURL;

    id delegate;


-(id) initWithDataDownloadString:(NSString *) stringAddress;

@property (nonatomic, retain) id delegate;

@end

.m 文件如下所示:

#import "NIAsyncDownloader.h"

@implementation NIAsyncImageDownloader

@synthesize delegate;

-(id) initWithDataDownloadString:(NSString *)stringAddress

    if (self = [super init])
    
        [self loadDataFromURL:[NSURL URLWithString:stringAddress]];
    
    return self;


- (void)loadDataFromURL:(NSURL*)url

    NSLog(@"Called: %@", NSStringFromSelector(_cmd));
    downloadURL = url;

    NSURLRequest* request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
    theConnection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];


-(void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response

    NSLog(@"Called: %@", NSStringFromSelector(_cmd));
    NSLog(@"The response is: %@, status code %i, url %@", response.description, ((NSHTTPURLResponse*)response).statusCode, ((NSHTTPURLResponse*)response).URL.description);


-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *)data

    NSLog(@"Called: %@", NSStringFromSelector(_cmd));

    if (myData == nil)
    
        myData = [[NSMutableData alloc] initWithCapacity:2048];
    

    [myData appendData:data];


//CALLED ON iOS 4.3
- (void)connectionDidFinishLoading:(NSURLConnection*)connection

    //so self data now has the complete image
    NSLog(@"Called: %@", NSStringFromSelector(_cmd));
    [self handleDownloadSuccess];


//CALLED ON iOS 5, iOS 6
-(void) connectionDidFinishDownloading:(NSURLConnection *)connection destinationURL:(NSURL *)destinationURL

    NSLog(@"Called: %@", NSStringFromSelector(_cmd));
    [self handleDownloadSuccess];


-(void) handleDownloadSuccess
    
    NSLog(@"Called: %@", NSStringFromSelector(_cmd));
    [theConnection release];
    theConnection = nil;

    [delegate asyncDownloaderDataDownloadComplete:myData withError:NO];

    [myData release];
    myData = nil;


- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error

    NSLog(@"Called: %@", NSStringFromSelector(_cmd));
    [delegate asyncDownloaderDataDownloadComplete:nil withError:YES];


@end

这里有一些截图可以告诉你我在说什么:

当我在 iOS5 或 iOS6 上运行应用程序时会发生这种情况,请求会自行初始化,收到响应,并立即调用 connectionDidFinishDownloading:(NSURLConnection *)connection destinationURL:(NSURL *)destinationURL

但是,当我在 iOS 4.3 上运行相同的应用程序时,一切正常,如下面的屏幕截图所示:

我还注意到 iOS 5 和 iOS 6 不像 iOS 4.3 那样调用相同的“完成”方法,但我认为这与我当前的问题无关。

最后,这里的文档说有问题的方法 (connection:didReceiveData) 从 iOS 4.3 开始实际上已被弃用: http://developer.apple.com/library/ios/#documentation/Foundation/Reference/NSURLConnectionDelegate_Protocol/DeprecationAppendix/AppendixADeprecatedAPI.html

但是,另一个参考指出它是 NSURLConnectionDataDelegate 协议的一部分,并且从 iOS 2 开始可用: http://developer.apple.com/library/ios/#documentation/Foundation/Reference/NSURLConnectionDataDelegate_protocol/Reference/Reference.html

XCode 似乎同意它已被弃用:

以防万一有人想知道我是如何使用下载器的,这真的很简单:

在.h中:

#import <UIKit/UIKit.h>
#import "NIAsyncDownloader.h"

@interface DTViewController : UIViewController <NIAsyncDownloaderDelegate>

    NIAsyncImageDownloader *downloader;


@end

在 .m 中:

#import "DTViewController.h"

@interface DTViewController ()

@end

@implementation DTViewController

- (void)viewDidLoad

    [super viewDidLoad];

    downloader = [[NIAsyncImageDownloader alloc] initWithDataDownloadString:@"http://www.freeimageslive.com/galleries/sports/sportsgames/pics/whitedice1.jpg"];
    downloader.delegate = self;


-(void) asyncDownloaderDataDownloadComplete:(NSData *)data withError:(bool)error

    if (data == nil || error)
    
        NSLog(@"DOWNLOAD FAILED");
    
    else
    
        NSLog(@"DOWNLOAD SUCCEEDED");
    


- (void)didReceiveMemoryWarning

    [super didReceiveMemoryWarning];
    // Dispose of any resources that can be recreated.


@end

所以,总结一下,我为什么会遇到问题以及该怎么办?

提前致谢:)

【问题讨论】:

投了赞成票不仅是因为这是一个好问题,还因为它写得非常好(问题描述、屏幕截图、到目前为止您尝试过的内容等) 如果将NSError 登录到- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error 会得到什么? 感谢 Bruno :) @Rich,我什么也没得到 - 正如您所看到的,该委托方法中也有一个 NSLog,但它从未被调用,因为显然没有发生错误。另外,您可能已经注意到,我也在记录“didReceiveResponse”,状态代码为“200”,这表明在这两种情况下一切正常 iOS 4.3 和 5.0 之间的主要变化似乎是引入了NSURLConnectionDataDelegate 协议,并且这些方法在那里正式化。协议中所有委托方法的可用性为“在 iOS 2.0 及更高版本中可用。在 iOS 5.0 之前作为非正式协议的一部分提供。” 不知道是不是实现connectionDidFinishDownloading:destinationURL:的问题。对于 iOS 5 或 6,无需这样做,您仍然可以使用 connectionDidFinishLoading:。你试过不用那种方法吗? 【参考方案1】:

这可能是也可能不是问题,但是当我设置做类似的事情时,我实现了 NSURLConnectionDelegate 和 NSURLConnectionDataDelegate 协议。我没有在 5 之前的 iOS 版本上进行过测试,但它对我来说在 5 和 6 中都有效:

@interface NIAsyncImageDownloader : NSObject <NSURLConnectionDelegate, NSURLConnectionDataDelegate> 


【讨论】:

我尝试遵守&lt;NSURLConnectionDataDelegate, NSURLConnectionDelegate, NSURLConnectionDownloadDelegate&gt; 中所有可能的协议组合(从所有 3 到无,包括您的建议),但遗憾的是它们都不起作用。 (我刚刚再次尝试以确保,但不幸的是它没有帮助) Hrmm.. 好吧,我不确定你的问题是什么。但我可以分享一个我正在使用的代码示例,它对我有用,也许它会帮助你。这是一个接口、实现和示例用法:gist.github.com/localhuman/5694156 非常感谢小伙伴,我会看看并尝试使用它 +1 表示NSURLConnectionDataDelegate。 IDK 为什么这个协议没有在官方docs 上列出NSURLConnection...

以上是关于NSURLConnection 在 iOS 4.3 中完美运行,但在 iOS 5 / iOS 6 中却不行的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS 中使用 NSURLConnection 以串行顺序下载文件

IOS:多个 NSUrlConnection 以及多个 UIProgressBar

iOS NSURLSession VS NSURLConnection

iOS学习笔记12-网络NSURLConnection

XCode 4.2.1 中的 NSURLConnection 文档在 iOS 上不存在吗?

iOS 中的 JSON 请求 - 使用 Grand Central Dispatch 或 NSURLConnection