好的,我正在尝试设计一个网页浏览 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/