简体   繁体   中英

Completion Handler is not working in viewDidLoad?

I'm using this library in my app for banners. I am trying to get the Link by parsing the JSON.

The Images are are not showing in the slideshow view. If I press the slideshow view, after that everything works fine. I thought that there was some issue with my completion handler. But I can't solve it yet :)

@IBOutlet weak var slideshow: ImageSlideshow!
var transitionDelegate: ZoomAnimatedTransitioningDelegate?
var Banner : [AlamofireSource] = []

override func viewDidLoad() {
        super.viewDidLoad()
        Banners { (imagesource) in
            if imagesource != nil {
                self.bannershow()
            }
        }
  }

    func Banners(completionHandler: ([AlamofireSource]?) -> ()) -> (){
        Alamofire.request(.GET, "http://46.420.116.11/mobileapp/gps/api.php?rquest=get_banners")
            .responseJSON{ response in
                if let data = response.result.value{
                    let json = JSON(data)
                    let count = json["image_path"].count
                    for index in 0...count-1 {
                        let image :String = json["image_path"][index].stringValue
                        let source : AlamofireSource = AlamofireSource(urlString: image)!
                        self.Banner.append(source)
                    }
                    completionHandler(self.Banner)
                }
        }
  }

    func bannershow(){
        self.slideshow.backgroundColor = UIColor.whiteColor()
        self.slideshow.slideshowInterval = 2.0
        self.slideshow.contentScaleMode = UIViewContentMode.ScaleToFill
        self.slideshow.setImageInputs(self.Banner)

        let recognizer = UITapGestureRecognizer(target: self, action: "click")
        self.slideshow.addGestureRecognizer(recognizer)
        }

 func click() {
        let ctr = FullScreenSlideshowViewController()
        ctr.pageSelected = {(page: Int) in
            self.slideshow.setScrollViewPage(page, animated: false)
        }

        ctr.initialPage = slideshow.scrollViewPage
        ctr.inputs = slideshow.images
        self.transitionDelegate = ZoomAnimatedTransitioningDelegate(slideshowView: slideshow);
        ctr.transitioningDelegate = self.transitionDelegate!
        self.presentViewController(ctr, animated: true, completion: nil)
    }

You probably have a threading problem. There is no guarantee that the Banners completion handler is called on the main thread. You need to step out to the main thread explicitly before doing anything that touches your properties or (especially) the interface.

I think your problem might be that you're expecting the images to be available immediately but they need to be downloaded before, so they won't be available immediately after your viewDidLoad method finished. That's why you should probably configure your slideshow in the viewDidLoad and not in your bannershow() method. Something like this might be an improvement:

@IBOutlet weak var slideshow: ImageSlideshow!
var bannerImages : [AlamofireSource] = []

override func viewDidLoad() {
    super.viewDidLoad()
    slideshow.backgroundColor = UIColor.whiteColor()
    slideshow.slideshowInterval = 2.0
    slideshow.contentScaleMode = UIViewContentMode.ScaleToFill
    let recognizer = UITapGestureRecognizer(target: self, action: "click")
    slideshow.addGestureRecognizer(recognizer)

    getBanners { imagesource in
        self.showBanner()
    }
}

func getBanners(completionHandler: ([AlamofireSource]?) -> ()) -> (){
    Alamofire.request(.GET, "http://46.420.116.11/mobileapp/gps/api.php?rquest=get_banners")
        .responseJSON{ response in
            if let data = response.result.value{
                let json = JSON(data)
                let count = json["image_path"].count
                for index in 0...count-1 {
                    let image :String = json["image_path"][index].stringValue
                    let source : AlamofireSource = AlamofireSource(urlString: image)!
                    self.bannerImages.append(source)
                }

            }
            completionHandler(self.bannerImages)
    }
}

func showBanner() {
    slideshow.setImageInputs(bannerImages)
}

Move the code to viewWillAppear .

override func viewWillAppear(animated: Bool) {
    Banners { (imagesource) in
        if imagesource != nil {
            self.bannershow()
        }
    }
}
func Banners(completionHandler: ([AlamofireSource]?) -> ()) -> (){
    Alamofire.request(.GET, "http://46.420.116.11/mobileapp/gps/api.php?rquest=get_banners")
        .responseJSON{ response in
            if let data = response.result.value{
                let json = JSON(data)
                let count = json["image_path"].count
                for index in 0...count-1 {
                    let image :String = json["image_path"][index].stringValue
                    let source : AlamofireSource = AlamofireSource(urlString: image)!
                    self.Banner.append(source)
                }
                completionHandler(self.Banner)
            }
    }

}

You are executing for loop in Banners fun
for index in 0...count-1 { let image :String = json["image_path"][index].stringValue let source : AlamofireSource = AlamofireSource(urlString: image)! self.Banner.append(source) } Replace this code in some other method and place an Optional
var image :String? = json["image_path"][index].stringValue

or place an thumb image, That will make you confirm that image is downloaded successfully or not .

Let me know if it works

Thanks, Happy Coding

Maybe you don't see images because you update them in a secondary thread, you have to perform image update in main thread; In swift ( performSelectorOnMainThread() is not available), you may use something like this :

 dispatch_async(dispatch_get_main_queue(), {

                    myslideshow.updateimage();

 })

Not really sure, but I am guessing that since your images need to get downloaded, they are nil when you call self.slideshow.setImageInputs(self.Banner) , which internally sets the image from the list to an imageview which is added inside the scrollView. So one way I can think of is use SDWebImage to set the image to the imageView so that it updates the respective imageViews once the image is ready(downloaded). I think you will need to use it in the InputSource.swift class in the setToImageView(_:) method. You will have to check this though, this is the only possible problem i could think of that might be causing your issue.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM