繁体   English   中英

目标C块变为无

[英]Objective C block becomes Nil

我正在从xib创建一个名为HeaderView的自定义UIView。 我在此HeaderView中有一个UIButton,在单击按钮时,我希望在其中添加HeaderView的ViewController上调用一个块。 这是我的HeaderView的代码。

头文件代码

@interface HeaderView : UIView

- (instancetype)initWithFrame:(CGRect)frame;

@property (copy) void(^seeAllHandler)();

@end

实施文件代码

@interface HeaderView()

@property (weak, nonatomic) IBOutlet UILabel *titleLabel;
@property (weak, nonatomic) IBOutlet UIButton *seeAllButton;
@property (nonatomic, strong) UIView *contentView;

@end

@implementation HeaderView


- (instancetype)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        [self setup];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)coder
{
    self = [super initWithCoder:coder];
    if (self) {

    }
    return self;
}

- (void)awakeFromNib
{
    [self.seeAllButton setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
    [self.seeAllButton setTitle:@"SEE ALL")  forState:UIControlStateNormal];
    [self.titleLabel setText:@"My Label")];

}

#pragma mark - Private methods

- (void)setup
{
    //Setup view from the xib file.
    self.contentView = [[[NSBundle mainBundle] loadNibNamed:NSStringFromClass(self.class) owner:self options:nil] firstObject];
    [self.contentView setFrame:self.bounds];
    [self addSubview:self.contentView];
    self.contentView.backgroundColor = [UIColor ccNordeaPink];
    self.contentView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
    self.clipsToBounds = YES;
}

- (IBAction)sellAllTapped:(UIButton *)sender {
    if(self.seeAllHandler != nil){
        self.seeAllHandler();
    }

}

@end

这是我的ViewController viewDidLoad方法。

@interface ViewController () <UIScrollViewDelegate, UICollectionViewDataSource, UICollectionViewDelegate>

@property (nonatomic, strong) HeaderView *headerView;

@end



- (void)viewDidLoad
{
    [super viewDidLoad];
    [self setupSubviews];
    [self setupConstraints];

}

- (void)setupSubviews
{

    self.headerView = [[HeaderView alloc] init ];
    self.headerView.translatesAutoresizingMaskIntoConstraints = NO;

    self.headerView.seeAllHandler = ^{
        DDLogDebug(@"See all Tapped");
    };

[self.view addSubView: self.headerView];


}

问题在于,当点击按钮时,分配的块为nil,因此不会调用它。

因此,正在发生的事情是您正在通过ViewController的viewDidLoad(通过setupSubviews方法)分配该块。 我可以看到您正在以编程方式实例化HeaderView。 因此,在分配块时,实际上是在向实例发送消息。

但是,您还通过在loadNibNamedsetup方法中调用loadNibNamed夸大另一个实例。 HeaderView没有你的块,就是这样被在UI中所示的一个。 您已经在HeaderView的contentView中获得了另一个HeaderView。

因此, 实际的/屏幕上的 HeaderView实例的handler属性为nil,因此当它尝试向您发射该块时,它也使用nil。

最好的方法是进入HeaderView并在awakeFromNib设置一个断点,并在setupsetup另一个断点。 您会看到该设置被首先调用。 如果您在lldb中输入po self ,则将是当前实例的地址。 接下来发生的事情是awakeFromNib被调用,并在该处到达断点。 如果再次进行po self ,则会看到一个不同的地址。 一个不同的实例! 这是您在UI中看到的那个。 而且它没有设置处理程序!

如果要保留此方法来加载视图层次结构,则一个简单的修复方法是从ViewController中的nib实例化HeaderView。

因此,您无需执行self.headerView = [[HeaderView alloc] init] ,而是这样做:

self.headerView = [[[NSBundle mainBundle] loadNibNamed:@"HeaderView" owner:self options:nil] firstObject];

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM