I have a collectionView of photos as a subview of another view. I would like to display it only after I have performed a query to get the pictures to populate it, and put an activity indicator if it is not ready. I tried to put my code in viewWillAppear, but I don't get the photo downloaded before displaying the view. What would be the best way to handle this?
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
let query = queryAPI()
query.userExtra(currentUser, completion: { (user:ModelUser) -> () in
self.currentUser = user
if let userPhotos = self.currentUser.photos as [ModelAttachment]! {
self.photos = [UIImage]()
for object in userPhotos as [ModelAttachment] {
Utils.getImageAsync(object.url!, completion: { (img: UIImage?) -> () in
self.photos?.append(img!)
object.image = img
})
}
self.photosCollectionView.reloadData()
}
})
}
func collectionView(collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView == photosCollectionView {
if let hasPhotos = photos as [UIImage]! {
return photos!.count
} else {
return 0
}
}else{
return friends.count
}
}
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
if collectionView == photosCollectionView {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("Cell", forIndexPath: indexPath) as! UICollectionViewCell
let imageView = cell.viewWithTag(1) as! UIImageView
let photo = photos![indexPath.row]
imageView.image = photo
return cell
}
}
And the function to get the images async:
class func getImageAsync(url:String, completion: (UIImage?) -> ()){
var escapedUrl = url.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet())
var imageUrl = NSURL(string: escapedUrl!)
if(imageUrl == nil)
{
println("Invalid Url!")
completion(nil)
}
else
{
var stdUrl = imageUrl!.standardizedURL!
println("Downlading image: "+stdUrl.description)
let req = NSURLRequest(URL: stdUrl)
NSURLConnection.sendAsynchronousRequest(req, queue: NSOperationQueue.mainQueue()) { (resp, data, error) -> Void in
var image: UIImage?
if data != nil {
image = UIImage(data: data!)!
} else {
println("Error while download the image: \(error)")
}
dispatch_async(dispatch_get_main_queue()) {
completion(image)
}
}
}
}
In response to your comment, "The function is in another file as I am using it in different places in my code, how can I call reload the data of another controller there?"
There are multiple ways to do this. One method is to post a NSNotification and add an observer on your view controller.
To post a notification:
[[NSNotificationCenter defaultCenter]
postNotificationName:@"TestNotification"
object:self];
To receive and respond to a notification:
- (void) viewDidLoad {
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(receiveTestNotification:)
name:@"TestNotification"
object:nil];
}
- (void) receiveTestNotification:(NSNotification *) notification
{
if ([[notification name] isEqualToString:@"TestNotification"])
[self.photosCollectionView reloadData];
}