I did develop a technique to keep the network activity indicator spinning when 
multiple sources may request to have it spinning.

In my app delegate, I have those methods:

- (void)startNetworkIndicatorForInstance:(id)anInstance
{
        NSString *addressAsString = [NSString stringWithFormat:@"%p", 
anInstance];
        if (addressAsString == nil) {
                return;
        }
        NSNumber *numberOfInvocations = [self.networkIndicatorClients 
objectForKey:addressAsString];
        if (numberOfInvocations == nil) {
                numberOfInvocations = [NSNumber numberWithInt:1];
                [self.networkIndicatorClients setObject:numberOfInvocations 
forKey:addressAsString];
        }
        else {
                [self.networkIndicatorClients setObject:[NSNumber 
numberWithInt:[numberOfInvocations intValue] + 1] forKey:addressAsString];
        }
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                _networkIndicatorStack++;
                if (_networkIndicatorStack > 0 && ! [UIApplication 
sharedApplication].networkActivityIndicatorVisible)
                        [UIApplication 
sharedApplication].networkActivityIndicatorVisible = YES;
        }];
}

- (void)reallyStopNetworkIndicatorFromTimer:(NSTimer *)aTimer
{
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                [aTimer invalidate];
                [UIApplication 
sharedApplication].networkActivityIndicatorVisible = NO;
        }];
}

- (void)stopNetworkIndicatorOnMainThread
{
        // In case of very short start and stop, we don't want to have the 
indicator flickering so when we get a stop, we delay
        // the hiding by one second
        [[self class] cancelPreviousPerformRequestsWithTarget:self 
selector:@selector(reallyStopNetworkIndicatorFromTimer:) object:NULL];
        [self performSelector:@selector(reallyStopNetworkIndicatorFromTimer:) 
withObject:NULL afterDelay:PERFORM_DELAY];
}

- (void)stopNetworkIndicatorForInstance:(id)anInstance
{
        NSString *addressAsString = [[NSString stringWithFormat:@"%p", 
anInstance] copy];
        NSNumber *numberOfInvocations = [self.networkIndicatorClients 
objectForKey:addressAsString];
        if (numberOfInvocations != nil) {
                if ([numberOfInvocations intValue] > 1) {
                        [self.networkIndicatorClients setObject:[NSNumber 
numberWithInt:[numberOfInvocations intValue] - 1] forKey:addressAsString];
                }
                else {
                        [self.networkIndicatorClients 
removeObjectForKey:addressAsString];
                }
        }
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
                _networkIndicatorStack--;
                if (_networkIndicatorStack < 0) {
                        _networkIndicatorStack = 0;
                }
                if (_networkIndicatorStack == 0) {
                        [self stopNetworkIndicatorOnMainThread];
                }
        }];
}

I have a setup with multiple UITableViewCells that download content from a 
server. They each send the app delegate startNetworkIndicatorForInstance: and 
they give their own pointer as the caller. As you can see in that method 
implementation, the app delegate object converts the address into a string and 
then check to see if that instance has already sent a 
startNetworkIndicatorForInstance:. If it hasn't, I create an NSNumber and set 
this object for the pointer address as a string as the key. I think it's fairly 
obvious what is happening. When a UITableViewCell is finished with its 
downloads (can have more than one), it sends the delegate 
stopNetworkIndicatorForInstance:.

If the UITableViewCell is about to be deallocated and had a download executing, 
it cancels the download and send the app delegate 
stopNetworkIndicatorForInstance:

This all works pretty well except that from time to time, the app will crash 
with a SIGABRT:

        • 0 erodr 0x0011cfe6 testflight_backtrace + 238
        • 1 erodr 0x0011dcd0 TFSignalHandler + 264
        • 2 libsystem_c.dylib 0x3901de92 _sigtramp + 42
        • 3 libsystem_c.dylib 0x39014122 pthread_kill + 58
        • 4 libsystem_c.dylib 0x39050972 abort + 94
        • 5 libsystem_c.dylib 0x3901af18 <redacted> + 0
        • 6 libsystem_c.dylib 0x3901b234 <redacted> + 84
        • 7 libsystem_c.dylib 0x38fe92de free + 170
        • 8 CoreFoundation 0x35262cae <redacted> + 206
        • 9 CoreFoundation 0x351c5560 <redacted> + 732
        • 10 erodr 0x000d7b06 -[ERAppDelegate 
startNetworkIndicatorForInstance:] (ERAppDelegate.m:747)
        • 11 erodr 0x000f531c __68-[StreamerImageTextCell 
downloadPictureFromURL:forKey:inDictionary:]_block_invoke_0 
(StreamerImageTextCell.m:81)
        • 12 Foundation 0x32ca5538 <redacted> + 200
        • 13 Foundation 0x32c9cdb8 <redacted> + 840
        • 14 Foundation 0x32d153da <redacted> + 102
        • 15 libdispatch.dylib 0x33f5411e <redacted> + 10
        • 16 libdispatch.dylib 0x33f58960 <redacted> + 252
        • 17 libdispatch.dylib 0x33f58ac0 <redacted> + 84
        • 18 libsystem_c.dylib 0x38feba10 <redacted> + 360
        • 19 libsystem_c.dylib 0x38feb8a3 start_wqthread + 7

Line 747 of ERAppDelegate.m is:

                [self.networkIndicatorClients setObject:numberOfInvocations 
forKey:addressAsString];

I have no idea why this crash is happening. I use the same technique in another 
app and never had a crash in the startNetworkIndicatorForInstance:.

Anybody has any idea of what is going on?

Thanks!

-Laurent.
-- 
Laurent Daudelin
AIM/iChat/Skype:LaurentDaudelin                                 
http://www.nemesys-soft.com/
Logiciels Nemesys Software                                      
[email protected]


_______________________________________________

Cocoa-dev mailing list ([email protected])

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to [email protected]

Reply via email to