Maystro
Maystro

Reputation: 2955

keep network activity indicator spinning

I found that sometimes you may be doing something in your iPhone application that requires the user to wait while it completes. Often this is a network related activity, but in other cases it may not be. In my case I was parsing the response from a network connection and wanted the network activity indicator to keep spinning even though it had already downloaded the content.

below is what i'm doing:

applicationDelegate.m :

- (void)setNetworkActivityIndicatorVisible:(BOOL)setVisible
{
    static NSInteger NumberOfCallsToSetVisible = 0;
    if (setVisible) 
        NumberOfCallsToSetVisible++;
    else 
        NumberOfCallsToSetVisible--;

    // Display the indicator as long as our static counter is > 0.
    [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:(NumberOfCallsToSetVisible > 0)];
}

otherView.m:

dispatch_queue_t dataLoadingQueue = dispatch_queue_create("synchronise", NULL);
    dispatch_async(dataLoadingQueue,
                   ^{
                       [appDelegate setNetworkActivityIndicatorVisible:YES];
                       [[DataLoader instance]LoadDataForGrewal];
                       [[FieldConsultantViewModelManager instance] resetCache];  
                       [[DailyFieldConsultantViewModelManager instance] clearCache];
                       [appDelegate loadMainViews];
                       [[DataLoader instance]LoadDataForOtherEntities]; 
                       [appDelegate setNetworkActivityIndicatorVisible:NO];
                   });    
 dispatch_release(dataLoadingQueue);

as u can see above, i'm trying to keep the network indicator while updating the data into the database but it does not work , any clue / suggestions ?

Thanks EDIT :

dispatch_queue_t dataLoadingQueue = dispatch_queue_create("synchronise", NULL);
    dispatch_async(dataLoadingQueue,
                   ^{
                       dispatch_async(dispatch_get_main_queue(), ^{ [self setNetworkActivityIndicatorVisible:YES]; });
                       [[DataLoader instance]LoadDataForGrewal];
                       [[FieldConsultantViewModelManager instance] resetCache];  
                       [[DailyFieldConsultantViewModelManager instance] clearCache];
                       [appDelegate loadMainViews];
                       [[DataLoader instance]LoadDataForOtherEntities]; 
                       dispatch_async(dispatch_get_main_queue(), ^{ [self setNetworkActivityIndicatorVisible:NO]; });
                   });    
 dispatch_release(dataLoadingQueue);

it does not work i'm not sure why because i'm newbie in ios

Upvotes: 2

Views: 2053

Answers (2)

Sunkas
Sunkas

Reputation: 9600

For anyone looking for a complete solution, this is what I use (in Swift). It delays a short duration when stopping the network indicator. This will prevent the indicator from flickering if you have a lot of serial network request.

private var networkActivityCount = 0

func updateNetworkActivityCount(increaseNumber increase:Bool)
{
    let appendingCount = increase ? 1 : -1
    networkActivityCount += appendingCount
    let delayInSeconds = increase ? 0.0 : 0.7
    perform({ () -> () in
        let application = UIApplication.sharedApplication()
        let shouldBeVisible = self.networkActivityCount > 0
        if application.networkActivityIndicatorVisible != shouldBeVisible {
            application.networkActivityIndicatorVisible = shouldBeVisible
        }
    }, afterDelay: delayInSeconds)
}

Where perform:afterDelay is defined as

public func perform(block: ()->(), afterDelay:Double) {
    let dispatchTime: dispatch_time_t = dispatch_time(DISPATCH_TIME_NOW, Int64(afterDelay * Double(NSEC_PER_SEC)))
    dispatch_after(dispatchTime, dispatch_get_main_queue(), {
         block()
    })
}

Just call updateNetworkActivityCount(increaseNumber: true) before your request and the same with false in your request callback. I.e:

updateNetworkActivityCount(increaseNumber: true)
let task = urlSession.dataTaskWithRequest(request) { data, response, error in
    self.updateNetworkActivityCount(increaseNumber: false)
    ...

Upvotes: 1

iSofTom
iSofTom

Reputation: 1718

try to dispatch your setNetworkActivityIndicatorVisible: call on main queue, because UIApplication is in UIKit and UIKit is not thread-safe.

Upvotes: 2

Related Questions