ios - 静态 UIView 添加到 superview 后变为 nil
问题描述
我有一个静态视图,用于在 UI 中显示为加载指示器。
static UIView *loadingView;
在我的课堂上,我在调用时Loading.m
添加loadingView
到我的容器中show()
+ (void)show {
if (loadingView == nil) {
UIWindow *containerView = UIApplication.sharedApplication.keyWindow;
loadingView = [UIView alloc] init];
[containerView addSubview:loadingView];
}
}
当dismiss()
被调用时,我将其从超级视图中删除:
+ (void)dismiss {
if (loadingView != nil) {
[loadingView removeFromSuperview];
loadingView = nil;
}
}
我发现loadingView
添加到 后总是 nil containerView
,所以我会继续添加更多loadingView
到 mycontainerView
中,并且在调用时不会被删除dismiss()
。当我打印UIApplication.sharedApplication.keyWindow
它显示 UIView 已添加到堆栈中。完成后似乎loadingView
已经失去了对它的引用。containerView
show()
是什么赋予了?
解决方案
事实上,这个问题可能会产生更深层次的后果:
- 你使用静态
UIView
的。如果您的应用程序在 ARC 下,系统会自动决定对象在不可见时是否可以存活。static
因此,在对可见对象使用声明之前,您应该三思而后行。 - 如果您的对象确实响应了类似
removeFromSuperview
和.superview
不响应的消息nil
- 这意味着该对象nil
不确定。如上所述,这是调试器的错误(在 XCode 下的设备上运行应用程序时发生)。
这篇文章的目标 - 注意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
对象方法(应用程序也崩溃)和手动生命周期控制的麻烦。
推荐阅读
- java - JUNIT如何检查检索到的自定义对象在assertthat中排序
- reactjs - React lazy/Suspens + React Router 在获取组件之前不会更改路由
- serialization - 用于 DateTime 的 Gson 自定义反序列化器
- esp32 - 我应该为 platformio 中的“ESP32-S”选择哪个 esp32 板?
- c# - 为什么在页面重定向之类的东西中使用@符号?
- json - 我们如何通过 ARM 模板将服务器 ID 传递给服务器端点到存储同步又名文件同步服务
- python - 使用 f solve 在 python 中求解隐式方程
- json - 如何从包含嵌套地图列表的 json 文件中获取和显示数据
- firebase - Flutter/Dart Stream Builder 多个集合 Firebase
- javascript - 如何使用 jQuery/JavaScript 移动/复制跨度值并将其放入另一个 div