【问题标题】:Second asynchronous NSURLConnection doesn't call delegate methods第二个异步 NSURLConnection 不调用委托方法
【发布时间】:2011-04-20 01:19:59
【问题描述】:

从我的 ApplicationDelegate 中,我正在通过网络进行 NSURLConnection 获取(它包含在一个类中,如下所示)。这似乎工作正常:我得到了 didReceiveData 中的所有数据,我得到了完成调用 connectionDidFinishLoading。在 connectionDidFinishLoading 结束时,我实例化了一个或多个稍微不同的包装类,但它们本质上是相同的。问题是第二个 NSURLConnection 的委托从未调用过它的方法。

我看过manydifferentanswers,但都无济于事。我没有产生任何新线程,并且我在整个代码中乱扔的所有 [NSThread isMainThread] 检查都返回 true。

我被难住了。谁能帮我吗?以下是相关代码:

应用代理:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    ConnectionWrapper* w = [[ConnectionWrapper alloc] initWithParams:self
    url:[NSURL URLWithString:<url>]];
[w beginFetch];

    return YES;
}

...

-(void)fetchCompleted:(NSURL*)url directory:(NSString*)directory
{
NSLog(@"fetch completed");
}

-(void)fetchFailed:(NSURL*)url
{
NSLog(@"fetch failed");
}

...

连接包装器:

-(id)initWithParams:(id<ConnectionWrapperDelegate>)d url:(NSURL*)url
{
    delegate = d;

    connURL = url;

    return [self init];
}

-(void)beginFetch
{
    NSURLRequest* request = [[NSURLRequest alloc] initWithURL:connURL];
    NSURLConnection* conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];

    [conn release];
    [request release];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    NSLog(@"append");
    [responseData appendData:data];
}

- (void) connectionDidFinishLoading: (NSURLConnection*) connection
{
    ... parsing ....

    DifferentConnectionWrapper* w = [[DifferentConnectionWrapper alloc] initWithParams:self
        url:[NSURL URLWithString:<different url>]];
    [w beginFetch];
}

-(void)fetchCompleted:(NSURL*)URL
{
    NSLog(@"completed: %@", URL);
}

-(void)fetchFailed:(NSURL*)URL
{
    NSLog(@"failed");
}

不同的连接包装器:

-(id)initWithParams:(id)d url:(NSURL*)url { 委托 = d;

    connURL = url;

    return [self init];
}

-(void)beginFetch
{
    NSURLRequest* request = [[NSURLRequest alloc] initWithURL:connURL];
    NSURLConnection* conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];

    [conn release];
    [request release];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    NSLog(@"append");
    [responseData appendData:data];
}

- (void) connectionDidFinishLoading: (NSURLConnection*) connection
{
    ... parsing ....

    DifferentConnectionWrapper* w = [[DifferentConnectionWrapper alloc] initWithParams:self
        url:[NSURL URLWithString:<different url>]];
    [w beginFetch];
}

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

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    NSLog(@"got data");
    [responseData appendData:data];
}

- (void) connectionDidFinishLoading: (NSURLConnection*) connection
{
    NSLog(@"image saver completed: %@", connURL);
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"error");
}

ConnectionWrapper 和DifferentConnectionWrapper 具有相似的功能,但为了简洁,我在此省略了其他逻辑。

感谢您的帮助。我很感激。

【问题讨论】:

    标签: iphone objective-c delegates nsurlconnection nsurlrequest


    【解决方案1】:

    有几件事:我没有看到 didFailWithError: 在您的第一个包装类中,并且(有点离题)您是否使用 DifferentConnectionWrapper *w 泄漏了内存?

    无论如何,我会尝试的是:看看您是否可以直接从 appDelegate 而不是 ConnectionWrapper 调用 DifferentConnectionWrapper。 无论如何,我都会尝试将这两个电话分开。当第一个完成并调用 appDelegate 时,您不能从那里启动您的 DifferentConnectionWrapper 吗?

    我知道这并不能解释你的问题,但你可能会得到它的工作(这两件事中哪一个更重要,是一个完全不同的争论。)

    【讨论】:

    • 看起来他确实泄露了他的连接包装。
    • DifferentConnectionWrapper 在 App Delegate 中独立工作,但是一旦我链接了两个连接请求,第二个连接请求就无处可去。我知道泄漏:这只是我为调试所做的事情(我想消除任何保留/释放问题)。
    【解决方案2】:

    我认为问题在于您正在释放-beginFetch 中的 URL 连接:

    -(void)beginFetch
    {
        NSURLRequest* request = [[NSURLRequest alloc] initWithURL:connURL];
        NSURLConnection* conn = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    
        [conn release];
        [request release];
    }
    

    URL 连接对象应该保持活动状态,并在连接完成加载后释放:

    - (void) connectionDidFinishLoading: (NSURLConnection*) connection
    {
        ... parsing ....
    
        // *** Release the connection and whatever data you’ve kept related to
        // this particular connection
        [connection release];
        [responseData release];
        // *** or [responseData setLenght:0]; depending on how you’re
        // managing responseData
    
        DifferentConnectionWrapper* w = [[DifferentConnectionWrapper alloc] initWithParams:self
            url:[NSURL URLWithString:<different url>]];
        [w beginFetch];
    }
    

    或出现错误时:

    - (void)connection:(NSURLConnection *)connection
      didFailWithError:(NSError *)error
    {
        // *** Release the connection and whatever data you’ve kept related to
        // this particular connection
        [connection release];
        [responseData release];
        // *** or [responseData setLenght:0]; depending on how you’re
        // managing responseData
    
        // inform the user
        NSLog(@"Connection failed! Error - %@ %@",
              [error localizedDescription],
              [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
    }
    

    编辑:您的初始化程序有点奇怪:

    -(id)initWithParams:(id<ConnectionWrapperDelegate>)d url:(NSURL*)url
    {
        delegate = d;    
        connURL = url;
        return [self init];
    }
    

    除非我们看到-init 的代码,否则无法知道会发生什么,无论如何,这应该是指定的初始化程序,因此无论如何都不应该将-init 发送到self。此外,您应该保留传递给初始化程序的 url 对象。

    以下更有意义:

    -(id)initWithParams:(id<ConnectionWrapperDelegate>)d url:(NSURL*)url
    {
        self = [super init];
        if (self) {
            delegate = d;    
            connURL = [url retain];
        }
        return self;
    }
    

    不要忘记释放-dealloc 中的url 对象,或者当您为connURL 分配另一个值时。

    【讨论】:

    • 不保留对 NSURLConnection 的引用没有错。它将被运行循环保留。
    • @fluchtpunkt 这有记录吗?
    • 现在找不到。我以这种方式使用 NSURLConnections 已经很长时间了,所以我希望我没有错。但我找不到它的记录。
    • @fluchtpunkt 嗯,我已经检查了运行循环输入源的文档,但我找不到任何提及运行循环保留其源的信息,除非它们是计时器。如果您碰巧找到任何有关此的信息,请告诉我。
    【解决方案3】:

    好的。事实证明,这个错误是由我错过的东西引起的。在第二个请求之后,我正陷入困境,这可能会搞砸任何事情。一旦我解决了这个问题,一切都很好。

    感谢您的帮助。

    【讨论】:

      猜你喜欢
      • 2011-08-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多