ios - API JSON 和 UIPageViewController 可选 Nil

标签 ios json swift uipageviewcontroller alamofire

好的,我正在尝试设计一个网页浏览 slider ,它使用这个 tutorial 从 API 检索图像 url作为基地。

我已经编写了异步下载图像并将其附加到 pageImages 数组的代码。那部分工作正常。

但是,当我尝试在模拟器中运行该应用程序时收到错误消息:

fatal error: unexpectedly found nil while unwrapping an Optional value

出于某种原因,获取 JSON 对象并填充 pageImages 数组发生在我调用辅助方法 viewControllerAtIndex 之后。

我的代码

class ViewController: UIViewController, UIPageViewControllerDataSource {

var pageViewController: UIPageViewController!
var pageImages = NSArray()
var jsonData = NSArray()

override func viewDidLoad() {
    super.viewDidLoad()

    ###THIS EXECUTES AFTER MY HELPER METHOD viewControllerAtIndex
    self.fetchPublishers()

    self.pageViewController = self.storyboard?.instantiateViewControllerWithIdentifier("PageViewController") as! UIPageViewController

    self.pageViewController.dataSource = self

    var startVC = self.viewControllerAtIndex(0) as ContentViewController
    var viewControllers = NSArray(object: startVC)

    self.pageViewController.setViewControllers(viewControllers as [AnyObject], direction: .Forward, animated: true, completion: nil)

    self.pageViewController.view.frame = CGRectMake(0, 30, self.view.frame.width, self.view.frame.size.height)

    self.addChildViewController(self.pageViewController)
    self.view.addSubview(self.pageViewController.view)
    self.pageViewController.didMoveToParentViewController(self)
}

func pageViewController(pageViewController: UIPageViewController, viewControllerBeforeViewController viewController: UIViewController) -> UIViewController? {
    var vc = viewController as! ContentViewController
    var index = vc.pageIndex as Int

    if (index == 0 || index == NSNotFound) {
        return nil
    }

    index--
    return self.viewControllerAtIndex(index)
}

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

    var vc = viewController as! ContentViewController
    var index = vc.pageIndex as Int

    if (index == NSNotFound) {
        return nil
    }

    index++

    if (index == self.pageImages.count) {
        return nil
    }

    return self.viewControllerAtIndex(index)

}

func viewControllerAtIndex(index: Int) -> ContentViewController
{
    if ((self.pageImages.count == 0) || (index >= self.pageImages.count)) {
        return ContentViewController()
    }

    var vc: ContentViewController = self.storyboard?.instantiateViewControllerWithIdentifier("ContentViewController") as! ContentViewController

    vc.imageFile = self.pageImages[index] as! String
    vc.pageIndex = index

    return vc

}

func presentationCountForPageViewController(pageViewController: UIPageViewController) -> Int
{
    return self.pageImages.count
}

func presentationIndexForPageViewController(pageViewController: UIPageViewController) -> Int
{
    return 0
}

func fetchPublishers () {

    var req:Request = Alamofire.request(OauthToken.Router.ReadPublishers(""))

    var aClosure =  {(req:NSURLRequest, response:NSHTTPURLResponse?, JSON:AnyObject?, error:NSError?) -> Void in

        if (error != nil) {
            println(error)
            println("Couldn't connection to server.")
        } else {

          dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0)) {

            self.jsonData = JSON as! NSArray!

            var baseUrl: String = "http://0.0.0.0:3000"
            self.pageImages = JSON!.valueForKey("photo_url") as! NSArray!

            ###Prints/executes after
            println(self.pageImages)

          }

        }

    }

    req.responseJSON(aClosure)

}

} 

ContentViewController

class ContentViewController: UIViewController {

@IBOutlet weak var imageView: UIImageView!

var pageIndex: Int!
var imageFile: String!

override func viewDidLoad() {
    super.viewDidLoad()

    ####THE ERROR HAPPENS HERE
    self.imageView.image = UIImage(named: self.imageFile)
}

}

我该如何解决这个问题?

最佳答案

事情没有按顺序发生,因为引用 AlamoFire github page :“Alamofire 中的网络是异步完成的。”这意味着 aClosure 中的代码在从服务器收到响应之前不会执行,但是 viewDidLoad 的执行无论如何都会继续。

结果是,当调用viewControllerAtIndex设置startVC时,pageImages数组为空,执行return ContentViewController() .这实例化了一个空的内容 View Controller ,并且由于它没有链接到 Storyboard,导出 imageView 为 nil(实际上 imageFile 为 nil)。这就是您收到错误的原因。

因此,您需要修改 viewControllerAtIndex 中的 if 语句,以便在数组为空时显示更有帮助的内容 - 可能是一个 View Controller ,向用户发送一条数据正在下载的消息,以及一个可视化 View 指示系统正在运行。

然后,当数据确实从服务器到达时,您必须找到一种方法来重新加载页面 View Controller 。为此,您应该在 aClosure 的末尾添加一些代码。在本教程中,有一个函数 restartAction 可以执行必要的操作,因此要么调用它,要么将代码复制到闭包中。

最后,因为最后一步涉及 UI 更新,所以它必须在主队列上运行。因此,您需要修改您的 dispatch_async 调用(在闭包中)以使用主队列,而不是全局队列。参见 this answer以获得对此的完整解释。

关于ios - API JSON 和 UIPageViewController 可选 Nil,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29713692/

相关文章:

java - Spring 启动 : Is it possible to consume @RequestParam's as json?

ios10 swift3.0 Alamofire上传图片出现错误

ios - 每当我在任何按钮(即 UISegmentedControl 按钮)外单击时,按钮也会被单击。谁能告诉我为什么会这样?

ios - 按下按钮时 UIViewcontroller 不打开

php - 在 PHP 中更新 JSON 数组

javascript - 如何解析JSON格式的数据

ios - 后台获取什么时间用完了?

ios - 为 PFobjects 实现 UISearchController 时出错

ios - 我有隐藏文本字段的问题

ios - swift 中 UITableView 的多个委托(delegate)