问题
I have a view controller with an UIActivityIndicatorView, and a button which triggers synchronisation. Synchronisation is performed in a separate class, usually in the background. The synchronisation can be triggered from different parts of my app, and my view controller is notified of the synchronisation events.
Now, when I click the button, the UIActivityIndicatorView does not become visible nor animated.
Here is my code in viewDiDLoad:
self.syncNowActivityIndicatorView.hidesWhenStopped = YES;
self.syncNowActivityIndicatorView.color = [MRStyleController getFirstLightColor];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(leechStarted)
name:MRLeechStartedNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(mergeStarted)
name:MRMergeStartedNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(fileSyncStarted)
name:MRFileSyncStartedNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(leechFailed)
name:MRLeechFailedNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(mergeFailed)
name:MRMergeFailedNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(fileSyncFailed)
name:MRFileSyncFailedNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(leechCompleted)
name:MRLeechCompletedNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(mergeCompleted)
name:MRMergeCompletedNotification
object:nil];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(fileSyncCompleted)
name:MRFileSyncCompletedNotification
object:nil];
I have read in some other posts, that, if I start and stop the indicator view in the same method, it will not work, because the ui is not update while the method is executing. So, the animation must be started and stopped in a separate thread, but in my case start and stop calls are all in different methods.
Note that I am receiving the notifications as my log shows.
Here are the other methods:
-(void)leechStarted{
NSLog(@"Leech started");
if (!_syncNowActivityIndicatorView.isAnimating) {
[_syncNowActivityIndicatorView startAnimating];
}
}
-(void)mergeStarted{
NSLog(@"Merge started");
if (!_syncNowActivityIndicatorView.isAnimating) {
[_syncNowActivityIndicatorView startAnimating];
}
}
-(void)fileSyncStarted{
NSLog(@"FileSync started");
if (!_syncNowActivityIndicatorView.isAnimating) {
[_syncNowActivityIndicatorView startAnimating];
}
}
-(void)leechFailed{
NSLog(@"Leech failed");
if (_syncNowActivityIndicatorView.isAnimating) {
[_syncNowActivityIndicatorView stopAnimating];
}
}
-(void)mergeFailed{
NSLog(@"Merge failed");
if (_syncNowActivityIndicatorView.isAnimating) {
[_syncNowActivityIndicatorView stopAnimating];
}
}
-(void)fileSyncFailed{
NSLog(@"FileSync failed");
if (_syncNowActivityIndicatorView.isAnimating) {
[_syncNowActivityIndicatorView stopAnimating];
}
}
-(void)leechCompleted{
NSLog(@"Leech completed");
if (_syncNowActivityIndicatorView.isAnimating) {
[_syncNowActivityIndicatorView stopAnimating];
}
}
-(void)mergeCompleted{
NSLog(@"Merge completed");
if (_syncNowActivityIndicatorView.isAnimating) {
[_syncNowActivityIndicatorView stopAnimating];
}
}
-(void)fileSyncCompleted{
NSLog(@"FileSync completed");
if (_syncNowActivityIndicatorView.isAnimating) {
[_syncNowActivityIndicatorView stopAnimating];
}
}
And here the IBAction for the button:
- (IBAction)syncNow:(id)sender {
// perform synchronisation
CoreDataHelper *cdh = [(MRMedSafeAppDelegate *) [[UIApplication sharedApplication] delegate] cdh];
if ([cdh canSynchronize]) {
[cdh mergeEnsemble];
[cdh synchroniseFiles];
}
}
mergeEnsemble
posts leech and merge notifications, and synchroniseFiles
file sync notifications, and I receive them according to the log.
回答1:
You must perform the start/stop animating on the main thread:
-(void)stopAnimation:(id)sender {
if( _syncNowActivityIndicatorView.isAnimating ) {
[_syncNowActivityIndicatorView stopAnimating];
}
}
-(void)startAnimation:(id)sender {
if( !_syncNowActivityIndicatorView.isAnimating ) {
[_syncNowActivityIndicatorView startAnimating];
}
}
-(void)leechStarted{
NSLog(@"Leech started");
[self performSelectorOnMainThread:@selector(startAnimation:) withObject:self waitUntilDone:YES];
}
-(void)leechFailed{
NSLog(@"Leech failed");
[self performSelectorOnMainThread:@selector(stopAnimation:) withObject:self waitUntilDone:YES];
}
来源:https://stackoverflow.com/questions/24944793/uiactivityindicatorview-does-not-show-start-animating