如何在后台线程上调用方法

时间:2010-10-22 20:49:55

标签: iphone objective-c multithreading

在我的应用程序中我解压缩一个zip文件(在启动视图控制器中)以后我显示一个图像并用4秒触发计时器来更改上一个图像视图的图像。后来在视图中确实出现了我正在用10秒触发另一个计时器来调用下一个视图控制器(主视图控制器)..并且我有一个按钮去故事视图控制器...在这里我使用的是解压缩数据..在这种情况下需要一些时间解压缩。所以图像r后来显示几秒......这里很好

问题是...我在背景线程上调用解压缩,因此它快速显示图像并移动到主视图控制器..然后通过单击按钮在设备上崩溃进入下一个视图控制器但其工作正常模拟器..

任何人都可以帮助我

感谢。

...代码

-(void)viewWillAppear:(BOOL)animated{
    [self performSelectorInBackground:@selector(unXip) withObject:nil]; 
    CGRect imageFrame = CGRectMake(0,20,320,460);
    splashView.frame = imageFrame;
    splashView.image = [UIImage imageNamed:@"Default.png"];
    [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:@selector(changeImg) userInfo:nil repeats:NO];
    [NSTimer scheduledTimerWithTimeInterval:3 target:self selector:@selector(changeImg2) userInfo:nil repeats:NO];


}

-(void)unXip{
    self.fileManager = [NSFileManager defaultManager];
    NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory , NSUserDomainMask, YES);
    self.documentsDir = [paths objectAtIndex:0];
    NSString *filePath = [NSString stringWithFormat:@"%@/temp", self.documentsDir];
    NSString *filePathbmlg = [NSString stringWithFormat:@"%@/temp/bmlg", self.documentsDir];

    NSString *updateURL = [[NSBundle mainBundle] pathForResource:@"bmlg" ofType:@"zip" inDirectory:@"res"];

    [fileManager createDirectoryAtPath:filePath 
           withIntermediateDirectories:NO
                            attributes:nil
                                 error:nil];


    if([fileManager fileExistsAtPath:filePath]) {
        NSLog(@"File exists at path: %@", updateURL);
    } else {
        NSLog(@"File does not exists at path: %@", updateURL);
    }

    NSLog(@"Checking update at : %@", updateURL);
    NSLog(@"Checking filepath at : %@", filePath);

    if(![fileManager fileExistsAtPath:filePathbmlg]) {  

        ZipArchive *zipArchive = [[ZipArchive alloc] init];

        if([zipArchive UnzipOpenFile:updateURL]) {

            if ([zipArchive UnzipFileTo:filePath overWrite:YES]) {
                //unzipped successfully
                NSLog(@"Archive unzip Success");
                //[self.fileManager removeItemAtPath:filePath error:NULL];
            } else {
                NSLog(@"Failure To Unzip Archive");             
            }

        } else  {
            NSLog(@"Failure To Open Archive");
        }

        [zipArchive release];
    }
}   

- (void)changeImg{

    splashView.image = [UIImage imageNamed:@"screen2.png"];

}

- (void)changeImg2{

    splashView.image = [UIImage imageNamed:@"screen3.png"];
}

- (void)viewDidAppear:(BOOL)animated{   
    [NSTimer scheduledTimerWithTimeInterval:15 target:self selector:@selector(pushCVC) userInfo:nil repeats:NO];
}

- (void)pushCVC{
    homeViewController = [[HomeViewController  alloc] initWithNibName:@"HomeView" bundle:nil];
    [self presentModalViewController:homeViewController animated:YES];
}

2 个答案:

答案 0 :(得分:1)

在任何示例代码中都很难回答这个问题。使用后台线程时要注意的一件事是确保更新UI的所有代码都在主线程上运行。

好的,我认为这可能是一个线程问题。您的unXip方法正在后台线程上修改某些内容,然后您尝试从另一个线程(主线程,如果您从UI代码访问它)访问该“某事”。您需要实现某种锁定/同步机制(例如NSLock或NSConditionLock)。

使用计时器调用pushCVC看起来有点奇怪。现在,我不确切知道你的应用程序做了什么,但是当解压缩完成后通过将其添加到unXip方法的末尾来调用pushCVC不是更好:

[self performSelectorOnMainThread:@selector(pushCVC) withObject:nil waitUntilDone:NO];

并删除计时器。

答案 1 :(得分:0)

感谢您的意见和回答......

问题是解压缩过程需要很长时间...所以如果我在完成解压缩文件之前单击主屏幕上的开始按钮,它会崩溃...因为我必须使用解压缩的数据文件...

再次感谢..