2010-03-06 84 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:方法