I am having problem with async programming.I have a UIScrollView
which will display multiple images(3~10) when I enter into detail view.So,there are two process that I currently working on.First,When I enter to the detail view,the post request which will call api to display detail data(images and data).Second,when I get the detail data,I have to download the images again which are from array(images with url).
I dont know whats wrong with my code.And also I am new to async programming.
My problem is when I first enter to UIScrollView,which was stucking at indicator
http://puu.sh/ijggV/fa90d7baed.png
When I go to the UITableViewCell and enter to UIScrollView again after three photo was downloaded,
http://puu.sh/ijgkN/d356f521b7.png
Is that because of ViewWillAppear? When I tried ViewDidLoad,the images doesn't show and stuck at loading even I change the tab multiple times
Here is my View Controller
import UIKit
import Kingfisher
class SecondViewController: UIViewController,AuctionAPIProtocol{
@IBOutlet weak var scrollView: UIScrollView!
@IBOutlet weak var imageIndicator: UIActivityIndicatorView!
var api : AuctionAPI?
var preferredViews: [UIView]!
var detailData : [AuctionModel] = []
var images = [UIImage]()
override func viewWillAppear(animated: Bool) {
api = AuctionAPI(delegate: self)
super.viewWillAppear(true)
//let images = [UIImage(named: "Image1")!, UIImage(named: "Image2")!, UIImage(named: "Image3")!]
self.preferredViews = [UIView]()
if self.detailData.isEmpty{
self.imageIndicator?.center
self.imageIndicator?.startAnimating()
// Start call the api to get the detail data
self.getAuctionDetailPhotos()
println("Auction Call")
}
// When the api get the detail data and downloaded the images,the image will show in the scroll view
if images != []{
println("Condition 1 In")
let photos : [UIImage] = self.images
for image in photos {
let preferredView = UIView(frame: CGRectMake(0, 0, image.size.width, image.size.height))
let imageView = UIImageView(frame: CGRectMake(0, 0, image.size.width, image.size.height))
imageView.image = image
imageView.contentMode = .ScaleAspectFit
imageView.clipsToBounds = true
preferredView.setTranslatesAutoresizingMaskIntoConstraints(false)
imageView.setTranslatesAutoresizingMaskIntoConstraints(false)
preferredView.addSubview(imageView)
scrollView.addSubview(preferredView)
preferredViews.append(preferredView)
}
self.imageIndicator?.stopAnimating()
}
}
func getAuctionDetailPhotos(){
api?.getAuctionDetail()
}
// This is one of the method from AuctionAPIProtocol which will went into results using delegate after API Request done
func didGetTheDetail(results: NSDictionary) {
var detail : NSDictionary = results["body"] as! NSDictionary
dispatch_async(dispatch_get_main_queue(),{
self.detailData = AuctionModel.dictWithJSON(detail)
println("Auction Call Ended")
if !(self.detailData.isEmpty){
var urlString = self.detailData[0].images as [String]
for url in urlString {
let imageUrl = NSURL(string: url)
// This is image downloading library that i using now named Kingfisher
KingfisherManager.sharedManager.retrieveImageWithURL(imageUrl!, optionsInfo: nil,
progressBlock: nil, completionHandler: { (image, error, cacheType, imageURL) -> () in
if var dimage = image {
self.images.append(dimage)
println("Photo Download Completed")
//println(self.images)
} else {
println("Error Downloading images")
}
})
}
}
})
}
override func updateViewConstraints() {
super.updateViewConstraints()
if !(images.isEmpty){
println("Condtion 2 In")
var prevView: UIView? = nil
for preferredView in preferredViews {
let imageView = preferredView.subviews[0] as! UIImageView
preferredView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[imageView]|",
options: nil, metrics: nil, views: ["imageView": imageView]))
preferredView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[imageView]|",
options: nil, metrics: nil, views: ["imageView": imageView]))
if prevView == nil {
scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|[preferredView(==scrollView)]",
options: nil, metrics: nil, views: ["scrollView": scrollView, "preferredView": preferredView]))
} else {
scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:[prevView][preferredView(==scrollView)]",
options: nil, metrics: nil, views: ["scrollView": scrollView, "prevView": prevView!, "preferredView": preferredView]))
}
scrollView.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|[preferredView(==scrollView)]",
options: nil, metrics: nil, views: ["scrollView": scrollView, "preferredView": preferredView]))
prevView = preferredView
}
}
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
if !(images.isEmpty){
println("Condition 3 In")
let contentWidth = CGFloat(preferredViews.count) * scrollView.bounds.width
let contentHeight = scrollView.bounds.height
scrollView.contentSize = CGSizeMake(contentWidth, contentHeight)
}
}
}
Any help please?I really need help.
You may need to put the "if images != []{}" block currently in the
viewWillAppear
into the Kingfisher's downloading completion handler. And since you are downloading multiple images, adispatch group
will help you to wait all downloads get over.I am not sure if it works for you, but I made a little change based on your code. You can find it here.