Pan Segue 调用 viewDidLoad 循环
Posted
技术标签:
【中文标题】Pan Segue 调用 viewDidLoad 循环【英文标题】:Pan Segue Calls viewDidLoad Loop 【发布时间】:2015-12-09 00:33:22 【问题描述】:我的平移手势以编程方式伪造按钮按下。如果按下实际按钮,VC 的 viewDidLoad 会再次运行一次,然后停止,一切正常。 但是当我使用平移手势以编程方式伪造按钮按下时,viewDidLoad 会运行大约七次,然后停止。
右边缘手势触发加载几次的“明天”状态。此时,左边缘手势触发“今天”状态。这也加载了 4-5 次。
有什么想法吗?如果需要,下面的一些代码。
在 viewDidLoad 中添加了平移手势:
//Adds edge gesture depending on VC state
if curMainList == "Today"
let panLeftEdgeGesture_MainVC = UIScreenEdgePanGestureRecognizer(target: self, action: "panLeftEdge_toLifeList:")
panLeftEdgeGesture_MainVC.edges = .Left
view.addGestureRecognizer(panLeftEdgeGesture_MainVC)
let panRightEdgeGesture_MainVC = UIScreenEdgePanGestureRecognizer(target: self, action: "panFromRightEdgeAction:")
panRightEdgeGesture_MainVC.edges = .Right
view.addGestureRecognizer(panRightEdgeGesture_MainVC)
self.footer_LeftBtn.addTarget(self, action: "LeftFooterBtnPress", forControlEvents: UIControlEvents.TouchUpInside)
else
let panLeftEdgeGesture = UIScreenEdgePanGestureRecognizer(target: self, action: "panFromLeftEdgeAction:")
panLeftEdgeGesture.edges = .Left
view.addGestureRecognizer(panLeftEdgeGesture)
手势触发:
//Gestures visible when view is 'Today'
func panLeftEdge_toLifeList(sender: UIScreenEdgePanGestureRecognizer)
dispatch_async(dispatch_get_main_queue()) () -> Void in
self.performSegueWithIdentifier("segueToLifeLists", sender: nil)
func panFromRightEdgeAction(sender: UIScreenEdgePanGestureRecognizer)
//self.tomHdrBtnPress(tomorrowHdr)
tomorrowHdr.sendActionsForControlEvents(UIControlEvents.TouchUpInside)
//Gesture added when viewing 'Tomorrow' list
func panFromLeftEdgeAction(sender: UIScreenEdgePanGestureRecognizer)
//self.todayHdrBtnPress(todayHdr)
todayHdr.sendActionsForControlEvents(UIControlEvents.TouchUpInside)
@IBAction func todayHdrBtnPress(sender: AnyObject)
UIView.animateWithDuration(0.75, animations:
//Header changes
self.hdrBox.backgroundColor = UIColor(red: 46/255.0, green: 173/255.0, blue: 11/255.0, alpha: 1.0)
self.footer_RightArrow.hidden = false
self.footer_RightBtn.hidden = false
, completion: nil
)
curMainList = "TodayTask"
currentListEntity = curMainList
viewDidLoad()
@IBAction func tomHdrBtnPress(sender: AnyObject)
UIView.animateWithDuration(0.75, animations:
//Header changes
self.hdrBox.backgroundColor = UIColor(red: 49/255.0, green: 82/255.0, blue: 171/255.0, alpha: 1.0)
self.footer_LeftBtn.addTarget(self, action: "LeftFooterBtnPress", forControlEvents: UIControlEvents.TouchUpInside)
, completion: nil
)
curMainList = "TomTask"
currentListEntity = curMainList
viewDidLoad()
【问题讨论】:
您不应该“以编程方式伪造按钮按下”。而且您不应该手动调用生命周期事件。您从根本上以多种方式完全错误地解决了这个问题。 你实际上想实际上做什么?viewDidLoad
中有什么需要重复调用??
@nhgrif 从用户的角度来看,pan 正在触发一个新页面。它实际上是标题标题和颜色发生变化的同一个 VC。但对用户来说,他们会觉得他们正在滑动以切换页面。什么都不应该重复运行。看看它是如何更新列表变量的?当 viewDidLoad 运行时,它会注意到变量发生了变化,并将加载不同值的表头和表。
该逻辑不应该在viewDidLoad
中。 viewDidLoad
也许调用一个包含该逻辑的方法,但您应该永远手动调用生命周期事件。 而且您还应该永远像这样以编程方式点击按钮(不进行自动化 UI 测试)。
@nhgrif 我可以猜想像 viewDidLoad 这样的生命周期事件不应该被调用,只是超出了原则。但实际上,我正在更改页面。页眉更改,表格更改,页脚更改。那么为什么我不希望我的 viewDidLoad 再次运行并改变它呢?以编程方式点击按钮有什么危险?
【参考方案1】:
问题在于平移手势是连续手势(意味着当您移动手指时,处理程序会被重复调用)。对于平移手势,使用gesture.state
或.Began
调用一次,在用户手指移动时使用state
或.Changed
重复调用一次,最后使用.Ended
或.Cancelled
的state
调用当用户停止手势时。
因此,您通常不会从连续手势触发animateWithDuration
。您只需根据 gesture.translationInView()
或您拥有的内容更新状态。只需立即更新视图以反映更新后的平移,它会被如此频繁地调用,最终渲染出一些感觉像动画的东西,但它实际上只是与手势识别器的处理程序作为用户接收的连续更新流相关的一系列更新他们的手势进步了。
您唯一会在连续手势中制作动画的时间是在 .Ended
或 .Cancelled
上完成动画。例如,也许用户将手指拖到一半,所以在.Changed
上,您只需立即更新视图而不使用任何动画,但是当他们抬起手指时(即手势处理程序接收.Ended
),您可能会为完成设置动画视图的最终状态。
归根结底,手势识别器中的处理是一种非常不同的动画机制,它可能由按钮产生(您在其中调用一次 animateWithDuration
方法来启动 UIKit 然后为您处理的动画)。最好不要将这两种非常不同的更新/动画 UI 的方式混为一谈。
您还在您的一个 pan 处理程序中执行 segue。如果您想在平移时以交互方式执行 segue,您应该参考 WWDC 2013 视频 Custom Transitions Using View Controllers,它展示了如何将动画控制器(决定动画的性质)与交互控制器(将动画控制器的手势进度)。但在这种模式中,您只执行一次 segue,并且仅更新手势中的UIPercentDrivenInteractiveTransition
,这会将转换的进度与用户的手指联系起来。
`
【讨论】:
谢谢!我的新函数如下所示: func panFromLeftEdgeAction(sender: UIScreenEdgePanGestureRecognizer) switch (sender.state) case UIGestureRecognizerState.Ended:以上是关于Pan Segue 调用 viewDidLoad 循环的主要内容,如果未能解决你的问题,请参考以下文章
viewDidLoad 实际上是在每次有 segue 转换时调用的
为什么在viewDidLoad中调用presentingViewController返回nil?
为什么在viewDidLoad中调用presentingViewController返回nil?
如何在 [self dismissModalViewControllerAnimated:YES] 之后调用 viewDidLoad;