(Два изменения следуют исходному телу этого вопроса, оба из которых очень сильно изменяют вопрос. Не зацикливайтесь на первой части этого - в то время как полезно для контекстных целей , Я почти исключил исходную проблему, о которой я просил.)Обновление освобожденного UIWebView из фоновой темы
Как вы можете видеть из названия, я запрограммировал себя в угол, и у меня есть несколько вещей, которые работают против меня ...
В подклассе UIViewController, который управляет большим и сложным видом. Одной из них является UIWebView, который содержит вывод веб-запроса, который мне нужно было создать и выполнить, и вручную собрать HTML. Так как для запуска требуется второй или два, я опустил его на задний план, вызвав self performSelectorInBackground:
. Затем из этого метода я звоню туда, я использую self performSelectorOnMainThread:
, чтобы вернуться на поверхность стека потоков, чтобы обновить UIWebView с тем, что я только что получил.
Как это (который я вырубил, чтобы показать только соответствующие вопросы):
-(void)locationManager:(CLLocationManager *)manager
didUpdateToLocation:(CLLocation *)newLocation
fromLocation:(CLLocation *)oldLocation
{
//then get mapquest directions
NSLog(@"Got called to handle new location!");
[manager stopUpdatingLocation];
[self performSelectorInBackground:@selector(getDirectionsFromHere:) withObject:newLocation];
}
- (void)getDirectionsFromHere:(CLLocation *)newLocation
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
CLLocationCoordinate2D here = newLocation.coordinate;
// assemble a call to the MapQuest directions API in NSString *dirURL
// ...cut for brevity
NSLog(@"Query is %@", dirURL);
NSString *response = [NSString stringWithContentsOfURL:[NSURL URLWithString:dirURL] encoding:NSUTF8StringEncoding error:NULL];
NSMutableString *directionsOutput = [[NSMutableString alloc] init];
// assemble response into an HTML table in NSString *directionsOutput
// ...cut for brevity
[self performSelectorOnMainThread:@selector(updateDirectionsWithHtml:) withObject:directionsOutput waitUntilDone:NO];
[directionsOutput release];
[pool drain];
[pool release];
}
- (void)updateDirectionsWithHtml:(NSString *)directionsOutput
{
[self.directionsWebView loadHTMLString:directionsOutput baseURL:nil];
}
Это все работает совершенно замечательно, если я не отказался от этой точки зрения контроллера, прежде чем CLLocationManager попадет его метод делегата , Если это произойдет после того, как я уже покинул эту точку зрения, я получаю:
2010-06-07 16:38:08.508 EverWondr[180:760b] bool _WebTryThreadLock(bool), 0x1b6830: Tried to obtain the web lock from a thread other than the main thread or the web thread. This may be a result of calling to UIKit from a secondary thread. Crashing now...
Несмотря на то, что это говорит о том, что я могу повторяемостью вызвать этот сбой, когда я вернулся слишком рано. Я совсем не убежден, что попытка обновления пользовательского интерфейса из фонового потока действительно является проблемой; Я думаю, что мой UIWebView освобожден. Я подозреваю, что тот факт, что я был только в фоновом потоке, заставляет предположить, что что-то случилось, но я уверен, что это не так.
Итак, как я могу сообщить CLLocationManager, чтобы не беспокоиться об этом, когда я отказываюсь от этой точки зрения? Я пробовал [self.locationManager stopUpdatingLocation]
внутри моего метода просмотраWillDisappear, но этого не делал.
(.. Кстати, APIs Mapquest являются Классно WAY лучше, чем что Google предоставляет я не могу рекомендовать их достаточно высоко.)
EDIT 1:
Это только что получил страннее. Я на самом деле изолирован, где он падает, и он находится внизу -(void) dealloc
. Если я прокомментирую [super dealloc]
, я не сбой! Но я не могу «вступить» в [super dealloc]
, чтобы увидеть, что происходит в суперклассе, он просто падает и перестает разговаривать со мной.
Вот StackTrace:
#0 0x3018c380 in _WebTryThreadLock()
#1 0x3018cac8 in _WebThreadAutoLock()
#2 0x3256e4f0 in -[UITextView dealloc]()
#3 0x323d7640 in -[NSObject release]()
#4 0x324adb34 in -[UIView(Hierarchy) removeFromSuperview]()
#5 0x3256e4a8 in -[UIScrollView removeFromSuperview]()
#6 0x3256e3e4 in -[UITextView removeFromSuperview]()
#7 0x324ffa24 in -[UIView dealloc]()
#8 0x323d7640 in -[NSObject release]()
#9 0x3256dd64 in -[UIViewController dealloc]()
#10 0x0000c236 in -[EventsDetailViewController dealloc] (self=0x1c8360, _cmd=0x3321ff2c) at /Users/danielray/Documents/Xcode Projects/EverWondr svn/source/obj-c/Classes/EventsDetailViewController.m:616
#11 0x323d7640 in -[NSObject release]()
#12 0x336e0352 in __NSFinalizeThreadData()
#13 0x33ad8e44 in _pthread_tsd_cleanup()
#14 0x33ad8948 in _pthread_exit()
#15 0x33731f02 in +[NSThread exit]()
#16 0x336dfd2a in __NSThread__main__()
#17 0x33ad8788 in _pthread_body()
#18 0x00000000 in ??()
Кроме того, теперь ясно, что ошибка происходит, когда кнопка назад обжигают в то время как [self getDirectionsFromHere]
работает. Окно для этого есть, пока мы ждем вызова stringWithContentsOfURL
для возврата.
EDIT 2:
Итак, заметив [UITextView dealloc]
в верхней части этого стека, я понял, что есть только один UITextView с этой точки зрения иерархии, так что я закомментирована выпуска этого UITextView объекта в -(void) dealloc
. Следующий крушение, было [UIWebView dealloc]
в том пятне следа. Гм! Изменение! Поэтому я прокомментировал выпуск одного моего webView в методе dealloc ... и теперь я не сбой. Это не решение, потому что, насколько я могу судить, я просто утечка этих двух объектов сейчас, но это, безусловно, интересно.Или, по крайней мере, я надеюсь, что это кому-то, потому что я полностью в недоумении.
Как уже упоминалось в моем обновлении ниже, я уверен, что ваша проблема на самом деле немного дальше трассировки стека: ваш контроллер быть dealloced, когда он освобождается от фонового потока на доработку. – walkytalky
Еще раз, как указано ниже: thread completes (# 17- # 12), освобождает контроллер (# 11), счетчик удержания переходит в 0, контроллер освобождается (# 10), материал UIKit освобождается по очереди (# 8- # 2), kaboom (# 0). – walkytalky
Я действительно не хочу спорить с кем-то, кто так полезен, но ... Этот след произошел от вызова моего метода dealloc, который произошел, когда я нажал кнопку назад на навигационной панели. Я не понимаю, как это можно уволить в фоновом режиме. Но эй: ты начал с ума меня, и оказалось, что ты совершенно прав, поэтому я заберу свою очередь, чтобы пошутить над вами, и, может быть, вы снова будете правы. Почему черт может быть фоновым потоком быть освобождением от контроллера представления, членом которого он является? И что можно сделать по этому поводу? –