API 请求后更新 UIPageViewController 的正确方法
Correct way to update UIPageViewController after an API request
当我尝试使用 Alamofire 执行 GET 请求时遇到问题。在我的 viewDidLoad 方法中。我已经检查过我的请求是否有效并且我的数组已填充但是当我 运行 代码时我得到一个致命错误:索引超出范围因为当我调用 getViewControllerAtIndex 方法时数组在那一刻是空的。
如果我想用来自 API 的数据创建我的 UIPageViewController,我该怎么办?
这是我在 ViewController.swift
中的代码
import UIKit
import Foundation
import Alamofire
class ViewController: UIPageViewController, UIPageViewControllerDataSource {
var arrPageTitle = [String]()
var arrPagePhoto = [String]()
override func viewDidLoad() {
super.viewDidLoad()
let guidesEndpoint: String = "http://testapi.eu-gb.mybluemix.net/guides"
Alamofire.request(guidesEndpoint).responseJSON { (response) in
if let JSON = response.result.value {
//print("JSON: \(JSON)")
if let guides = JSON as? [String : AnyObject] {
if let guideResourceList = guides["_embedded"] as? [String : AnyObject] {
//print(guideResourceList)
if let guidesArray = guideResourceList["guideResourceList"] as? [AnyObject] {
for guide in guidesArray {
if let guideGuide = guide["guide"] as? [String : AnyObject] {
if let textItem = guideGuide["text"] as? String {
// Populate arrPageTitle
self.arrPageTitle.append(textItem)
print(textItem)
}
}
if let guideLinks = guide["_links"] as? [String : AnyObject] {
if let linksObj = guideLinks["imageUrl"] as? [String : String] {
if let link = linksObj["href"] {
// Populate arrPagePhoto
self.arrPagePhoto.append(link)
print(link)
}
}
}
}
}
}
}
}
}
self.dataSource = self
self.setViewControllers([getViewControllerAtIndex(0)] as [UIViewController], direction: UIPageViewControllerNavigationDirection.forward, animated: false, completion: nil)
}
// Use this method to return to previous view. In this I have put a condition such that if it is first view then return nil otherwise return ViewController.
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
let pageContent: PageContentViewController = viewController as! PageContentViewController
var index = pageContent.pageIndex
if index == 0 || index == NSNotFound {
return nil
}
index -= 1
return getViewControllerAtIndex(index)
}
// MARK:- UIPageViewControllerDataSource Methods
// Use this method to return next view. In this I have put a condition such that if it is last view then return nil otherwise return ViewController.
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
let pageContent: PageContentViewController = viewController as! PageContentViewController
var index = pageContent.pageIndex
if index == NSNotFound { return nil }
index += 1
if index == arrPageTitle.count { return nil }
return getViewControllerAtIndex(index)
}
// MARK:- Custom Methods
func getViewControllerAtIndex(_ index: Int) -> PageContentViewController {
// Create a new view controller and pass suitable data.
let pageContentViewController = self.storyboard?.instantiateViewController(withIdentifier: "PageContentViewController") as! PageContentViewController
// fatal error: Index out of range
pageContentViewController.strTitle = "\(arrPageTitle[index])"
pageContentViewController.strPhotoName = "\(arrPagePhoto[index])"
pageContentViewController.pageIndex = index
pageContentViewController.numberOfPages = arrPagePhoto.count
print("\(arrPagePhoto.count)")
return pageContentViewController
}
}
这是我的 PageContentViewController.swift
import UIKit
class PageContentViewController: UIViewController {
@IBOutlet weak var lblTitle: UILabel!
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var pageControl: UIPageControl!
var pageIndex: Int = 0
var strTitle: String!
var strPhotoName: String!
var numberOfPages: Int!
override func viewDidLoad() {
super.viewDidLoad()
imageView.image = UIImage(named: strPhotoName)
lblTitle.text = strTitle
pageControl.currentPage = pageIndex
pageControl.numberOfPages = numberOfPages
}
}
有什么想法吗???
self.setViewControllers([getViewControllerAtIndex(0)] as [UIViewController], direction: UIPageViewControllerNavigationDirection.forward, animated: false, completion: nil)
需要在不超出该范围的 alamofire 回调中调用。您从 (arrPageTitle) 填充的数组在您调用 setViewControllerAtIndex 时将为空,并且您正在访问数组中的值,索引给您带来越界错误。
你应该在这个 if-scope 的末尾调用函数
if let guidesArray = guideResourceList["guideResourceList"] as? [AnyObject] {
//parsing code...
self.setViewControllers([getViewControllerAtIndex(0)] as [UIViewController], direction: UIPageViewControllerNavigationDirection.forward, animated: false, completion: nil)
}
或在 for 循环内,具体取决于您要执行的操作。
当我尝试使用 Alamofire 执行 GET 请求时遇到问题。在我的 viewDidLoad 方法中。我已经检查过我的请求是否有效并且我的数组已填充但是当我 运行 代码时我得到一个致命错误:索引超出范围因为当我调用 getViewControllerAtIndex 方法时数组在那一刻是空的。 如果我想用来自 API 的数据创建我的 UIPageViewController,我该怎么办? 这是我在 ViewController.swift
中的代码 import UIKit
import Foundation
import Alamofire
class ViewController: UIPageViewController, UIPageViewControllerDataSource {
var arrPageTitle = [String]()
var arrPagePhoto = [String]()
override func viewDidLoad() {
super.viewDidLoad()
let guidesEndpoint: String = "http://testapi.eu-gb.mybluemix.net/guides"
Alamofire.request(guidesEndpoint).responseJSON { (response) in
if let JSON = response.result.value {
//print("JSON: \(JSON)")
if let guides = JSON as? [String : AnyObject] {
if let guideResourceList = guides["_embedded"] as? [String : AnyObject] {
//print(guideResourceList)
if let guidesArray = guideResourceList["guideResourceList"] as? [AnyObject] {
for guide in guidesArray {
if let guideGuide = guide["guide"] as? [String : AnyObject] {
if let textItem = guideGuide["text"] as? String {
// Populate arrPageTitle
self.arrPageTitle.append(textItem)
print(textItem)
}
}
if let guideLinks = guide["_links"] as? [String : AnyObject] {
if let linksObj = guideLinks["imageUrl"] as? [String : String] {
if let link = linksObj["href"] {
// Populate arrPagePhoto
self.arrPagePhoto.append(link)
print(link)
}
}
}
}
}
}
}
}
}
self.dataSource = self
self.setViewControllers([getViewControllerAtIndex(0)] as [UIViewController], direction: UIPageViewControllerNavigationDirection.forward, animated: false, completion: nil)
}
// Use this method to return to previous view. In this I have put a condition such that if it is first view then return nil otherwise return ViewController.
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
let pageContent: PageContentViewController = viewController as! PageContentViewController
var index = pageContent.pageIndex
if index == 0 || index == NSNotFound {
return nil
}
index -= 1
return getViewControllerAtIndex(index)
}
// MARK:- UIPageViewControllerDataSource Methods
// Use this method to return next view. In this I have put a condition such that if it is last view then return nil otherwise return ViewController.
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
let pageContent: PageContentViewController = viewController as! PageContentViewController
var index = pageContent.pageIndex
if index == NSNotFound { return nil }
index += 1
if index == arrPageTitle.count { return nil }
return getViewControllerAtIndex(index)
}
// MARK:- Custom Methods
func getViewControllerAtIndex(_ index: Int) -> PageContentViewController {
// Create a new view controller and pass suitable data.
let pageContentViewController = self.storyboard?.instantiateViewController(withIdentifier: "PageContentViewController") as! PageContentViewController
// fatal error: Index out of range
pageContentViewController.strTitle = "\(arrPageTitle[index])"
pageContentViewController.strPhotoName = "\(arrPagePhoto[index])"
pageContentViewController.pageIndex = index
pageContentViewController.numberOfPages = arrPagePhoto.count
print("\(arrPagePhoto.count)")
return pageContentViewController
}
}
这是我的 PageContentViewController.swift
import UIKit
class PageContentViewController: UIViewController {
@IBOutlet weak var lblTitle: UILabel!
@IBOutlet weak var imageView: UIImageView!
@IBOutlet weak var pageControl: UIPageControl!
var pageIndex: Int = 0
var strTitle: String!
var strPhotoName: String!
var numberOfPages: Int!
override func viewDidLoad() {
super.viewDidLoad()
imageView.image = UIImage(named: strPhotoName)
lblTitle.text = strTitle
pageControl.currentPage = pageIndex
pageControl.numberOfPages = numberOfPages
}
}
有什么想法吗???
self.setViewControllers([getViewControllerAtIndex(0)] as [UIViewController], direction: UIPageViewControllerNavigationDirection.forward, animated: false, completion: nil)
需要在不超出该范围的 alamofire 回调中调用。您从 (arrPageTitle) 填充的数组在您调用 setViewControllerAtIndex 时将为空,并且您正在访问数组中的值,索引给您带来越界错误。
你应该在这个 if-scope 的末尾调用函数
if let guidesArray = guideResourceList["guideResourceList"] as? [AnyObject] {
//parsing code...
self.setViewControllers([getViewControllerAtIndex(0)] as [UIViewController], direction: UIPageViewControllerNavigationDirection.forward, animated: false, completion: nil)
}
或在 for 循环内,具体取决于您要执行的操作。