- r - 以节省内存的方式增长 data.frame
- ruby-on-rails - ruby/ruby on rails 内存泄漏检测
- android - 无法解析导入android.support.v7.app
- UNIX 域套接字与共享内存(映射文件)
在调查内存泄漏时,我发现了一个与在过渡动画 block 中调用 setRootViewController:
技术相关的问题:
[UIView transitionWithView:self.window
duration:0.5
options:UIViewAnimationOptionTransitionFlipFromLeft
animations:^{ self.window.rootViewController = newController; }
completion:nil];
如果旧的 View Controller (被替换的那个)当前呈现另一个 View Controller ,那么上面的代码不会从 View 层次结构中删除呈现的 View 。
也就是这个操作序列...
transitionWithView:
使 Z 成为新的 Root View Controller ...对用户来说看起来没问题,但是调试 View 层次结构工具会显示 Y 的 View 仍然在 Z 的 View 后面,在 UITransitionView
中。即经过上述三步后, View 层级为:
我怀疑这是个问题,因为在转换时,X 的 View 实际上并不是 View 层次结构的一部分。
如果我在 transitionWithView:
之前立即向 X 发送 dismissViewControllerAnimated:NO
,则生成的 View 层次结构为:
如果我将 dismissViewControllerAnimated:
(是或否)发送到 X,然后在 completion:
block 中执行转换,则 View 层次结构是正确的。不幸的是,这会干扰动画。如果动画解雇,那会浪费时间;如果没有动画,它看起来就坏了。
我正在尝试一些其他方法(例如,制作一个新的容器 View Controller 类作为我的 Root View Controller )但没有找到任何可行的方法。我会随时更新这个问题。
最终目标是直接从呈现的 View 过渡到新的 Root View Controller ,而不会留下杂散的 View 层次结构。
最佳答案
我最近遇到了类似的问题。我不得不从窗口中手动删除那个 UITransitionView
来解决这个问题,然后在之前的 Root View Controller 上调用 dismiss 以确保它被释放。
修复不是很好,但除非您在发布问题后找到更好的方法,否则这是我发现的唯一可行的方法! viewController
只是您原始问题中的 newController
。
UIViewController *previousRootViewController = self.window.rootViewController;
self.window.rootViewController = viewController;
// Nasty hack to fix http://stackoverflow.com/questions/26763020/leaking-views-when-changing-rootviewcontroller-inside-transitionwithview
// The presenting view controllers view doesn't get removed from the window as its currently transistioning and presenting a view controller
for (UIView *subview in self.window.subviews) {
if ([subview isKindOfClass:NSClassFromString(@"UITransitionView")]) {
[subview removeFromSuperview];
}
}
// Allow the view controller to be deallocated
[previousRootViewController dismissViewControllerAnimated:NO completion:^{
// Remove the root view in case its still showing
[previousRootViewController.view removeFromSuperview];
}];
我希望这也能帮助您解决问题,这绝对是个麻烦!
Swift 3.0
(查看其他 Swift 版本的编辑历史)
为了更好地实现作为 UIWindow
的扩展,允许传入可选的转换。
extension UIWindow {
/// Fix for http://stackoverflow.com/a/27153956/849645
func set(rootViewController newRootViewController: UIViewController, withTransition transition: CATransition? = nil) {
let previousViewController = rootViewController
if let transition = transition {
// Add the transition
layer.add(transition, forKey: kCATransition)
}
rootViewController = newRootViewController
// Update status bar appearance using the new view controllers appearance - animate if needed
if UIView.areAnimationsEnabled {
UIView.animate(withDuration: CATransaction.animationDuration()) {
newRootViewController.setNeedsStatusBarAppearanceUpdate()
}
} else {
newRootViewController.setNeedsStatusBarAppearanceUpdate()
}
if #available(iOS 13.0, *) {
// In iOS 13 we don't want to remove the transition view as it'll create a blank screen
} else {
// The presenting view controllers view doesn't get removed from the window as its currently transistioning and presenting a view controller
if let transitionViewClass = NSClassFromString("UITransitionView") {
for subview in subviews where subview.isKind(of: transitionViewClass) {
subview.removeFromSuperview()
}
}
}
if let previousViewController = previousViewController {
// Allow the view controller to be deallocated
previousViewController.dismiss(animated: false) {
// Remove the root view in case its still showing
previousViewController.view.removeFromSuperview()
}
}
}
}
用法:
window.set(rootViewController: viewController)
或者
let transition = CATransition()
transition.type = kCATransitionFade
window.set(rootViewController: viewController, withTransition: transition)
关于ios - 在 transitionWithView 中更改 rootViewController 时泄漏 View ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/26763020/
我正在使用以下代码尝试翻转 UIView。这是一张扑克牌。有一个容器 View ,有两个 child ,前后。我在这里读过类似的问题,这应该是正确的方法,但实际的翻转本身并没有被执行。 我打算为此设置
我正在尝试编写一个应用程序,它使用自定义动画在 UINavigationController 的 View 堆栈中的 View Controller 之间进行转换。 现在,我正在添加同一 View 的
我有一个占位符 UIImageView(从 .xib 加载),我想加载一张卡片背面的图片,然后翻转到正面图像。 [cardView setImage:backCardImage]; [UIView t
我有一个首先显示登录屏幕的应用程序。用户登录后,将执行以下代码: [UIView transitionWithView:self.view.window
我查看 Didload 我有如下设置: [[self layer] setCornerRadius:30.0f]; NSString *imgFilepath = [[NSBundle
我已经尝试了以下几种变体,但都无济于事。我想要的是一个显示一些东西的向下 curl 过渡,然后是一个相反的向上 curl 过渡。有透明度,所以效果是一个清晰的东西在 View 上滚动。这是在上卷和下卷
这是测试项目中主视图 Controller 的 viewDidLoad: - (void)viewDidLoad { [ super viewDidLoad]; UIView *containerVi
我正在尝试在我的应用程序中为 root-view-controller-change 设置动画。交换 View Controller 后,我立即加载第二个 Controller 所需的数据。在加载数据
有人可以帮助我了解 swift 中 transitionWithView 的语法吗?在 objective-c 中我会这样使用它: [UIView transitionWithView:[ self
我的主视图有一个 subview ,其中有一个 UIActivityIndicatorView。最初,此 subview 的 hidden 属性设置为 YES。 我希望这个 subview 淡入屏
我在使用 transitionWithView 和 animateWithDuration 时遇到问题。我的一个 animateWithDuration block 没有过渡,这是一个突然的变化,并且
我想在动画完成后运行一段代码,但编译器显示以下错误:“不兼容的 block 指针类型将‘void (^)(void)’发送到‘void (^)(BOOL) 类型的参数)'" 这是我的代码,我不确定我做
使用下面的代码,我已经成功地使我的 UIImageView 在其图像中淡出。 [UIView transitionWithView:myCell.myImageView duration:2.0 op
我几乎可以用 AnimationWithDuration 做 TransistionWithView 能做的所有事情。我真的不确定什么时候只有一个用例超过另一个用例。 在 AnimateWithDur
我正在尝试制作一个简单的 Simon 游戏(闪烁的颜色序列越来越多,用户必须尝试重复该序列)。我要解决的方法是使用 4 个带有 8 个图像的 UIView。所以有一个 UIView 用于红色、蓝色、绿
我正在尝试在两个 subview (view1 和 view2)之间创建一个过渡。当按下按钮时,我希望 view1(正面)翻转并显示 view2(背面)。我已经尝试过 transitionFromVi
我目前有一个 UIView,上面有 UILabel。 这些 UILabel 有圆角。 我按下一个按钮,然后使用 UIView transitionWithView 方法以编程方式删除所有这些标签。 但
我已经建立了一个简单的项目来试验 UIView transitionWithView: 动画片段并遇到了相当奇怪的行为。 动画只对标签的文本起作用(在 View 旋转一半时改变它),但是颜色变化发生在
我想创建一些在它们之间有延迟的动画,所以我决定使用 UIView.animateKeyframesWithDuration:delay:options:animations:completion:。
我正在尝试使用以下代码让我的 UIImageView (self.posterImageview) 在一组带有动画的 UIImage 中循环: func animatePoster (imageAr
我是一名优秀的程序员,十分优秀!