"NSInternalInconsistencyException", причина: "Выполняется только в основном потоке!" ошибка
Итак, я знаю причину этой ошибки, но я не совсем уверен, как обойти ее.
У меня есть TextField
, который я не хочу редактировать, но с поддержкой прокрутки внутри представления.
Вот как я настроил этот вид:
- (void)tableView:(UITableView *) tableView
didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSDictionary *component = self.resultsTuples[indexPath.row];
NSString* serverUrl = @"http://staging.toovia.com";
NSString* pageLink = component[@"$element"][@"ContactCard"][@"PageLink"];
NSString* recUrl =[NSString stringWithFormat:@"%@%@&format=json&fields=summary&fields=session_info", serverUrl,pageLink];
[AJAXUtils getAsyncJsonWithUrl:(NSURL *)[NSURL URLWithString:recUrl] callback:^(NSDictionary *returnjson){
if (returnjson != nil){
NSLog(@"RETURN JSON : %@", returnjson);
NSString *userPageLink = returnjson[@"Node"][@"SessionInfo"][@"PostingAs"][@"Key"];
self.detailController.userPageLink = userPageLink;
self.detailController.nodePage = returnjson[@"Node"][@"Key"];
NSString *selectedCard = component[@"$element"][@"Title"];
// [self.detailController setDescription:component[@"element"][@"ContactCard"][@"Description"]];
[self.detailController setPageTitle:selectedCard];
NSString* photoUrl = component[@"$element"][@"ContactCard"][@"Cover"][@"Medium"][@"Link"];
[self.detailController setRestaurantImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:photoUrl]]]];
self.detailController.title = selectedCard;
NSString* rating = component[@"$element"][@"Summary"][@"AverageRating"];
self.detailController.rating =(NSInteger)rating;
[self.navigationController pushViewController:self.detailController animated:YES];
}
}];
Это код viewWillAppear
для представления:
-(void)viewWillAppear:(BOOL)animated{
[super viewWillAppear: animated];
self.rateView.notSelectedStar =[UIImage imageNamed:@"star-off.png"];
self.rateView.fullSelectedStar = [UIImage imageNamed:@"star-on.png"];
self.rateView.rating = self.rating;
self.rateView.editable = YES;
self.rateView.maxRating = 5;
self.rateView.delegate = self;
_pageTitleLabel.text = _pageTitle;
_pageScoreLabel.text = _pageScore;
_trendingImageView.image = [UIImage imageNamed:@"trending.png"];
_restaurantImageView.image = _restaurantImage;
}
Полная ошибка:
2013-12-16 01:22:50.362 ReviewApp[7332:441f] *** Assertion failure in void _UIPerformResizeOfTextViewForTextContainer(NSLayoutManager *, UIView<NSTextContainerView> *, NSTextContainer *, NSUInteger)(), /SourceCache/UIFoundation_Sim/UIFoundation-258.1/UIFoundation/TextSystem/NSLayoutManager_Private.m:1510
2013-12-16 01:22:50.365 ReviewApp[7332:441f] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Only run on the main thread!'
Итак, я предполагаю, что это происходит, потому что изменение размера текстового поля (когда контент установлен) должен произойти в основном потоке. Как заставить это произойти/подавить эту ошибку? Я не контролирую изменение размера текстового поля, я?
Спасибо
Ответы
Ответ 1
Я предполагаю, что обратный вызов из AJAXUtils
происходит в фоновом потоке. Я не знаю, является ли это вашим кодом или нет, но вы должны выполнять все операции пользовательского интерфейса (например, устанавливать текст в ярлыке, задавать изображение в представлении изображения, нажимать контроллер представления) в основном потоке.
dispatch_sync(dispatch_get_main_queue(), ^{
/* Do UI work here */
});
Ответ 2
версия Swift 3.0
DispatchQueue.main.async(execute: {
/* Do UI work here */
})
Ответ 3
Вы всегда должны выполнять код пользовательского интерфейса в основном потоке. Вы не являетесь, следовательно, ошибкой. Попробуйте следующее:
[AJAXUtils getAsyncJsonWithUrl:(NSURL *)[NSURL URLWithString:recUrl] callback:^(NSDictionary *returnjson){
if (returnjson != nil){
NSLog(@"RETURN JSON : %@", returnjson);
NSString *userPageLink = returnjson[@"Node"][@"SessionInfo"][@"PostingAs"][@"Key"];
self.detailController.userPageLink = userPageLink;
self.detailController.nodePage = returnjson[@"Node"][@"Key"];
NSString *selectedCard = component[@"$element"][@"Title"];
// [self.detailController setDescription:component[@"element"][@"ContactCard"][@"Description"]];
[self.detailController setPageTitle:selectedCard];
NSString* photoUrl = component[@"$element"][@"ContactCard"][@"Cover"][@"Medium"][@"Link"];
[self.detailController setRestaurantImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:photoUrl]]]];
self.detailController.title = selectedCard;
NSString* rating = component[@"$element"][@"Summary"][@"AverageRating"];
self.detailController.rating =(NSInteger)rating;
dispatch_async(dispatch_get_main_queue(), ^{
[self.navigationController pushViewController:self.detailController animated:YES];
});
}
}];
Это обеспечивает отображение контроллера вида на основном потоке. На самом деле вам может понадобиться немного больше кода внутри вызова dispatch_async
.
Ответ 4
Быстрая версия
dispatch_async(dispatch_get_main_queue()){
/* Do UI work here */
}
Ответ 5
Кроме того, это не очень хороший способ делать вещи в didSelectRow. У вас должен быть сетевой уровень, отделяйте сетевой код от контроллеров представления, иначе вы получите огромный контроллер просмотра, код не будет проверяться.