2010-10-16

網路傳輸時 UIActivityIndicatorView 的動作

這已經是習慣了,大家都習慣要有這個符號出現。
當你的程式有使用到網路傳輸,通常就需要放一個 UIActivityIndicatorView 在畫面上,讓使用者知道目前正在傳輸中,以免讓人覺得沒有回應,像是當機一樣。
可是,為何你照著書本範例加到自己的程式卻不會動呢?

原因是:UIKit 的 main thread 一次只有做一件事,如果你在 ViewController 傳輸檔案,那麼其他的動作會等傳輸完之後再接下去做,所以你要另外再生出一個 thread 去處理 UIActivityIndicatorView 的動作。

使用 Objective-C 來處理 thread 是很簡單的,比 Java 還容易,在後面的說明裡會看到。


首先,在 .h 檔的 @interface 內加上

UIActivityIndicatorView *activityIndicator;


以及

@property (nonatomic, retain) IBOutlet UIActivityIndicatorView *activityIndicator;


另外,再加上兩個 method

-(void)actIndicatorBegin;
-(void)actIndicatorEnd;


開啓 .m 檔,在 @implementation 的下面加上

@synthesize activityIndicator;


在 (void)loadView 內把你的 UIActivityIndicatorView 加上去你要的 View 上面,我這裡加在 UIToolbar 工具列裡面的一個 UIBarButtonItem 按鈕

activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(0, 0, 24, 24)];
[activityIndicator setCenter:CGPointMake(12, 12)];
[activityIndicator setHidesWhenStopped:YES];
[activityIndicator setActivityIndicatorViewStyle: UIActivityIndicatorViewStyleWhite];
[activityIndicator startAnimating];
UIBarButtonItem *activityItem = [[[UIBarButtonItem alloc] initWithCustomView: activityIndicator] autorelease];


再把這個 UIBarButtonItem 加到 UIToolbar 內

NSArray *items = [NSArray arrayWithObjects:activityItem, nil];
toolbarTop.items = items;


在處理網路傳輸之前先執行這個 thread

[NSThread detachNewThreadSelector: @selector(actIndicatorBegin) toTarget:self withObject:nil];

//需要時間下載檔案的程式寫在這裡

url = [NSURL URLWithString:@"http://網址/圖片檔.jpg"];
img =[UIImage imageWithData:[NSData dataWithContentsOfURL:url]];


網路傳輸完之後再執行這個 thread

[NSThread detachNewThreadSelector: @selector(actIndicatorEnd) toTarget:self withObject:nil];


再加上這兩個 method 開關旋轉狀態
- (void) actIndicatorBegin {
[activityIndicator startAnimating];
}

-(void) actIndicatorEnd {
[activityIndicator stopAnimating];
}


就這麼簡單,做看看吧!

.

2 則留言:

  1. [NSThread detachNewThreadSelector: @selector(actIndicatorBegin) toTarget:self withObject:nil];

    或許可以寫成:

    [NSThread detachNewThreadSelector: @selector(startAnimating) toTarget:activityIndicator withObject:nil];

    回覆刪除