Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Image passed from an API not displaying in a pageview container swift

I am working on an iOS application which interacts with an API using alamofire and swiftyJSON. In this api I get a bunch of values returned and one of them is images. the Images returned comes in form of an array but i am able to iterate through the array and display a single image. To make the application more advanced, I decided to implement UIPageViewController class in my application. I called the API function and tried to pass my images into view controllers.

List of things in my storyboard

  1. A UIPageView
  2. A UiViewController with a UIImage embeded into it.

I have my codes fine to the best of my knowledge but when I run the application nothing happens on in the console. Below is my codes.

protocol ProductImagesPageViewControllerDelegate: class {
    func setupPageController(numberOfPages: Int)
    func turnPageController(to index: Int)
}

class ProductPageVC: UIPageViewController {

    weak var  pageViewControllerDelegate: ProductImagesPageViewControllerDelegate?

    override func viewDidLoad() {
        super.viewDidLoad()

        automaticallyAdjustsScrollViewInsets = false
        dataSource = self
        delegate = self

    }


    func configureImg() {
        let productId = ProductServices.instance.selectedProduct?.id
        ProductServices.instance.findIndividualProducts(id: productId!, completion: { (success) in

            if success {
                ProductServices.instance.productDetails.forEach({ (productDetail) in

                    let images = productDetail.productImg.count

                    if images > 0 {

                        for image in 0..<(images) {

                            let imageVC = self.storyboard?.instantiateViewController(withIdentifier: PRODUCT_IMAGE_VC)
                            self.controllers.append(imageVC!)

                        }
                    }

                })
            }
        })
    }

    lazy var controllers: [UIViewController] = {

        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        var controllers = [UIViewController]()


        let productId = ProductServices.instance.selectedProduct?.id
        ProductServices.instance.findIndividualProducts(id: productId!, completion: { (success) in

            if success {
                ProductServices.instance.productDetails.forEach({ (productDetail) in

                    let images = productDetail.productImg.count

                    if images > 0 {

                        for image in 0..<(images) {

                            let imageVC = storyboard.instantiateViewController(withIdentifier: PRODUCT_IMAGE_VC)
                            controllers.append(imageVC)

                        }
                    }

                })
            }
        })



        self.pageViewControllerDelegate?.setupPageController(numberOfPages: controllers.count)

        return controllers
    }()



    func turnToPage(index: Int)
    {
        let controller = controllers[index]
        var direction = UIPageViewControllerNavigationDirection.forward

        if let currentVC = viewControllers?.first {
            let currentIndex = controllers.index(of: currentVC)!
            if currentIndex > index {
                direction = .reverse
            }
        }

        self.configureDisplaying(viewController: controller)

        setViewControllers([controller], direction: direction, animated: true, completion: nil)
    }

    func configureDisplaying(viewController: UIViewController)
    {
        for (index, vc) in controllers.enumerated() {
            if viewController === vc {
                if let imageVC = viewController as? ImagesVC {

                    imageVC.configureImage(productIndex: index)

                    self.pageViewControllerDelegate?.turnPageController(to: index)
                }
            }
        }
    }
}
// MARK: - UIPageViewControllerDataSource

extension ProductPageVC : UIPageViewControllerDataSource
{
    func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController?
    {
        if let index = controllers.index(of: viewController) {
            if index > 0 {
                return controllers[index-1]
            }
        }

        return controllers.last
    }

    func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {

        if let index = controllers.index(of: viewController) {
            if index < controllers.count - 1 {
                return controllers[index + 1]
            }
        }

        return controllers.first
    }
}

extension ProductPageVC : UIPageViewControllerDelegate {

    func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController])
    {
        self.configureDisplaying(viewController: pendingViewControllers.first as! ImagesVC)
    }

    func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool)
    {
        if !completed {
            self.configureDisplaying(viewController: previousViewControllers.first as! ImagesVC)
        }
    }
}

