上一篇里面用*** UIPageController***实现了一个问卷的小demo
UIPageController实现 问卷、试卷
思路上是没有问题,但是经大神点拨,发现没有做复用,这个就很悲剧了,当题少的时候还可以,但是当题比较多的时候,发生了悲剧(题比较少的时候,还是可以接受的),内存暴涨。发现问题-->解决问题,因此琢磨了一个解决方案:
因为题的数据一直存储在dataSource中,通过复用的思路,每次重新设置数据源,实现题目切换,在数组中固定存储两个Controller,(因为不论是上一题,还是下一题,所涉及到的Controller有且仅有2个),然后每次通过重置刷新tableView来实现题目的改变
变更如下
-
*** UIPageControllerDataSource***中核心方法做如下改变:
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? { print("after- \(pageIndex)") if (pageIndex == questions.count - 1) || translateLock{ //最后一条 return nil } direction = .next let vc = getNextViewController(viewController: currentController) as? QAQuestionViewController vc?.dataSource = (questions[pageIndex + 1], realAnswer[pageIndex + 1]) currentController = vc return vc } func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? { print("before") if pageIndex == 0 || translateLock{ //当前页是第一页,那么 return nil } direction = .last let vc = getNextViewController(viewController: currentController) as? QAQuestionViewController vc?.dataSource = (questions[pageIndex - 1], realAnswer[pageIndex - 1]) currentController = vc return vc }
其中,direction,是一个枚举值,用来存储当时的方向
enum QADirection {
case none
case last
case next
}
getNextViewController是一个方法用来切换两个VC,需要从当前VC获取另一个Controller,这里通过重新设置Controller的dataSrouce,来改变Controller的内容视图
func getNextViewController(viewController: UIViewController?) -> UIViewController? {
let vc: QAQuestionViewController?
if viewController == viewControllers.first {
print(".last")
vc = viewControllers.last as? QAQuestionViewController
}else
{
print(".first")
vc = viewControllers.first as? QAQuestionViewController
}
return vc
}
这里实现了切换的逻辑,下面为了实现切换的效果:
//将要到--
func pageViewController(_ pageViewController: UIPageViewController, willTransitionTo pendingViewControllers: [UIViewController]) {
translateLock = true
if direction == .last {//想上 print("will Trans to last")
pageIndex -= 1
}else if direction == .next{// print("will Trans to next")
pageIndex += 1
}else{
print("direction 出错了")
}
pageLabel.text = "\(pageIndex + 1)/\(questions.count)"
}
func pageViewController(_ pageViewController: UIPageViewController, didFinishAnimating finished: Bool, previousViewControllers: [UIViewController], transitionCompleted completed: Bool) {
//判断是否成功,不成功,重新设置回去
print("complete \(completed)")
if !completed {
if direction == .last {
pageIndex += 1
}else if direction == .next
{
pageIndex -= 1
}else
{
print("direction 出错了")
}
pageLabel.text = "\(pageIndex + 1)/\(questions.count)"
currentController = previousViewControllers.first as? QAQuestionViewController
}
translateLock = false
}
这里根据方向,决定下一个题还是上一个题,让pageIndex自增或自减,并更新页码,在完成方法中如果失败将currentController 设置回去。
这里还创建了一个全局的变量 var translateLock: Bool = false // 锁
,用来保护Controller在animated的同时不会被重复使用,(本意是使用VC的自有属性,但是没找到...)
同样,直接跳到某一页的时候,也设置遵循这个逻辑
/// 显示相应题目
///
/// - Parameter index: 数组中第几个
func showTargetQuestion(with index: Int) {
guard !translateLock else {
//正在跳
return
}
//跳走
let pDirection: UIPageViewControllerNavigationDirection = pageIndex < index ? .forward : .reverse
pageIndex = index
let vc = getNextViewController(viewController: currentController) as? QAQuestionViewController
vc?.dataSource = (questions[pageIndex], realAnswer[pageIndex])
translateLock = true
pageViewController.setViewControllers([vc!], direction: pDirection, animated: true) { (bool) in
self.translateLock = false
if bool {
//设置当前Controller, 完成后去更新 上面的数字
self.currentController = vc
self.pageLabel.text = "\(index + 1)/\(self.questions.count)"
}
}
}
这个思路很是拙劣适应性也很差,仅仅是实现了效果,剩在简单粗暴,先凑合用用了
已经又了最新改动,放在了 UIPageController实现 问卷、试卷 3上面
demo 在:github master1.0 上面