【问题标题】:willRemoveSubview does not remove subview when called from a class outside the superView's ViewController?从 superView 的 ViewController 之外的类调用时 willRemoveSubview 不会删除子视图?
【发布时间】:2018-07-06 23:01:45
【问题描述】:

当我使用 Objective-C 和 UIView willRemoveSubview 方法以编程方式删除子视图时,我不了解我在 iOS 应用程序中观察到的不同行为。

方法一
在我的 ViewController 类中,我添加了一个 UIVisualEffectView 作为 ViewController 视图的子视图:

- (void)blurView {
    UIBlurEffect *blurEffect = [UIBlurEffect effectWithStyle:UIBlurEffectStyleDark];
    blurEffectView = [[UIVisualEffectView alloc] initWithEffect:blurEffect];
    blurEffectView.frame = self.view.bounds;
    blurEffectView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

    [self.view insertSubview:blurEffectView atIndex:5];
}

此方法被调用以响应用户的某些操作。

blurEffectView 本身是我在实现中定义的 ViewController 类的私有变量,它将指向新的子视图

@interface MyViewController ()

@end
@implementation
UIVisualEffectView *blurEffectView;  
...

我有一个点击手势识别器,它通过删除添加的子视图调用另一种方法来“取消模糊”

- (void) tapped {
    blurEffectView.hidden = true;
    [self.view willRemoveSubview:blurEffectView];
}

此方法效果很好,模糊显示并覆盖了视图。当点击发生时,模糊消失,一切看起来都很好。

方法二
接下来我尝试了一些更复杂的东西,现在它的行为有所不同。我创建了一个小的 Objective-C 类来将模糊/取消模糊功能包装在一个单独的实用程序对象中,我可以更轻松地重用它。

基本上,MyViewController 现在有一个新的私有变量来引用我的新类 ViewBlurrer,它只是扩展了 NSObject。 ViewBlurrer 现在封装了对 UIVisualEffectView *blurEffectView 的引用,并且它的接口具有用于模糊和取消模糊的公共方法。
所以层次结构类似于 MyViewController -> ViewBlurrer -> UIVisualEffectView

ViewBlurrer 还维护对 MyViewController.view 的引用,它在 blur 和 unblur 方法中使用。将此指针称为 parentView。

这与模糊的行为完全相同,它正确地添加了覆盖 ViewController 视图的模糊效果。

我观察到的不同之处在于,现在我无法隐藏和删除 blurEffectView,因为它位于这个实用程序类 ViewBlurrer 中。我可以使它被删除的唯一方法是在 ViewBlurrer.unblur 方法中使用任意标签号查找 UIVisualEffectView :

-(void)unblurView {
    UIView *theSubView = [self.parentView viewWithTag:66];
    theSubView.hidden = YES;
    [self.parentView willRemoveSubview:theSubView];
}

我的问题是为什么我不能打电话 [self.parentView willRemoveSubview:blurEffectView],但我必须通过标签查找是不是我插入到 parentView 的指向 blurEffectView 的指针仍然与方法 1 中的原始方法相同?

【问题讨论】:

  • 仅供参考 - willRemoveSubview 不会删除任何内容。你不应该打电话给willRemoveSubview。当视图即将被移除时,框架会调用它。您的自定义视图可以覆盖 willRemoveSubview,如果它希望收到即将从中删除某些内容的通知。
  • 调用 blurView removeFromSuperview

标签: ios objective-c iphone uiview uiviewcontroller


【解决方案1】:

正如您的问题的 cmets 中已经提到的,您不应该自己致电 willRemoveSubview。当您从视图层次结构中删除子视图时,它会自动调用(由系统)。来自willRemoveSubview的文档:

当子视图接收到 removeFromSuperview() 消息或子视图由于使用 addSubview(_:) 添加到另一个视图而从视图中删除时调用此方法。

因此你应该写:

- (void) tapped {
    blurEffectView.hidden = true;
    [blurEffectView removeFromSuperview];
}

或更短:

- (void) tapped {
    [blurEffectView removeFromSuperview];
}

【讨论】:

  • 我已经尝试过[blurEffectView removeFromSuperview];blurEffectView.hidden = true; [blurEffectView removeFromSuperview]; 但我似乎遗漏了一些东西,模糊的 UIVisualEffectView 仍然存在,没有隐藏,我可以在 Xcode 的“调试视图层次结构”窗口中看到它,是否需要在父视图控制器中的 removeFromSuperview 之后调用一些东西?
  • 在调试器中,我注意到 blurEffectView._viewDelegate 为空,创建 blurEffectView 时一定缺少与 ViewController 的链接?
  • 您是否添加了多个蓝视图?您的方法blurView 每次调用时都会添加一个模糊视图,并由用户事件触发。
  • 我认为这正是发生的事情,那是我在添加模糊视图的代码中的错误,在两个地方再次被调用。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多