This is my ImageVC code

class ImagesVC: UIViewController {

    @IBOutlet weak var imageView: UIImageView!


    func configureImage(productIndex : Int) -> Void {

        ProductServices.instance.productDetails.forEach { (productImg) in

            if productImg.productImg.count > 0 {
                imageView.sd_setImage(with: URL(string: productImg.productImg[productIndex]!) )
            } else {
                imageView.image = UIImage(named: "image_not_found")
            }
        }

    }}

This is my HeaderImageView code

class HeaderImageVC: UIView {

    @IBOutlet weak var pageControl: UIPageControl!
}

extension HeaderImageVC : ProductImagesPageViewControllerDelegate {
    func setupPageController(numberOfPages: Int)
    {
        pageControl.numberOfPages = numberOfPages
    }

    func turnPageController(to index: Int)
    {
        pageControl.currentPage = index
    }
}

I have no idea why the code is not working but further codes would be supplied on request. Thanks.

According to suggestion

var images = (ProductServices.instance.productDetails.first?.productImg) 

    lazy var controllers: [UIViewController] = {

        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        var controllers = [UIViewController]()

        if let images = self.images {
            for image in images {
                let imageVC = storyboard.instantiateViewController(withIdentifier: PRODUCT_IMAGE_VC)
                controllers.append(imageVC)
            }
        }



        self.pageViewControllerDelegate?.setupPageController(numberOfPages: controllers.count)

        return controllers
    }()

this still returns empty

like image 331
King Avatar asked May 28 '18 00:05

King


1 Answers

problem

lazy var controllers: [UIViewController] = {

    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    var controllers = [UIViewController]()

    // IT WILL NOT WAIT TO FINISH IT
    let productId = ProductServices.instance.selectedProduct?.id
    ProductServices.instance.findIndividualProducts(id: productId!, completion: { (success) in

        if success {
            ProductServices.instance.productDetails.forEach({ (productDetail) in

               // NO USE OF productDetail as it is already returned 

                let images = productDetail.productImg.count

                if images > 0 {

                    for image in 0..<(images) {

                        let imageVC = storyboard.instantiateViewController(withIdentifier: PRODUCT_IMAGE_VC)
                        controllers.append(imageVC)

                    }
                }

            })
        }
    })


    // controllers.count is 0

    self.pageViewControllerDelegate?.setupPageController(numberOfPages: controllers.count)

    return controllers
}()

if you observe above code and you should debug it, then you will find that controllers is empty Because it is async task and compiler will not wait for finish findIndividualProducts task to complete it will return the empty array which you have define so outcome is your controller has nothing to show !! -> Make sense

Solution is that simple you can create method that will set the call the API findIndividualProducts and assign it to the controllers now the controller is simple plain property.

Hope it is helpful

EDIT

First create one method and call it from view did load or view will appear whatever suits you

 private func getAllControllers () {
    let storyboard = UIStoryboard(name: "Main", bundle: nil)
    var controllers = [UIViewController]()

    // IT WILL NOT WAIT TO FINISH IT
    let productId = ProductServices.instance.selectedProduct?.id
    ProductServices.instance.findIndividualProducts(id: productId!, completion: { (success) in

        if success {
            ProductServices.instance.productDetails.forEach({ (productDetail) in

               // NO USE OF productDetail as it is already returned 

                let images = productDetail.productImg.count

                if images > 0 {

                    for image in 0..<(images) {

                        let imageVC = storyboard.instantiateViewController(withIdentifier: PRODUCT_IMAGE_VC)
                        controllers.append(imageVC)

                    }


  self.pageViewControllerDelegate?.setupPageController(numberOfPages: controllers.count)
  self.controllers = controllers
                }

            })
        }
    })

}

and remove lazy block from your controller property

var controllers: [UIViewController] = []

like image 72
Prashant Tukadiya Avatar answered Oct 01 '22 04:10

Prashant Tukadiya