2010-03-06 159 views
1

我的想法是有一个视角,显示用户什么时候在幕后计算的东西。这是一个高度为30px的视图,其中包含一个UIActivityIndi​​catorView和一个UILabel,显示目前正在计算的内容。从不是主线程的线程更改GUI?

我试图通过使这些方法ActivityHandler实现它:

- (void)newActivityStarted{ 
    [self performSelectorOnMainThread:@selector(showActivityViewer) withObject:nil waitUntilDone:NO]; 
} 

- (void)activityStopped{ 
    [self performSelectorOnMainThread:@selector(hideActivityViewer) withObject:nil waitUntilDone:NO]; 
} 

- (void)changeInfoText:(NSString*)infoText{ 
    [activityView.infoLabel performSelectorOnMainThread:@selector(setText:) withObject:infoText waitUntilDone:NO]; 
} 

这里有被称为主线程的方法:

-(void)hideActivityViewer{ 
    CGContextRef context = UIGraphicsGetCurrentContext(); 
    [UIView beginAnimations:nil context:context]; 

    [UIView setAnimationCurve:UIViewAnimationCurveEaseOut]; 
    [UIView setAnimationDuration:0.2]; 
    [UIView setAnimationDelegate: self]; 
    [UIView setAnimationDidStopSelector:@selector(closeActivityViewer:finished:context:)]; 
    [activityView setFrame:CGRectMake(320, 10, 320, 30)]; 

    [UIView commitAnimations]; 
} 

-(void)closeActivityViewer:(NSString*)id finished:(BOOL)finished context:(id)context{ 

    [activityView removeFromSuperview]; 
    [activityView release]; 
    activityView = nil; 
} 

-(void)showActivityViewer{ 

    activityView = [[BCActivityView alloc] initWithFrame:CGRectMake(320, 10, 320, 30)]; 
    [activityView.infoLabel setText:NSLocalizedString(@"WorkInProgressKey",nil)]; 

    [[(MyAppDelegate*)[[UIApplication sharedApplication] delegate] window] addSubview: activityView]; 

    CGContextRef context = UIGraphicsGetCurrentContext(); 
    [UIView beginAnimations:nil context:context]; 

    [UIView setAnimationCurve:UIViewAnimationCurveEaseIn]; 
    [UIView setAnimationDuration:0.2]; 
    [activityView setFrame:CGRectMake(0, 10, 320, 30)]; 

    [UIView commitAnimations]; 
} 

方法newActivityStarted,activityStopped,changeInfoText被后台线程调用,计算一些耗时的数据。

消耗线程将被打开这样的时间:

NSInvocationOperation* operation = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(calculateData) object:nil]; 
[[[NSOperationQueue new] autorelease] addOperation:operation]; 
[operation release]; 

的计算完成这样的:

-(void) calculateData{ 
    [[ActivityIndicatorHandler instance] newActivityStarted]; 
    [[ActivityIndicatorHandler instance] changeInfoText:NSLocalizedString(@"InitializingForecastKey", nil)]; 

    //Do something time consuming 

    [[ActivityIndicatorHandler instance] activityStopped]; 
} 

的效果是,该活动图被示出和整个后隐藏计算完成。我希望GUI能够显示视图,并在后台完成计算时负责用户交互。但即使我在计算中有一个断点,在计算线程完成其工作之前,该视图将无法使用,并且活动视图也不会显示......并且我无法弄清楚什么是错误的...

有没有人有想法?

回答

2
@implementation ActivityHandler; 

//.... 
- (void)newActivityStarted{ 
    [self performSelectorOnMainThread:@selector(showActivityViewer) withObject:nil waitUntilDone:NO]; 
} 

- (void)activityStopped{ 
    [self performSelectorOnMainThread:@selector(hideActivityViewer) withObject:nil waitUntilDone:NO]; 
} 

- (void)changeInfoText:(NSString*)infoText{ 
    [activityView.infoLabel performSelectorOnMainThread:@selector(setText:) withObject:infoText waitUntilDone:NO]; 
} 


- (NSInvocationOperation*)myOperation: 
{ 
    NSInvocationOperation* operation = [[[NSInvocationOperation alloc] initWithTarget:self selector:@selector(calculateData) object:nil] autorelease]; 
    return operation; 
} 

在其他一些方法,可能是您的应用程序委托,有一个本地队列在初始化设置:

NSOperaionQueue* aQueue = [[[NSOperationQueue alloc] init] retain]; //release in dealloc 
ActivityHandler* myHandler [[[ActivityHandler alloc] init] retain]; //release in dealloc 

Have a method to add ops to the queue: 

-(void)queueOperation:(NSInvocationOperation*)anOp; 
{ 
    [aQueue addOperation:anOp]; 
} 

-(IBAction*)startCalcs:(id)sender; 
{ 
    [self queueOperation:[myHandler myOperation]]; 

} 
+0

保留消息后该分配是不必要的。这只是造成内存泄漏。 – Giao 2010-03-06 16:07:06

+0

当然可以。我改变了答案,让myHandler成为应用程序委托人的一个ivar,并且更好地展示了我的意图。 – 2010-03-06 16:54:03

+0

感谢您的详细解答。如果我比较我们的解决方案,似乎唯一的区别是,您的队列由局部变量引用。我会尝试这个解决方案回来告诉我的结果。但是这个改变是什么? – Shingoo 2010-03-06 23:44:10

0

你有没有尝试这样做,而不是调用计算:

[self performSelectorInBackground:@selector(calculateData) withObject:nil]; 
0

我想你需要考虑performSelectorOnMainThread:withObject:waitUntilDone:方法