第二个异步 NSURL 不调用委托方法



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

我看过很多不同的答案,但都没有用。我没有产生任何新的线程,所有的[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");
}
...

ConnectionWrapper:

-(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");
}

DifferentConnectionWrapper:

(id) initWithParams: (id) 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)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具有类似的功能,但为了简洁起见,我在这里省略了其他逻辑。

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

几件事:我没有看到一个didFailWithError:在你的第一个包装器类,和(有点偏离主题)你泄漏内存与你的DifferentConnectionWrapper *w ?

无论如何,我要尝试的是:看看你是否可以调用DifferentConnectionWrapper直接从appDelegate而不是ConnectionWrapper。在任何情况下,我都会尝试解耦这两个调用。当第一个完成并调用appDelegate时,你不能从那里启动你的DifferentConnectionWrapper吗?

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

我认为问题是你在-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赋另一个值时。

OK。事实证明,这个bug是由我遗漏的东西引起的。在第二次请求之后,我就陷入了困境,这可能会把任何事情都搞砸。一旦我解决了这个问题,一切都正常了。

谢谢你的帮助

最新更新