从superView的ViewController外部的类调用时,willRemoveSubview不会删除子视图吗?

时间:2018-01-27 22:18:23

标签: ios objective-c iphone uiview uiviewcontroller

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

方法1
在我的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;  
...

我有一个Tap Gesture识别器,通过删除添加的子视图调用另一种“unblur”方法

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

此方法工作正常,模糊显示并覆盖视图。当点击发生时,模糊消失,一切看起来都没问题。

方法2
接下来我尝试了一些更复杂的东西,现在它的行为有所不同。我创建了一个小的Objective-C类来将blur / unblur函数包装在一个单独的实用程序对象中,我可以更容易地重用它。

基本上MyViewController现在有一个新的私有变量来引用我的新类ViewBlurrer,它只扩展了NSObject。 ViewBlurrer现在封装了对UIVisualEffectView * blurEffectView的引用,它的界面有模糊和unblur的公共方法。
所以层次结构是这样的 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中的原始方法吗?

1 个答案:

答案 0 :(得分:1)

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

  

当子视图收到removeFromSuperview()消息或从视图中删除子视图时,会调用此方法,因为它已使用addSubview(_:)添加到另一个视图中。

因此你应该写:

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

或更短:

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