title: SWIFT aws S3 downloads asynchonously ? downloading images and populating a tableview
body: <p>I m kind of new to swift and IOS and I might have an asynchronous problem (not sure), I have a firebase database giving me the keys and URLS of uploaded content on Amazon S3. I m trying to download the images from S3, store them in an array and then populate the tableview.</p>
  
  <p>The code seems to launch the download but it doesnt progress (a break point on progress doesn t even hit)</p>
  
  <p>could someone give me a hand on how to cleanly populate my tableview ? my array of images is always empty and i don t know if it s coming from my s3 function (but does not return any error) or if it comes from the dispatch events.</p>
  
  <pre><code>    //
  //  MainWitness.swift
  //  trainning2
  //
  //  Created by Yann MASSARD on 2/2/16.
  //  Copyright © 2016 Witness. All rights reserved.
  //
  
  import UIKit
  import Firebase
  import FirebaseUI
  
  
  class MainWitness: UIViewController, UITableViewDataSource, UITableViewDelegate {
  
      let rootref = Firebase(url: "XXXXXXX/witness/")
      let refpost = Firebase(url: "XXXXXXX/witness/POSTS")
      var posts = [getitems]()
      var Images = [UIImage]()
  
  
  
      @IBOutlet weak var tableView: UITableView!
  
      // S3 download function / called on view did appear, gets the key from firebase
  
      func downloadImage(key:String){
  
          var completionHandler: AWSS3TransferUtilityDownloadCompletionHandlerBlock?
  
          let S3BucketName: String = "witnesstest/" + rootref.authData.uid
          let S3DownloadKeyName: String = key
  
  
          let expression = AWSS3TransferUtilityDownloadExpression()
          expression.downloadProgress = {(task: AWSS3TransferUtilityTask, bytesSent: Int64, totalBytesSent: Int64, totalBytesExpectedToSend: Int64) in
              dispatch_async(dispatch_get_main_queue(), {
                  let progress = Float(totalBytesSent) / Float(totalBytesExpectedToSend)
                  print("Progress is: \(progress)")
              })
          }
  
          completionHandler = { (task, location, data, error) -&gt; Void in
              dispatch_async(dispatch_get_main_queue(), {
                  if ((error) != nil){
                      print("Failed with error")
                      print("Error: \(error!)")
                  }
                  else{
                      //Set your image
                      self.Images.append(UIImage(data: data!)!)
                  }
              })
          }
  
          let transferUtility = AWSS3TransferUtility.defaultS3TransferUtility()
  
          transferUtility.downloadToURL(nil, bucket: S3BucketName, key: S3DownloadKeyName, expression: expression, completionHander: completionHandler).continueWithBlock { (task) -&gt; AnyObject! in
              if let error = task.error {
                  print("Error: \(error.localizedDescription)")
              }
              if let exception = task.exception {
                  print("Exception: \(exception.description)")
              }
              if let _ = task.result {
                  print("Download Starting!")     // shows in console for each firebase post loop
              }
              return nil;
          }
  
      }
  
      override func viewDidAppear(animated: Bool) {
  
          // [1] Call the queryOrderedByChild function to return a reference that queries by the "author" property
           self.refpost.queryOrderedByChild("author").observeEventType(.Value, withBlock: { snapshot in
  
              var newItems = [getitems]()
  
              for item in snapshot.children {
  
                  let postitem = getitems(snapshot: item as! FDataSnapshot)
                  newItems.append(postitem)
  
              //     READ IMAGE FROM S3
                  self.downloadImage(postitem.imagekey)
  
              }
  
              self.posts = newItems
              self.tableView.reloadData()
          })
  
      }
  
  
      override func viewDidLoad() {
         //ref.unauth()
          super.viewDidLoad()
  
          //tableview datasource and delegate
          tableView.delegate = self
          tableView.dataSource = self
      }
  
  
  
      override func didReceiveMemoryWarning() {
          super.didReceiveMemoryWarning()
          // Dispose of any resources that can be recreated.
      }
  
      override func viewWillAppear(animated: Bool) {
          // is any user log ?
          if ((rootref.authData) != nil) {
              print("user logged")
          } else {
              print("user not logged")
              dispatch_async(dispatch_get_main_queue()){
  
                  self.performSegueWithIdentifier("log", sender: self)
  
              }
          }
  
      }
  
      func numberOfSectionsInTableView(tableView: UITableView) -&gt; Int {
          return 1
  
      }
  
       func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -&gt; UITableViewCell {
  
          let cell: MainWitnessTableViewCell = self.tableView.dequeueReusableCellWithIdentifier("RIcell") as! MainWitnessTableViewCell
  
              // populate the cell
              let postitem = posts[indexPath.row]
              cell.postOwner.text = postitem.author
              cell.postContent.text = postitem.content
              cell.postDate.text = postitem.createon
  
             // cell.cellImage.image = Images[indexPath.row] // returns array index out of range
  
  
          return cell
      }
  
      func tableView(tableView: UITableView, didselectRowAtIndexPath indexPath: NSIndexPath) {
  
      }
  
      func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -&gt; Int {
  
          return posts.count
  
  
  
      }
  
  
  
  }
  </code></pre>