2016-08-24 3 views
0

HeaderViewというxibからカスタムUIViewを作成しています。このHeaderViewにUIButtonがあり、ボタンタップで、HeaderViewが追加されているViewControllerでブロックが呼び出されます。ここで私のHeaderViewのコードです。目的CブロックがNilになる

ヘッダーファイルのコード

@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であるため、呼び出されないという問題があります。

答えて

2

ですから、ViewControllerのviewDidLoad(setupSubviewsメソッド経由)にブロックを割り当てていることが起こります。私はあなたがプログラムでHeaderViewをインスタンス化していることがわかります。したがって、ブロックを割り当てるときに、実際にメッセージをインスタンスに送信しています。

ただし、HeaderViewのsetupメソッド内でloadNibNamedを呼び出して別のインスタンスを膨張させることもできます。 その HeaderViewにはブロックがありません。そのブロックはUIに表示されます。 HeaderViewのcontentViewの中に別のHeaderViewがあります。

実際の/画面上 HeaderViewインスタンスのハンドラプロパティはnilなので、ブロックを起動しようとするとnilも使用されます。

何が起きているかを調べる最も良い方法は、HeaderViewに入り、ブレークポイントをawakeFromNibに設定し、別のブレークポイントをsetupに設定することです。セットアップが最初に呼び出されることがわかります。 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]; 
+0

おかげで非常によく説明しました。 – Madu