【问题标题】:Static UIView becomes nil after added to superview静态 UIView 添加到 superview 后变为 nil
【发布时间】:2021-05-10 08:44:08
【问题描述】:

我有一个静态视图,用于在 UI 中显示为加载指示器。

static UIView *loadingView;

在我的班级Loading.m 中,当show() 被调用时,我将loadingView 添加到我的容器中

+ (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在添加到containerView之后总是为零,所以我会继续在我的containerView中添加更多loadingView,并且在调用dismiss()时它不会被删除。当我打印 UIApplication.sharedApplication.keyWindow 时,它显示 UIView 已添加到堆栈中。在show() 完成后,loadingView 似乎失去了对containerView 的引用。

什么给了?

【问题讨论】:

    标签: ios objective-c


    【解决方案1】:

    确实,这个问题可能会产生更深层次的影响:

    • 您使用静态UIView。如果您的应用程序在 ARC 下,系统会自动决定对象在不可见时是否可以存活。因此,在对可见对象使用 static 声明之前,您应该三思而后行。
    • 如果您的对象确实响应removeFromSuperview.superview 之类的消息不是nil - 这意味着该对象肯定不是nil。如上所述,这是调试器的错误(在 XCode 下在设备上运行应用程序时发生)。

    这篇文章的目标 - 关注UIView对象层次结构,其中父对象具有.subviews非空NSArray属性,表示所有对象,作为子视图添加。它们将由 ARC 自动释放,然后从堆栈 VC 中删除。因此,在static UIView * 声明的情况下,ARC 将继续加载其所有父元素,直到将其从超级视图中手动删除。换句话说,static UIView * 是潜在危险的构造,可能导致内存泄漏或其他冲突。例如,控制加载指示器的更好方法是检查当前顶部 VC 的最后一个子视图元素:

    if (self.view.subviews && [self.view.subviews.lastObject isKindOfClass: [loadview class]]) {
        [self.view.subviews.lastObject removeFromSuperview];
    }
    

    在这种情况下,您无需担心调用 nil 对象方法(应用程序也会崩溃)和手动生命周期控制的麻烦。

    【讨论】:

      【解决方案2】:

      您是如何检测到“loadingView”为 nil 的?

      请通过代码或在调试器中使用“po”进行验证。

      如果您刚刚在变量列表中看到“nil”值,有时是 Xcode 调试器错误。 当变量列表中的变量为“nil”,但它不是“nil”时。

      【讨论】:

      • 你是对的,原来是调试器的bug,当我po它时它显示它不是nil,这解决了我的问题,非常感谢
      猜你喜欢
      • 2020-04-28
      • 2015-05-28
      • 1970-01-01
      • 2013-07-15
      • 1970-01-01
      • 2015-06-14
      • 1970-01-01
      • 1970-01-01
      • 2014-07-15
      相关资源
      最近更新 更多