标题上写着,我想问为什么以下不起作用,因为它应该是imho。
// ViewController.m
#import "B.h"
...
@implementation ViewController
{
B *bInstance;
}
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])
{
bInstance = [[B alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
[bInstance setBlockCalled:^(NSDictionary *dict) {
NSLog(@"%@", dict[@"key"]);
}];
[self.view addSubview:bInstance];
}
return self;
}
// B.h
#import <UIKit/UIKit.h>
@interface B : UIView
@property (nonatomic, copy) void (^blockCalled)(NSDictionary *);
@end
// B.m
#import "B.h"
#import "A.h"
@implementation B
{
A *aInstance;
void (^blockCalled)(NSDictionary *);
}
@synthesize blockCalled;
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
{
aInstance = [[A alloc] initWithFrame:frame];
[aInstance setBlockCalled:blockCalled];
[self addSubview:aInstance];
}
return self;
}
@end
// A.h
#import <UIKit/UIKit.h>
@interface A : UIView
@property (nonatomic, copy) void (^blockCalled)(NSDictionary *);
@end
// A.m
#import "A.h"
@implementation A
{
void (^blockCalled)(NSDictionary *);
}
@synthesize blockCalled;
- (instancetype)initWithFrame:(CGRect)frame
{
if (self = [super initWithFrame:frame])
{
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button setFrame:CGRectMake(0, 0, 100, 100)];
[button setBackgroundColor:[UIColor redColor]];
[button addTarget:self action:@selector(buttonClicked) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:button];
}
return self;
}
- (void) buttonClicked
{
blockCalled(@{@"key":@"value"});
}
@end
我想要做的是&#39;遍历视图hiearchy&#39;,就我所见,我指定一个具有相同参数的块变量,所以我&#39; d期待它的运作。为什么这是一个错误的想法?
编辑:在发生此问题时添加了更完整的示例。
EDIT2:添加了MCVE,我已经测试过。
在我检查了MCVE后,代码在A.m中的blockCalled(@{@"key":@"value"});
行崩溃,因为blockCalled为零。
更新了问题:我想知道为什么呼叫[aInstance setBlockCalled:blockCalled]
并未设置A中的blockCalled,因为在我看来,它与< / p>
[aInstance setBlockCalled:^(NSDictionary *dict)
{
__strong typeof (self) strongSelf = self;
strongSelf.blockCalled(dict);
}];
答案 0 :(得分:1)
@implementation ViewController
{
B *bInstance;
}
- (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])
{
bInstance = [[B alloc] initWithFrame:CGRectMake(0, 0, 200, 200)];
[bInstance setBlockCalled:^(NSDictionary *dict) {
NSLog(@"%@", dict[@"key"]);
}];
[self.view addSubview:bInstance];
}
在初始化bInstance
时,您还没有设置阻止。这意味着
aInstance = [[A alloc] initWithFrame:frame];
[aInstance setBlockCalled:blockCalled];
在之前调用
[bInstance setBlockCalled:^(NSDictionary *dict) {
NSLog(@"%@", dict[@"key"]);
}];
您应该覆盖B中的块设置器并在A上调用它。
// B.m
-(void)setBlockCalled(void(^)(NSDictionary*))passedBlock{
[a setBlockCalled:passedBlock];
}
答案 1 :(得分:0)
问题(a)中的代码使用了不必要的ivars和@synthesize
语句; (b)此代码段不足以重现您描述的崩溃。
话虽如此,问题中的代码示例提出了两种可能的崩溃源,即:(a)如果A
被释放,代码无法删除观察者; (b)在试图打电话之前,确实应该仔细检查以确保这些街区是非零的。
但是,请考虑以下事项:
// A.h
@interface A : UIView
@property (nonatomic, copy) void (^blockCalled)(NSDictionary *dict);
@end
// A.m
@implementation A
- (instancetype) initWithFrame:(CGRect)frame {
if (self = [super initWithFrame:frame]) {
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(handleNotification:) name:@"kNotification" object:nil];
}
return self;
}
- (void)handleNotification:(NSNotification *)notification {
// never just call `blockCalled`; always check to see if not null
if (self.blockCalled) {
// everything is good, so let's call the block
self.blockCalled(notification.userInfo);
}
}
- (void)dealloc {
// never just `addObserver`; make sure to remove the observer when this is deallocated
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"kNotification" object:nil];
}
@end
// B.h
@interface B : UIView
@property (nonatomic, copy) void (^blockCalled)(NSDictionary *dict);
@property (nonatomic, strong) A *aInstance;
@end
// B.m
@implementation B
- (void) someMethod {
// !!!!! why this crashes the app when blockCalled on aInstance is called:
[self.aInstance setBlockCalled:self.blockCalled];
// but this does not crash when the same happens
__weak typeof (self) weakSelf = self;
self.aInstance.blockCalled = ^(NSDictionary *dict) {
__strong typeof (self) strongSelf = weakSelf;
// again, never just call `blockCalled`; always check to see if not null
if (strongSelf.blockCalled) {
strongSelf.blockCalled(dict);
}
};
}
@end
最重要的是,当我修复两个明显的崩溃源时(未能删除观察者并且无法检查以确保块在调用之前是非零),并使用逻辑方案测试它,它似乎工作正常:
- (void)viewDidLoad {
[super viewDidLoad];
B *b = [[B alloc] init];
b.blockCalled = ^(NSDictionary *dict) {
NSLog(@"%@", dict);
};
A *a = [[A alloc] init];
b.aInstance = a;
[b someMethod];
[self.view addSubview:a];
[self.view addSubview:b];
NSDictionary *dict = @{@"foo": @"bar", @"baz": @"qux"};
[[NSNotificationCenter defaultCenter] postNotificationName:@"kNotification" object:nil userInfo:dict];
}
因此,假设这两个问题中的一个不是问题的根源,您必须提供MCVE我们可以用来重现您描述的崩溃。