首页 > 解决方案 > 静态 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已经失去了对它的引用。containerViewshow()

是什么赋予了?

标签: iosobjective-c

解决方案


事实上,这个问题可能会产生更深层次的后果:

  • 你使用静态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对象方法(应用程序也崩溃)和手动生命周期控制的麻烦。


推荐阅读