API JSON & UIPageViewController 可选 Nil

Posted

技术标签:

【中文标题】API JSON & UIPageViewController 可选 Nil【英文标题】:API JSON & UIPageViewController optional Nil 【发布时间】:2015-04-18 06:18:33 【问题描述】:

好的,我正在尝试设计一个浏览量滑块,它使用此tutorial 作为基础从 API 检索图像 url。

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

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

致命错误:在展开可选值时意外发现 nil

由于某种原因,获取 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)



我该如何解决这个问题?

【问题讨论】:

【参考方案1】:

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

结果是,当调用viewControllerAtIndex设置startVC时,pageImages数组为空,执行return ContentViewController()。这将实例化一个空的内容视图控制器,并且由于它没有链接到情节提要,因此出口imageView 为零(实际上imageFile 为零)。这就是您收到错误的原因。

因此,您需要修改 viewControllerAtIndex 中的 if 语句,以便在数组为空时显示更有用的信息 - 可能是一个视图控制器,其中包含向用户显示数据正在下载的消息,以及系统正在下载的视觉指示器工作。

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

最后,因为最后一步涉及 UI 更新,它必须在主队列上运行。因此,您需要修改您的 dispatch_async 调用(在闭包中)以使用主队列,而不是全局队列。有关详细说明,请参阅 this answer。

【讨论】:

以上是关于API JSON & UIPageViewController 可选 Nil的主要内容,如果未能解决你的问题,请参考以下文章

iOS UIPageView与UIScrollView

在 UITableView 下方的 UIPageView 上检测滑动事件

UIPageView 容器中的大小类变化为未指定

UIPageView UIWebView 预取

SwiftUI UIPageView 编译错误和操作表问题

如何最好地将使用一个 UIViewController 将所有页面作为 UIView 处理为 StoryBoarding 和 UIPageView 的图书应用程序转换?