静态 UIView 添加到 superview 后变为 nil
Static UIView becomes nil after added to superview
我有一个静态视图,用于在 UI 中显示为加载指示器。
static UIView *loadingView;
在我的 class Loading.m
中,我在 show()
被调用时将 loadingView
添加到我的容器中
+ (void)show {
if (loadingView == nil) {
UIWindow *containerView = UIApplication.sharedApplication.keyWindow;
loadingView = [UIView alloc] init];
[containerView addSubview:loadingView];
}
}
当调用 dismiss()
时,我将其从 superview 中删除:
+ (void)dismiss {
if (loadingView != nil) {
[loadingView removeFromSuperview];
loadingView = nil;
}
}
我发现 loadingView
添加到 containerView
后将永远为零,所以我会继续添加更多 loadingView
到我的 containerView
并且它不会被删除当调用 dismiss()
时。当我打印 UIApplication.sharedApplication.keyWindow
时,它显示 UIView 已添加到堆栈中。在 show()
完成后,loadingView
似乎失去了对 containerView
的引用。
什么给了?
您是如何检测到“loadingView”为零的?
请通过代码或在调试器中使用“po”进行验证。
如果您刚刚在变量列表中看到“nil”值,有时是 Xcode 调试器错误。
当变量列表中的变量为“nil”,但它不是“nil”时。
的确,这个问题可能会产生更深层次的后果:
- 您使用静态
UIView
。如果您的应用程序在 ARC 下,系统会自动决定对象在不可见时是否可以存活。因此,在对可见对象使用 static
声明之前应该三思。
- 如果您的对象确实响应
removeFromSuperview
之类的消息并且 .superview
不是 nil
- 这意味着该对象肯定不是 nil
。如上所述,它是调试器的错误(发生在 运行 设备上的应用程序在 XCode 下)。
这个 post 的目标 - 注意 UIView
对象层次结构,其中父对象具有 .subviews
非空 NSArray 属性,表示所有对象, 添加为子视图。它们将由 ARC 自动释放,然后从堆栈中移除 VC。因此,在 static UIView *
声明的情况下,ARC 将保持加载其所有父元素,直到它被手动从 superview 中删除。换句话说,static UIView *
是一种潜在的危险构造,可能导致内存泄漏或其他冲突。例如,控制加载指示器的更好方法是检查当前顶部的最后一个子视图元素 VC:
if (self.view.subviews && [self.view.subviews.lastObject isKindOfClass: [loadview class]]) {
[self.view.subviews.lastObject removeFromSuperview];
}
在这种情况下,您没有调用 nil
对象方法的风险(应用程序也会崩溃)和手动生命周期控制的麻烦。
我有一个静态视图,用于在 UI 中显示为加载指示器。
static UIView *loadingView;
在我的 class Loading.m
中,我在 show()
被调用时将 loadingView
添加到我的容器中
+ (void)show {
if (loadingView == nil) {
UIWindow *containerView = UIApplication.sharedApplication.keyWindow;
loadingView = [UIView alloc] init];
[containerView addSubview:loadingView];
}
}
当调用 dismiss()
时,我将其从 superview 中删除:
+ (void)dismiss {
if (loadingView != nil) {
[loadingView removeFromSuperview];
loadingView = nil;
}
}
我发现 loadingView
添加到 containerView
后将永远为零,所以我会继续添加更多 loadingView
到我的 containerView
并且它不会被删除当调用 dismiss()
时。当我打印 UIApplication.sharedApplication.keyWindow
时,它显示 UIView 已添加到堆栈中。在 show()
完成后,loadingView
似乎失去了对 containerView
的引用。
什么给了?
您是如何检测到“loadingView”为零的?
请通过代码或在调试器中使用“po”进行验证。
如果您刚刚在变量列表中看到“nil”值,有时是 Xcode 调试器错误。 当变量列表中的变量为“nil”,但它不是“nil”时。
的确,这个问题可能会产生更深层次的后果:
- 您使用静态
UIView
。如果您的应用程序在 ARC 下,系统会自动决定对象在不可见时是否可以存活。因此,在对可见对象使用static
声明之前应该三思。 - 如果您的对象确实响应
removeFromSuperview
之类的消息并且.superview
不是nil
- 这意味着该对象肯定不是nil
。如上所述,它是调试器的错误(发生在 运行 设备上的应用程序在 XCode 下)。
这个 post 的目标 - 注意 UIView
对象层次结构,其中父对象具有 .subviews
非空 NSArray 属性,表示所有对象, 添加为子视图。它们将由 ARC 自动释放,然后从堆栈中移除 VC。因此,在 static UIView *
声明的情况下,ARC 将保持加载其所有父元素,直到它被手动从 superview 中删除。换句话说,static UIView *
是一种潜在的危险构造,可能导致内存泄漏或其他冲突。例如,控制加载指示器的更好方法是检查当前顶部的最后一个子视图元素 VC:
if (self.view.subviews && [self.view.subviews.lastObject isKindOfClass: [loadview class]]) {
[self.view.subviews.lastObject removeFromSuperview];
}
在这种情况下,您没有调用 nil
对象方法的风险(应用程序也会崩溃)和手动生命周期控制的麻烦。