2010-03-29 2 views
0

6 раз из 10 мое очень простое приложение для iPhone получает поврежденный дисплей при запуске или аварийно падает. Но он отлично работает в симуляторе. Повреждение дисплея выглядит как неправильно окрашенные шрифты, шрифт нестандартного шрифта, неправильные цвета фона и т. Д.Зачем задерживать искажение ответа на ответ потока?

Я обнаружил странную работу. Когда мой поток задерживается на 2 секунды, прежде чем вызывать «сделанные», уведомление, все работает плавно. Поток читает веб-страницу, а «сделанное» уведомление загружает PickerView со строками. Так что же дает? Могу ли я безопасно инициировать задачу с потоком из viewDidLoad?

- (void) loadWebPage:(NSString *)urlAddition { 
     NSAutoreleasePool *subPool = [[NSAutoreleasePool alloc] init]; 
     NSString *pageSource; 
     NSError *err; 
     NSString *urlString = [NSString stringWithFormat:@"http://server/%@", 
          urlAddition]; 
     pageSource = [NSString stringWithContentsOfURL:[NSURL URLWithString: urlString] 
              encoding:NSUTF8StringEncoding 
               error:&err]; 

     [NSThread sleepForTimeInterval:2.0]; // THIS STOPS THE DISPLAY CORRUPTION 
     [[NSNotificationCenter defaultCenter] postNotificationName:@"webDoneNotification" 
                  object:nil]; 
     [subPool drain]; 
} 

- (void) webDoneNotification: (NSNotification *)pNotification { 
     [mediaArray release]; 
     mediaArray = [[NSArray arrayWithObjects: 
        [NSString stringWithString:@"new pickerview text"], 
        nil] retain]; 

     [mediaPickerView reloadAllComponents]; 

     [mediaPickerView selectRow:0 
        inComponent:0 
         animated:NO]; 
} 


- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { 
    mediaArray = [[NSArray arrayWithObjects: 
       [NSString stringWithString:@"init pickerview text"], 
       nil] retain]; 

    if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) { 
     // Custom initialization 
    } 

    return self; 
} 

- (void)viewDidLoad { 
    [super viewDidLoad]; 

    myWebThread = [[WebThread alloc] initWithDelegate:self]; 
    [[NSNotificationCenter defaultCenter] addObserver:self 
              selector:@selector(webDoneNotification:) 
               name:@"webDoneNotification" 
               object:nil]; 
    [myWebThread performSelectorInBackground:@selector(loadWebPage:) withObject:@""]; 
} 

Спасибо!

Обновление: достаточно полной задержки на 0,1 секунды, чтобы полностью устранить проблему.

+0

Я не могу помочь вам с вашей основной проблемой, но я считаю, что использование 'stringWithString' неверно. Если вы хотите использовать «% @» в качестве спецификатора формата, вместо этого вы должны использовать 'stringWithFormat'. – warrenm

+0

Ах да. Это была ошибка копирования/вставки при попытке упростить код для этого вопроса. Я редактировал сообщение. Благодарю. –

ответ

3

Вы обновляете представление из фоновой нити. Это то, что вызывает проблемы; Представления UIKit не являются потокобезопасными. Когда вам нужно изменить вид, сделайте это в основном потоке.

+0

О, интересно. Я попробую, спасибо! –

+1

Вместо того, чтобы отправлять уведомление из вашего фонового потока, сделайте '[self performSelectorOnMainThread: @selector (webDone) withObject: nil waitUntilDone: NO];' Это расписание селектора, который будет вызываться на следующем проходе через цикл запуска основного потока. – codewarrior

+0

Это сработало отлично! Спасибо! Эта ошибка преследует меня какое-то время. Мне нужно сохранить уведомление, потому что мне нужно скопировать некоторые данные из моего класса веб-потока в мой MainViewController, прежде чем поток завершит выполнение (и автоматически очистит мои данные). Но добавление вызова performSelectorOnMainThread после уведомления отлично работает только для обновления пользовательского интерфейса. –

Смежные вопросы