NSURLConnection работает только один раз

#iphone #objective-c #ios #nsurlconnection

#iPhone #objective-c #iOS #nsurlconnection

Вопрос:

Я уже некоторое время работаю над своим первым приложением, но, похоже, мне здесь чего-то не хватает. Приведенный ниже код изначально был только в моем делегате приложения; Я просто добавил кнопку обновления в первый контроллер представления, чтобы обновить данные, используемые приложением, поэтому моей первой идеей было снова вызвать код делегата приложения внутри контроллера представления, но методы NSURLConnection делегирования не сработали. Теперь я добавил код в контроллер представления (а также сохранил его в делегате приложения), и методы делегирования срабатывают при нажатии кнопки обновления, но responseData имеют значение null, refreshString являются пустыми и JSONValue выдают ошибку «Неожиданный конец ввода» (поскольку ничего не вводится) в журнале (theприложение все еще запускается и очищает UITableView, это правильное поведение, поскольку массив теперь пуст). Набор символов данных JSON равен UTF-8

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

 - (void) refreshData{
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://beersandears.net/beer-list-json.php?native=yes"]];
    [[NSURLConnection alloc] initWithRequest:request delegate:self];
    NSLog(@"loadData complete");
}

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

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

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    [connection release];
    //label.text = [NSString stringWithFormat:@"Connection failed %@", [error description]];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
    [connection release];
    connection = nil;
    NSString *refreshString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];

    [responseData release];

    NSDictionary *results = [refreshString JSONValue];

    BeerListAppDataObject* theDataObject = [self beerListAppDataObject]; 

    [theDataObject.beerList removeAllObjects];
    [theDataObject.mapList removeAllObjects];
    [theDataObject.blogList removeAllObjects];

    theDataObject.beerList = [results objectForKey:@"beer"];
    theDataObject.mapList = [results objectForKey:@"map"];
    theDataObject.blogList = [results objectForKey:@"blog"];

    NSLog(@"Data Loaded");

    [self.tableView reloadData];
}
  

Ответ №1:

Вы освобождаете переменную-член NSData responseData при окончательной загрузке:

 [responseData release];
  

Но я не вижу, чтобы что-то еще добавляло другой объект NSData.

В этом примере кода здесь:

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.html

когда они снова запускают соединение (в вашем методе обновления), они:

 NSURLConnection *theConnection=[[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (theConnection) {
    // Create the NSMutableData to hold the received data.
    // receivedData is an instance variable declared elsewhere.
    receivedData = [[NSMutableData data] retain];
} else {
    // Inform the user that the connection failed.
}
  

Ключевая строка заключается в том, что они получают объект NSMutabaleData и сохраняют его.

 receivedData = [[NSMutableData data] retain];
  

Комментарии:

1. У меня было ощущение, что мне не хватает одной маленькой, но важной детали! Спасибо!

Ответ №2:

Просто предположение: попробуйте проверить, что переменная responseData NSMutableData была правильно инициализирована в контроллере представления.

Даже если это решит непосредственную проблему, было бы неплохо абстрагировать этот код в свой собственный класс (возможно, класс «BeerAPIClient»?) поэтому он не должен существовать в двух местах. Таким образом, его легче поддерживать по мере его роста и изменений, потому что есть только одно место для обновления.

Комментарии:

1. Вы были правы, и мне нравится идея поместить код в свой собственный класс, тогда делегат приложения и контроллер представления могут вызывать класс.