【问题标题】:How to notify superview of subview removal如何通知子视图删除的超级视图
【发布时间】:2018-11-14 18:38:09
【问题描述】:

我向 UIViewController 添加了一个自定义 UIView,在视图中的一些代码之后,我想从 UIViewController 中删除此视图,但我不确定如何通知 UIViewController UIView 的删除。

我正在使用这个方法从 UIView 中退出

-(void)exit{
    [self removeFromSuperview];
}

我需要设置一个监听器吗?任何帮助表示赞赏


我发布了详细的解决方案。感谢 Rage、Bill L 和 FreeNickname

【问题讨论】:

  • 如果一个视图将自己从superView中删除,如果superView删除它的子视图会很容易。这样您就可以更好地控制自己的工作。
  • 我不知道该怎么做。就我而言,我正在根据子视图中的条件删除子视图。我相信在这种情况下,我需要一个监听器或一个 NSNotification 来自我的超级视图中的子视图的条件

标签: ios objective-c uiview uiviewcontroller


【解决方案1】:

由于不方便将代码写成注释,所以我将它写成答案。这个答案说明了@Rage 在他的回答中提出的建议。

首先,您为您的CustomView 创建一个@protocol 并为其添加一个delegate。您声明delegate 应符合此协议。然后在您的 ViewController 中实现您的协议并将 ViewController 设置为您的 CustomView 的委托。

像这样:

CustomView.h:

@protocol CustomViewDelegate<NSObject>

//You can also declare it as @optional. In this case your delegate can
//ignore this method. And when you call it, you have to check, whether 
//your delegate implements it or not.
-(void)viewWasRemoved:(UIView *)view

@end

@interface CustomView: UIView

@property (nonatomic, weak) id<CustomViewDelegate> delegate;

@end

CustomView.m:

@implementation CustomView

-(void)exit {
    [self removeFromSuperview];
    //if your method is NOT @optional:
    [self.delegate  viewWasRemoved:self];

    //if it IS @optional:
    if ([self.delegate respondsToSelector:@selector(viewWasRemoved:)]) {
        [self.delegate viewWasRemoved:self];
    }
}

@end

ViewController.m:

#import "CustomView.h"

@interface ViewController()<CustomViewDelegate>

@end

@implementation ViewController

-(void)someMethod {
    self.customView.delegate = self;
}

-(void)viewWasRemoved:(UIView *)view {
    //Whatever
}

@end

【讨论】:

  • 这个答案真的为我清除了协议。非常有效和有用!谢谢!
【解决方案2】:

使用委托。向您的自定义视图添加一个协议,该协议实现一种通知删除子视图的方法。 在添加自定义视图时使视图控制器成为委托。在您的自定义类中,在 [self removeFromSuperview]; 之前调用委托方法

【讨论】:

    【解决方案3】:

    使用名为viewWasRemoved: 或类似的方法为其设置一个委托。将视图的委托设置为您要通知的 ViewController,然后在您的退出方法中调用 [self.delegate viewWasRemoved:self];,这将启动您的 ViewController 中的 viewWasRemoved: 方法,您可以在其中执行您需要做的任何相关工作一旦视图被删除。

    【讨论】:

      【解决方案4】:

      我会发布一个详细的解决方案,以防它帮助任何人,或者如果有人可以提供任何指示。感谢 Rage、Bill L 和 FreeNickname:

      答案是使用委托

      首先我将超级视图导入到子视图的 .h 中:

      #import "ViewController.h"
      

      然后我将代理 id 添加到同一个文件中:

      @property (weak) id delegate;
      

      然后在superview中初始化自定义UIView的时候,我设置了delegate:

       CustomView *view = [[CustomView alloc]initWithFrame:frame];
       view.delegate = self;
      

      我在superview中添加了这个方法用于回调:

      - (void) viewWasRemoved: (UIView *) view{
          NSLog(@"removed");
      }
      

      然后最后调用我的subView中的方法:

      -(void)exit{
          [self.delegate viewWasRemoved:self];
          [self removeFromSuperview];
      }
      

      【讨论】:

      • 永远不要将retain 用于代表(顺便说一句,为什么retain,而不是strong?ARC 已经存在了一段时间了)。仅使用weak。因为您的委托很可能持有对您的对象的强引用。就像 ViewController 持有对您的视图的强引用。如果视图还持有对 VC 的强引用,它会创建一个保留周期并导致内存泄漏。
      • 另外,如果我理解正确,您将#import "ViewController.h" 添加到子视图头文件中。为什么?
      • 好的,谢谢,我改用weak,编辑以修复我的错误。我需要导入ViewController.h才能引用方法[self.delegate viewWasRemoved:self]
      • 这不是你的做法 :) 如果你想在另一个 ViewController 中使用你的自定义视图怎么办?您不能将要使用 CustomView 的每个文件的标题导入到 CustomView 的标题中。它是使用协议完成的(正如 Rage 建议的那样)。把代码写成注释不方便,我一会儿写成答案。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-02-23
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多