Цель C: Как предотвратить NSURLConnection от изменения переменной экземпляра делегата класса? - PullRequest
1 голос
/ 13 марта 2011

Я довольно долго искал и не могу понять, как решить довольно досадную ошибку, которую я получаю.

У меня есть два класса: один управляет запросами и NSURLConnections (только один ввремя) и отправляет обратный вызов делегату класса, когда все сказано и сделано (NSURLConnection завершает загрузку всех данных).Проблема возникает, когда метод обратного вызова вызывается для делегата, я проследил указатель, и кажется, что он изменил свой адрес.

Как NSURLConnection изменил адрес моей переменной экземпляра класса (идентификатор делегата)?Я никогда не использовал его с NSURLConnection (по крайней мере, я думаю, что не использовал).

Код:

#import <Foundation/Foundation.h>
#import "JSON.h"

@interface Downloader : NSObject 
{
    NSMutableData *receivedData;
    id delegate;
}

@property(nonatomic, assign) id delegate;

- (void)download:(NSString*)url;

- (void)finished:(id)object;

@end

#import "Downloader.h"


@implementation Downloader

@synthesize delegate;

- (void)download:(NSString*)url
{   
    //NSLog(@"The delegate is: [%@]", delegate);
    receivedData = [[[NSMutableData alloc] init] retain];
    NSURLRequest *urlRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:url]];
    NSURLConnection *connection = [[[NSURLConnection alloc] initWithRequest:urlRequest delegate:self] retain];
}

- (void)finished:(id)object
{

}

- (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
{
    // release the connection, and the data object
    [connection release];
    // receivedData is declared as a method instance elsewhere
    [receivedData release];

    // inform the user
    NSLog(@"Connection failed! Error - %@ %@",
          [error localizedDescription],
          [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    NSLog(@"Downloader: Finished download");
    //NSLog(@"The delegate is: [%@]", delegate);

    SBJsonParser *parser = [[[SBJsonParser alloc] init] retain];
    NSString *jsonString = [[[NSString alloc] initWithData:receivedData  encoding:NSUTF8StringEncoding] retain];

    //NSLog(@"Downloader: Received [%@]", jsonString);

    // Parse the JSON into an Object
    id jsonObject = [parser objectWithString:jsonString];

    // Call the delegate and give it the JSON Object.
    [delegate finished:jsonObject];

    [connection release];
    //[receivedData release];
}

@end

Потратил немало времени, пытаясь выяснить это.... слава всем, если они могут найти источник этой загадочной проблемы!

Она взрывается прямо здесь:

// Call the delegate and give it the JSON Object.
[delegate finished:jsonObject];

И выдает эту ошибку:

Программаполученный сигнал: «EXC_BAD_ACCESS».

Раньше он генерировал «нераспознанный селектор, отправленный экземпляру», но с тех пор прекратил это делать ...

Спасибо, ребята!

Ответы [ 3 ]

0 голосов
/ 13 марта 2011

Очень похоже на то, что объект, который вы назначили в качестве делегата, был освобожден;это чаще всего дает EXC_BAD_ACCESS, но может выдавать «нераспознанный селектор, отправленный экземпляру», если новый объект оказывается в том же месте, что и старый.

0 голосов
/ 13 марта 2011

@ hoha и @Anomie верны ... Я просто укажу, что в Какао объекты никогда не сохраняют своего делегата, так как делегаты могут содержать ссылку на объект, который они делегируют, что может создать цикл сохранения. если вы работаете без GC.

Таким образом, вы все делаете правильно, когда устанавливаете свойство делегата для присваивания ... но какой-то другой объект (например, контроллер представления) должен отвечать за сохранение вашего делегата и затем освобождение его, когда вы закончите с скачать.

0 голосов
/ 13 марта 2011

Я предполагаю, что загрузчик освобожден преждевременно, и это

, кажется, что он изменил свой адрес

, делает мое подозрение еще сильнее.Попробуйте переопределить dealloc в Downloader и вставить туда логирование.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...