https://dl.dropboxusercontent.com/u/39330138/Bug_Demo1.mov
有两个视图控制器,第一个是非模糊的,不太重要.单击加号按钮时,应用程序将切换到新控制器(无动画),在prepareForSegue()中,我使用UIGraphicsBeginImageContext和UIGraphicsGetImageFromCurrentImageContext从当前视图捕获UIImage并将其传递给下一个.
当新视图出现时,我使用UIVisualEffectView创建模糊视图,并将其作为子视图添加到“背景”的图像视图中.然后,使用UIView动画和springWithDamping在屏幕上对2个视图和2个按钮进行动画处理,同时对其不透明度进行动画处理,从而产生视图模糊和顶部项目动画的错觉.
顶视图中嵌入了一个UITextField,当点击调用finallyFirstResponder()并使所有重叠(New Session,Tag& Button)视图(包括嵌入在背景图像视图中的视觉效果视图)消失时.
我进入这么多细节的原因是因为我不确定究竟是什么问题.但是,我怀疑它与Xcode 6中的AutoLayout / Size Classes有关.
有谁知道为什么会发生这种情况以及如何解决这个问题?
如果您需要其他信息,请告诉我们.
谢谢!
编辑:
当我单击TextField后记录视图时,所有帧看起来都是一样的.
编辑2:
这是一个演示项目的链接,它将是视频中的所有功能:
https://dl.dropboxusercontent.com/u/39330138/DEMO%20APP.zip
if !returningFromTagView { blurView.alpha = 0 }
我认为你打算在视图出现之前调用它一次,因为我看到你在viewDidAppear(动画:Bool)中将alpha动画设为1.但是,只要系统因任何原因重新评估布局,就会调用viewDidLayoutSubviews(),如果returnsFromTagView为false,则blurView上的alpha将返回0.这就是为什么当您召唤键盘(触发布局重新评估)时,此视图会消失. Xcode还警告你在控制台中制作alpha 0(它会破坏视觉效果直到不透明度返回到1).将上面的代码放在viewDidLoad()方法中,您将看到blurView返回.视图加载时,只需将alpha设置为0.
其他观点的问题看起来有点困难,但罪魁祸首再次是你使用viewDidLayoutSubviews().我想你甚至在你的keyboardNotfication()方法非常彻底地设置框架,将视图放在前面,确保它们没有被隐藏,然后看到为什么视图不出现之后你会感到困惑记录这一切.但是在keyboardNotification()方法完成之后,布局系统再次被触发,我看到你在这里和那里轻推视图的框架:
if returningFromTagView { setX(-titleView.frame.size.width, v: titleView) setX(-tagView.frame.size.width, v: tagView) setX(-(cancelButton.frame.size.width + 20 + nextButton.frame.size.width), v: cancelButton) setX(-nextButton.frame.size.width, v: nextButton) } else { setX(-titleView.frame.size.width, v: titleView) setX(view.frame.size.width, v: tagView) setX(-cancelButton.frame.size.width, v: cancelButton) setX(view.frame.size.width, v: nextButton) }
每次进行布局更改时,您都会在屏幕外移动视图!在召唤键盘后使用Xcode 6的全新Capture View Hierarchy功能查看视图层次结构,暂停程序.它在Debug>查看调试>捕获视图层次结构.这些观点只是隐藏在一边.
为了支持您的过渡动画,我想象您只是在视图出现时尝试执行此操作一次,但无论视图是刚出现还是出现像键盘这样的小变化,都会调用它.我建议您以另一种方式实现这些动画,例如使用视图的变换或使用自动布局约束(尽管故事板中有很多缺少的约束)来制作动画. viewDidLayoutSubviews()实际上是一个在布局系统完成工作后在布局中随处捏造东西的地方.你应该有充分的理由使用它.它有一个很好的功能,它可以覆盖你的自动布局约束,并让你在不使用约束的情况下为这些视图设置动画(因为该方法发生在updateConstraints()和layoutSubviews()方法之后),这就是为什么我们不能将上面的代码放入像viewWillAppear(animated:Bool)这样的方法(因为自动布局约束会在布局后对抗动画),但viewDidLayoutSubviews()只是不支持基本动画的方法.
尽管如此,这里有一些简单的东西让您的应用程序再次运行并让您看到发生了什么:
为NewSessionVC视图控制器创建属性var comingFromSessionView:Bool属性.在SessionVC的prepareForSegue(segue:UIStoryboardSegue,sender:AnyObject?)中,添加nextVC.comingFromSessionView = true
然后将代码块从上面的viewDidLayoutSubviews()更改为:
if returningFromTagView { setX(-titleView.frame.size.width, v: titleView) setX(-tagView.frame.size.width, v: tagView) setX(-(cancelButton.frame.size.width + 20 + nextButton.frame.size.width), v: cancelButton) setX(-nextButton.frame.size.width, v: nextButton) } else if comingFromSessionView { setX(-titleView.frame.size.width, v: titleView) setX(view.frame.size.width, v: tagView) setX(-cancelButton.frame.size.width, v: cancelButton) setX(view.frame.size.width, v: nextButton) }
我们将在viewDidAppear完成后将这些Bools切换为false:
override func viewDidAppear(animated: Bool) { ... if returningFromTagView { ... returningFromTagView = false } else if comingFromSessionView { ... comingFromSessionView = false } }
现在,当召唤键盘时,您的视图就在您离开它们的位置!
上面的代码不是很好.我宁愿远离viewDidLayoutSubviews()来做这些动画.但希望你能看到现在正在发生的事情.您的viewsDidLayoutSubviews()一直在窃听您的观点.