#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.
В этом примере кода здесь:
когда они снова запускают соединение (в вашем методе обновления), они:
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. Вы были правы, и мне нравится идея поместить код в свой собственный класс, тогда делегат приложения и контроллер представления могут вызывать класс.