【问题标题】:Image passed from an API not displaying in a pageview container swift从 API 传递的图像未快速显示在页面浏览容器中
【发布时间】:2018-11-06 13:04:39
【问题描述】:

我正在开发一个使用 alamofire 和 swiftyJSON 与 API 交互的 iOS 应用程序。在这个 api 中,我得到了一堆返回的值,其中一个是图像。返回的图像以数组的形式出现,但我能够遍历数组并显示单个图像。为了使应用程序更高级,我决定在我的应用程序中实现 UIPageViewController 类。我调用了 API 函数并尝试将我的图像传递给视图控制器。

我的故事板中的事物列表

  1. 一个 UIPageView
  2. 一个嵌入了 UIImage 的 UiViewController。

据我所知,我的代码很好,但是当我运行应用程序时,控制台中没有任何反应。以下是我的代码。

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)
        }
    }
}

这是我的 ImageVC 代码

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")
            }
        }

    }}

这是我的 HeaderImageView 代码

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
    }
}

我不知道为什么代码不起作用,但会根据要求提供更多代码。谢谢。

根据建议

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
    }()

这仍然返回空

【问题讨论】:

  • 你在主线程上设置图像吗?
  • 我不知道在主线程上设置是否有问题,但我没有指定线程
  • 打印当前线程或放置断点以检查您正在设置图像的线程。或者,您可以指定线程以排除线程问题。
  • 它没有在主线程上运行
  • 请在主线程上设置图像。 DispatchQueue.main.async { // 设置图片 }

标签: ios json swift alamofire sdwebimage


【解决方案1】:

问题

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
}()

如果你观察上面的代码并且你应该调试它,那么你会发现controllers是空的,因为它是异步任务并且编译器不会等待完成findIndividualProducts任务完成它会返回你的空数组有定义所以结果是你的控制器没有什么可显示的! -> 有意义

解决方案很简单,您可以创建方法来设置调用 API findIndividualProducts 并将其分配给 controllers 现在控制器是简单的普通属性。

希望对你有帮助

编辑

首先创建一个方法并从视图调用它加载或视图将出现任何适合你的东西

 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
                }

            })
        }
    })

}

并从控制器属性中删除惰性块

var controllers: [UIViewController] = []

【讨论】:

  • 对不起,我不太明白。你能进一步解释一下吗?
  • @King 简而言之,您的懒惰var controllers: [UIViewController] = { 现在在 api 响应到来之前有 API 调用,return controllers 语句执行,因此您的视图控制器为空,您将看不到任何东西 希望很清楚
  • 是的。但是我现在如何将图像传递给控制器​​
  • @King 您必须创建一个方法,然后将该代码放入其中并从 viewDidLoad 或 viewwillappear 中调用它! , 所以当api调用完成后你可以调用self.pageViewControllerDelegate?.setupPageController(numberOfPages: controllers.count)并同时赋值controllers
  • 我有一个函数说 configureImg() 我删除了控制器中的 API 调用,但在 viewDidLoad 中调用 configureImg() 什么也没做。也返回空白页
猜你喜欢
  • 1970-01-01
  • 2014-11-13
  • 2020-09-02
  • 2016-11-05
  • 1970-01-01
  • 2015-04-16
  • 2014-12-11
  • 2023-03-03
  • 1970-01-01
相关资源
最近更新 更多