Question

My cocoa app needs to fetch data from network and then shows content in the table view. So I add a spinning style of NSProgressIndicator to animate when the data is downloading. After that the animation of NSProgressIndicator stops and reloads the NSTableView. The strange thing is after the table view reloading, the content shown is not updated. Then If you scroll the table view, the content starts to show,just like: enter image description here (the small rectangle above is the frame for the NSProgressIndicator)

Below is my code:


- (void)loadOperationData
{   
    dispatch_async(dispatch_get_main_queue(), ^{
        [self _showIndicator];
    });

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

- (void)_showIndicator
{
    if (indicator == nil) 
    {
        indicator = [[NSProgressIndicator alloc] init];
        [indicator setStyle:NSProgressIndicatorSpinningStyle];
        [indicator setUsesThreadedAnimation:NO];// I tried to comment this, but no use
        int width = 30;
        CGRect rect = CGRectMake(0, 0, width, width);
        NSRect selfRect = [_coverView frame];
        rect.origin.x = selfRect.size.width/2 - width/2;
        rect.origin.y = selfRect.size.height/2 - width/2;
        indicator.frame = rect;
        [_coverView addSubview:indicator];
    }
    
    [indicator setHidden:NO];
    [indicator startAnimation:self];
}

-(void)getOperationLogProcess{
    
    NSDictionary *tempResutDic = [WebServiceManager getOperationLog];//using synchronous ASIHttpRequest to download data
    if ([[tempResutDic objectForKey:@"resultCode"] intValue]==100) {
        self.operationLogArray = [tempResutDic objectForKey:@"items"];
        
        [self performSelectorOnMainThread:@selector(reloadTableview) withObject:nil waitUntilDone:YES];//refresh UI in main thread
    }
}

-(void)reloadTableview
{
    [indicator stopAnimation:self];
    [indicator setHidden:YES];
    [operationlogTable setEnabled:YES];
    
    if ([_coverView isHidden])
    {
        return;
    }
    
    self.lastUpdateDate = [NSDate date];
    
    [operationlogTable reloadData];
}

The -(void)loadOperationData is called by the mouse click event. And The reason why I put the -(void)_showIndicator in a dispatch block is that the indicator can't be shown. I tried a lot and finally chose it.

I guess the problem ties closely to the way of showing indicator because If I commented the code about the indicator, the problem dismissed.

I really need the indicator to let user know they are waiting.So Please help me how to correctly use NSProgressIndicator.

Thanks!

Was it helpful?

Solution

It caused by the multithread.

In- (void)loadOperationData I use main block to show progress indicator and create a thread to fetch data in background. The block is run asynchronously and sometimes is after the -(void)reloadTableview.

Finally, I keep - (void)loadOperationData is called in main thread and put the - (void)_showIndicator out of the block. Then it is fixed.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top