【问题标题】:NSURLConnection with ARC not receiving Data带有ARC的NSURLConnection不接收数据
【发布时间】:2012-04-10 09:33:05
【问题描述】:

我是 iOS 开发的新手,我正在尝试从 URL 获取内容。我正在使用 Apple 教程来使用 NSURLConnection,一切正常,但我没有获取数据。我环顾四周,找不到我的问题的答案。我在我的项目中也使用了 ARC,也许这会导致问题?

这是我正在使用的代码,从我的头文件开始:

@interface ViewController : UIViewController
@property (nonatomic, retain) NSMutableData *receivedData;
@end

实现文件:

@implementation ViewController

@synthesize receivedData;

- (void)didReceiveMemoryWarning
{
    [super didReceiveMemoryWarning];
    // Release any cached data, images, etc that aren't in use.
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"1. viewDidLoad");
    // Create the request
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.apple.com/"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];
    // Create the connection with the request and start loading the data
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    if (connection) {
        NSLog(@"2. connection succeeded");
        receivedData = [NSMutableData data];
    } else {
        NSLog(@"2. connection failed");
    }
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse     *)response
{
    NSLog(@"3. didReceiveResponse");
    [receivedData setLength:0];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [receivedData appendData:data];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"4. Connection failed! Error - %@ %@", [error localizedDescription], [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSLog(@"4. Succeeded! Received %d bytes of data", [receivedData length]);
}

所有的 NSLog 都在工作,但它一直说 receivedData 有 0 个字节。我找不到我的问题的答案,所以我希望我能找到这个问题的答案。

【问题讨论】:

  • ARC 不应该用于自动引用计数,请阅读标签 wiki。
  • Lars,对于 ARC 代码,您的 @property 应该使用 strong 而不是 retain。另外,为什么您的-connection :didReceiveData: 方法中没有日志语句?安德鲁
  • 我认为 NSURLConnection *connection 被释放了,所以你必须将它声明为强属性。

标签: ios cocoa-touch automatic-ref-counting nsurlconnection nsurlrequest


【解决方案1】:

我已经使用 ARC 翻译了 URL Loading System Programming GuideUsing NSURLConnection 部分。

//
//  MyConnection.h
//

#import <Foundation/Foundation.h>

@interface MyConnection : NSObject

- (void)start;

@property NSMutableData *receivedData;

@end


//
//  MyConnection.m
//

#import "MyConnection.h"

@implementation MyConnection

- (void)start {

    // Create the request
    NSURLRequest *theRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.apple.com"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];

    // Create the connection with the request and start loading the data
    NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];

    if (theConnection) {
        // Create the NSMUtableData to fold the received data
        // ReceivedData is an instance variable declared elsewhere
        _receivedData = [NSMutableData data];

    }
}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    [_receivedData setLength:0];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [_receivedData appendData:data];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    // Inform the user
    NSLog(@"Connectionfailed! Error - %@ %@",
          [error localizedDescription],
          [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    // Do something with the data
    NSLog(@"Succeeded! Recevied %d bytes of data", [_receivedData length]);

}

@end

【讨论】:

    【解决方案2】:

    只是为了完成。我遇到了同样的问题,原因是 threading。如果拥有NSURLConnection 对象的线程与拥有delegate 的线程不同,则delegate 将不会收到通知。这意味着连接中的错误也将消失。

    因此,请确保在创建委托的同一线程上创建 NSURLConnection

    【讨论】:

      【解决方案3】:

      您需要启动连接。

      例如,您可以使用– initWithRequest:delegate:startImmediately:

      对现有代码的更小的更改是在 if 分支上的连接上使用 - start

      NSURLConnection *connection = [[NSURLConnection alloc] 
                                      initWithRequest:request 
                                             delegate:self 
                                     startImmediately:NO
                                     ];
      if (connection) {
          NSLog(@"2. connection succeeded");
          receivedData = [NSMutableData data];
          [connection start];
      } else {
          NSLog(@"2. connection failed");
      }
      

      您可以找到 NSURLConnection here 的参考手册

      【讨论】:

      • 不这样不正确,不需要调用start。正如您链接到的手册中所述:“这相当于调用 initWithRequest:delegate:startImmediately: 并为 startImmediately 传递 YES。”
      • 我同意,当且仅当您使用初始化程序的长版本并为 startImmediately 传递 YES 时,才需要调用 start。为了对现有代码进行小的更改,我提供了第二个选项。确实,我在示例中打错了字。编辑修复它。
      • 不,我的意思是当你像他一样使用[[NSURLConnection alloc] initWithRequest:request delegate:self];时,没有必要调用start。使用较短的初始化程序会自动调用较长的版本,并将 YES 设置为 startImmediately。我在我的代码中广泛使用 NSURLConnection,总是使用较短的初始化程序,并且从不调用 start。它以这种方式工作,并在您链接到的文档中得到确认。同样根据他的问题,正在调用他的委托方法,因此连接显然正在开始。
      猜你喜欢
      • 1970-01-01
      • 2014-10-12
      • 1970-01-01
      • 1970-01-01
      • 2011-12-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多