2010-03-29 70 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 2010-03-29 01:28:45

+0

啊是的。试图简化此问题的代码时,这是一个复制/粘贴错误。我编辑了这篇文章。谢谢。 – 2010-03-29 03:32:51

回答

3

您正在从后台线程更新视图。这是什么导致你的问题; UIKit视图不是线程安全的。当你需要改变视图时,在主线程中进行。

+0

哦有趣。我会试试这个,谢谢! – 2010-03-29 03:33:13

+1

而不是从后台线程发布通知,请执行'[self performSelectorOnMainThread:@selector(webDone)withObject:nil waitUntilDone:NO];'这将调度选择器,以便在主线程运行循环的下一个循环中调用。 – codewarrior 2010-03-29 03:37:53

+0

这工作得很好!谢谢!这个bug现在一直困扰着我。 我需要保留通知,因为我需要在线程完成执行(并自动释放我的数据)之前将一些数据从我的web线程类复制到我的MainViewController。但是,在通知正常更新UI之后添加performSelectorOnMainThread调用。 – 2010-03-29 14:26:00