问题
I'm playing with some JSON parsing in iOS and i wanted to add a spinner, this works wel but i can't stop the spinner and i would like to understand why.
[spinner stopAnimating]
is called in the async block and i believe thats where the problem is, maybe because i can't call the method on spinner in the block? i've logged the spinner obj and the output is:
<UIActivityIndicatorView: 0x76905f0; frame = (150 230; 20 20); layer = <CALayer: 0x768ffb0>>
Maybe somebody can make me understand how to deal with this async methods in objective-c. I'm a absolute beginner.
The code:
- (void)viewDidLoad{
[super viewDidLoad];
UIActivityIndicatorView *spinner = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
spinner.center = CGPointMake(160, 240);
[self.view addSubview:spinner];
[spinner startAnimating];
dispatch_async(kBgQueue, ^{
NSData* data = [NSData dataWithContentsOfURL:
kLatestKivaLoansURL];
[self performSelectorOnMainThread:@selector(fetchedData:)
withObject:data waitUntilDone:YES];
NSLog(@"loans: %@", spinner);
[spinner stopAnimating];
});
}
回答1:
Never never never (never!) talk to the interface on a background thread. What you want is to jump back into the main thread - as you rightly suspect. It's easy-peasy:
[spinner startAnimating];
dispatch_async(kBgQueue, ^{
NSData* data = [NSData dataWithContentsOfURL:
kLatestKivaLoansURL];
// ... do other stuff in the background
dispatch_async(dispatch_get_main_queue(), ^{
[spinner stopAnimating];
});
});
However, your use of performSelectorOnMainThread:withObject:waitUntilDone:
with waitUntilDone:YES
is also wrong (or at least a very bad smell), since you should not be blocking on your background thread. Just call a method right here on the background thread (unless it touches the interface) and when the result comes back, it comes back.
回答2:
also call the method removeFromSuperview after stopAnimating
[spinner stopAnimating];
[spinner removeFromSuperview];
回答3:
UIKit calls can only be made in the main thread. Try this:
dispatch_async(kBgQueue, ^{
NSData* data = [NSData dataWithContentsOfURL:kLatestKivaLoansURL];
[self performSelectorOnMainThread:@selector(fetchedData:)
withObject:data waitUntilDone:YES];
NSLog(@"loans: %@", spinner);
dispatch_async(dispatch_get_main_queue(), ^{
[spinner stopAnimating];
});
});
来源:https://stackoverflow.com/questions/14538560/uiactivityindicatorview-wont-stop