2012-04-28 67 views
18

我想在加載數據時(在另一個線程中)在uitableview上顯示活動指示器。所以在的UITableViewController的viewDidLoad方法:IOS:UITableView上的ActivityIndi​​cator ...如何?

-(void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    //I create the activity indicator 
    UIActivityIndicatorView *ac = [[UIActivityIndicatorView alloc] 
         initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray]; 
    [ac startAnimating]; 

    //Create the queue to download data from internet 
    dispatch_queue_t downloadQueue = dispatch_queue_create("PhotoDownload",NULL); 
    dispatch_async(downloadQueue, ^{ 
     //Download photo 
     ....... 
     ....... 
     dispatch_async(dispatch_get_main_queue(), ^{ 
     ...... 
     ...... 
     [ac stopAnimating]; 
     }); 
    }); 
    ....... 

爲什麼活動指示燈不顯示在表視圖?我怎樣才能實現它?

+0

對這個問題也感興趣。但據我所知,UIView子類不是線程安全的。 – 2012-04-28 11:39:37

回答

21

您需要將UIActivityIndi​​catorView添加到某個東西。您可以將其添加到UITableView標題視圖。爲此,您需要提供自己的自定義視圖。

... 
UIView *view = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320, 50)]; 
[view addSubview:ac]; // <-- Your UIActivityIndicatorView 
self.tableView.tableHeaderView = view; 
... 
+1

擊敗我! +1的答案。活動指標是一個UIView,所以它需要以某種方式添加到視圖層次結構中! – jmstone617 2012-04-28 11:46:00

+0

在將它添加到新創建的視圖之前,ac居住在哪裏? – sports 2015-05-19 02:02:12

12

我一直在試圖找到一個解決方案,並閱讀了很多的論壇,但我沒有得到我想要的。在瞭解活動指標和表格視圖控制器的工作原理之後,我想出了以下解決方案。

由於某些原因,如果您嘗試使用tableReload或任何其他昂貴的進程在同一線程上啓動活動指示器,活動指示器將永不運行。如果您嘗試在另一個線程中運行表重裝或其他操作,那麼它可能不安全並可能產生錯誤或不需要的結果。所以我們可以運行在另一個線程上顯示活動指示符的方法。

我也將這個解決方案與MBProgressHUD結合起來,呈現出一個看起來更漂亮的活動指標視圖。在任何情況下,activityView的外觀都可以定製。

-(void)showActivityViewer 
{ 
    AppDelegate *delegate = [[UIApplication sharedApplication] delegate]; 
    UIWindow *window = delegate.window; 
    activityView = [[UIView alloc] initWithFrame: CGRectMake(0, 0, window.bounds.size.width, window.bounds.size.height)]; 
    activityView.backgroundColor = [UIColor blackColor]; 
    activityView.alpha = 0.5; 

    UIActivityIndicatorView *activityWheel = [[UIActivityIndicatorView alloc] initWithFrame: CGRectMake(window.bounds.size.width/2 - 12, window.bounds.size.height/2 - 12, 24, 24)]; 
    activityWheel.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhite; 
    activityWheel.autoresizingMask = (UIViewAutoresizingFlexibleLeftMargin | 
             UIViewAutoresizingFlexibleRightMargin | 
             UIViewAutoresizingFlexibleTopMargin | 
             UIViewAutoresizingFlexibleBottomMargin); 
    [activityView addSubview:activityWheel]; 
    [window addSubview: activityView]; 

    [[[activityView subviews] objectAtIndex:0] startAnimating]; 
} 

-(void)hideActivityViewer 
{ 
    [[[activityView subviews] objectAtIndex:0] stopAnimating]; 
    [activityView removeFromSuperview]; 
    activityView = nil; 
} 

- (IBAction)reloadDataAction:(id)sender { 
    [NSThread detachNewThreadSelector:@selector(showActivityViewer) toTarget:self withObject:nil]; 
    //... do your reload or expensive operations 
    [self hideActivityViewer]; 
} 
+0

這對我來說很好,在幾種選擇之後。謝謝@zirinisp! – dfdumaresq 2013-08-26 14:11:38

+0

一直在尋找相當長的一段時間,我不得不說這是迄今爲止最好的解決方案。 – cookiemonsta 2013-09-26 09:04:06

+0

這是行得通的,但是我怎樣才能將它移入幫助程序類,以便我可以調用任何視圖? – aherrick 2014-03-30 14:33:27

6

[的iOS 5 +]
如果你只是想顯示activityWheel無需額外parentview,您還可以在activityWheel添加直奔的tableView和計算使用的tableViews contentOffset幀的y值:

@interface MyTableViewController() 
@property (nonatomic, strong) UIActivityIndicatorView *activityView; 
@end 

// .... 

- (void) showActivityView { 
    if (self.activityView==nil) { 
     self.activityView = [[UIActivityIndicatorView alloc] initWithFrame:CGRectZero]; 
     [self.tableView addSubview:self.activityView]; 
     self.activityView.activityIndicatorViewStyle = UIActivityIndicatorViewStyleWhiteLarge; 
     self.activityView.hidesWhenStopped = YES; 
     // additional setup... 
     // self.activityView.color = [UIColor redColor]; 
    } 
    // Center 
    CGFloat x = UIScreen.mainScreen.applicationFrame.size.width/2; 
    CGFloat y = UIScreen.mainScreen.applicationFrame.size.height/2; 
    // Offset. If tableView has been scrolled 
    CGFloat yOffset = self.tableView.contentOffset.y; 
    self.activityView.frame = CGRectMake(x, y + yOffset, 0, 0); 

    self.activityView.hidden = NO; 
    [self.activityView startAnimating]; 
} 

- (void) hideActivityView { 
    [self.activityView stopAnimating]; 
} 

如果activityView不立即(或從不)顯示,請參閱zirinisp的回答或做重活的背景。

4

有解決UIViewController的方法。 (您可以使用帶有表視圖的UIViewController來實現UITableViewController。) 在故事板中,在UIViewController的視圖中添加一個activityIndi​​cator。 然後在viewDidLoad中,添加以下:

[self.activityIndicator layer].zPosition = 1; 

的activityIndi​​cator將在表視圖被顯示。

-1

雖然這個問題很老,但我也加了我的。 [IOS 8+] 以上不適用於我。取而代之,我將 指標視圖(ac)存儲在類中。 後來我做:

- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section 
{ 
    if (ac.isAnimating) 
     return 50.0f; 
    return 0.0f; 
} 

- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section 
{ 
    if (ac.isAnimating) 
     return ac; 
    return nil; 
} 

用於顯示indicatorview我做

[ac startAnimating] 

隱藏它,我做

[ac stopAnimating] 

我希望這是有幫助的人。

相關問題