I have a PhotoViewController
class with an @property UIActivityIndicatorView* spinner
. FlickrPhotoViewController
is a subclass of PhotoViewController
that downloads a photo from Flickr and tells the spinner when to start and stop animating. 'updatePhoto' is called every time the view controller is given a Flickr photo:
- (void)updatePhoto { // Download photo and set it
NSLog("updatePhoto called");
if (self.spinner) NSLog(@"Spinner exists in updatePhoto");
dispatch_queue_t downloadQueue = dispatch_queue_create("downloader",
NULL);
[self.spinner startAnimating];
dispatch_async(downloadQueue, ^{
// Download the photo
dispatch_async(dispatch_get_main_queue(), ^{
[self.spinner stopAnimating];
// Set the photo in the UI
}
});
});
}
The above methodology is exactly what I use for displaying a spinning wheel in my table view controllers while the table contents download, and it always works there.
You will notice at the beginning of updatePhoto
I print a message if the UIActivityIndicatorView
exists. I put a similar statement in awakeFromNib
, viewDidLoad
, and viewWillAppear
. When I run it, this is the exact output I get:
2013-01-31 21:30:55.211 FlickrExplorer[1878:c07] updatePhoto called
2013-01-31 21:30:55.222 FlickrExplorer[1878:c07] Spinner exists in viewDidLoad
2013-01-31 21:30:55.223 FlickrExplorer[1878:c07] Spinner exists in viewWillAppear
Why does spinner
not exist in awakeFromNib
? Docs indicate that "When an object receives an awakeFromNib message, it is guaranteed to have all its outlet and action connections already established." Can an IBOutlet be connected without the existence of the object it is connecting to? In this case, can the spinner
IBOutlet be connected to the storyboard without spinner
being allocated?
Moving beyond this, I overrode the getter for spinner
so that it would instantiate if it does not exist. As a result, the printing output now looks like this:
2013-01-31 21:48:45.646 FlickrExplorer[2222:c07] Spinner exists in awakeFromNib
2013-01-31 21:48:45.647 FlickrExplorer[2222:c07] updatePhoto called
2013-01-31 21:48:45.647 FlickrExplorer[2222:c07] Spinner exists in updatePhoto
2013-01-31 21:48:45.649 FlickrExplorer[2222:c07] Spinner exists in viewDidLoad
2013-01-31 21:48:45.650 FlickrExplorer[2222:c07] Spinner exists in viewWillAppear
This is what I would have expected to see earlier. Nevertheless, I still do not get any animation.
Possible problems that I have ruled out:
- The spinner is the same color as the background, making it invisible. In my project, the background is black and the spinner is white.
- I am attempting to animate the
UIActivityIndicatorView
while some expensive method is blocking the main thread. In my project, all my file system I/O and downloading methods are called in a non-maindispatch_async
queue. - The spinner's IBOutlet is not hooked up. In my project, I have double checked this numerous times. It can be seen from both the storyboard and the PhotoViewController.h file that it is connected.
All three of these possibilities are ruled out by the fact that putting [self.spinner startAnimating];
in viewWillAppear
makes it successfully animate throughout the download process.
You can download this project if you like. Just go to any screen that attempts to display a large photo and you will see that the spinner does not appear. There are many problems with this project, but this is the one I am focusing on now.
Edit 1:
- I added the project's missing dependencies on Git, so the project will now compile for you
Edit 2 (2 February 2013):
- I am seeing this problem only on the iPhone when the
updatePhoto
method is called due to another view controller'sprepareForSegue
setting the photo in theFlickrPhotoViewController
. Is it possible that this contributes to the problem?