Я пытался работать с TWrequest и получить блок твитов, но у меня возникают проблемы с синхронизацией данных и обновлением таблицы.
У меня есть следующий относительно простой блок в TableViewController для получения информации об учетной записи пользователя:
- (void)viewDidLoad
{
NSArray *twitterAccounts = [[NSArray alloc] init];
if ([TWRequest class]) {
store = [[ACAccountStore alloc] init];
ACAccountType *twitterType = [store accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[store requestAccessToAccountsWithType:twitterType withCompletionHandler:^(BOOL granted, NSError *error){
if (granted == YES) {
NSLog(@"Access granted to Twitter Accounts");
} else {
NSLog(@"Access denied to Twitter Accounts");
}
}];
twitterAccounts = [store accountsWithAccountType:twitterType];
self.account = [[store accounts] objectAtIndex:0];
} else {
// The iOS5 Twitter Framework is not supported so need to provide alternative
}
self.homeTimeLineData = [NSMutableArray array];
self.profileImages = [NSMutableDictionary dictionary];
[self updateTimeLineData:HOME_TIMELINE_URL];
[super viewDidLoad];
}
получить последние 20 твитов из домашней хроники пользователей:
- (void)updateTimeLineData:(NSString *)urlString {
NSDictionary *parameters = [NSDictionary dictionaryWithObjectsAndKeys:@"20", @"count", nil];
TWRequest *myHomeTimeLine = [[TWRequest alloc] initWithURL:[NSURL URLWithString:urlString] parameters:parameters requestMethod:TWRequestMethodGET];
myHomeTimeLine.account = account;
[myHomeTimeLine performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
NSError *jsonError = nil;
NSArray *timeLineData = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&jsonError];
dispatch_async(dispatch_get_main_queue(), ^{
[self refresh:timeLineData];
});
}];
}
парсинг данных временной шкалы и перезагрузка таблицы:
- (void)refresh:(NSArray *)arrayOfTweets {
for (int i=0; i < [arrayOfTweets count]; i++) {
NSDictionary *rawTweetJSON = [arrayOfTweets objectAtIndex:i];
Tweet *tweet = [[Tweet alloc] init];
tweet.screenName = [[rawTweetJSON objectForKey:@"user"] objectForKey:@"screen_name"];
tweet.tweetText = [rawTweetJSON objectForKey:@"text"];
tweet.createdAt = [rawTweetJSON objectForKey:@"created_at"];
[self.homeTimeLineData insertObject:tweet atIndex:i];
}
[self.tableView reloadData];
}
Это работает нормально, но каждый раз, когда я пытаюсь изменить это, я сталкиваюсь с проблемами
- Если я попытаюсь проанализировать дату JSON в блоке executeRequestWithHandler и передать обратно проанализированные данные, я получу ошибку подтверждения.
- Если я перенесу запрос на доступ к учетным записям в AppDelegate (чтобы в конечном итоге информация об учетных записях могла быть разделена между различными контроллерами представления) и передал нужную учетную запись в TableViewController, я получу ошибку подтверждения.
В обоих случаях ошибка подтверждения выглядит одинаково: просмотр таблицы обновит достаточно твитов, чтобы заполнить экран в первый раз, затем вызовет tableView: numberOfRowsInSection: и после того, как данные для следующей ячейки будут нулевыми.
2011-11-23 00: 02: 57.470 TwitteriOS5Tutorial [9750: 10403] * Ошибка подтверждения в - [UITableView _createPreparedCellForGlobalRow: withIndexPath:], /SourceCache/UIKit_Sim/UIKit-1912.3/UIT : 6072
2011-11-23 00: 02: 57.471 TwitteriOS5Tutorial [9750: 10403] * Завершение работы приложения из-за невыполненной исключительной ситуации NSInternalInconsistencyException, причина: «Источник данных UITableView должен возвращать ячейку из tableView: cellForRowAtIndexPath: «
Я пытался рассмотреть другие подобные вопросы, но не мог понять, как синхронизировать различные блоки. Что показалось мне странным, так это влияние того, где находится запрос информации об учетной записи.
homeTimeLineData в данном случае является просто NSMutableArray. Является ли решение перейти к Core Data и использовать NSFetchResultsController?
Мои знания о блоках все еще немного ограничены, поэтому любые знания будут высоко оценены.
Спасибо,
Norman
Обновление:
Я считаю, что нашел проблему, она связана с раскадровками и TableViewCells.
В учебном пособии по раскадровке я сказал, что вы можете заменить
NSString *CellIdentifier = @"MyCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableView alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
с одной строки
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyCell"];
и раскадровка позаботится о создании новой копии ячейки автоматически, если ее не будет в очереди. Я проверил документацию Apple, и там тоже написано.
Я последовал этому совету и использовал только однострочное объявление, и оно работало до определенного момента, но затем, когда я выполнял рефакторинг и реорганизацию кода, я начал получать ошибки утверждения.
Я использую пользовательский UITableViewCell с IBOutlets для изменения положения различных элементов в ячейке, поэтому может быть ограничением то, что для удаления строк, которые «проверяют возвращаемое значение ячейки», вы должны придерживаться стандартных ячеек и делать все ваши настройка в раскадровке и Интерфейсном Разработчике.
Кто-нибудь сталкивался с подобной проблемой?