让Xcode抱怨缺少参数

时间:2013-09-22 16:56:16

标签: iphone ios ipad cocoa-touch objective-c-blocks

我正在通过现代化我过去编写的代码来设计一个新的应用程序。这个旧代码使用类/委托模型,我试图将它们转换为使用块作为回调,而不是委托的东西。

我所做的就是创建一个像

这样的属性
@property (nonatomic, copy) void (^onTouch)(NSInteger index);

那将使用该类传递给对象一个可以插入代码的块,在这种情况下可以触摸执行。

但我的问题是这个。当您使用委托并且您在委托协议上有方法时,如果您使用该类并且忘记实现委托协议,Xcode将发出警告。这是用块做到这一点的方法吗?或者换句话说:如果调用者没有定义回调块,有没有办法让Xcode抱怨?

我的意思是这是正确的:

MyClass *obj = [[MyClass alloc] init];
obj.onTouch = ^(NSInteger *index){ //call back code to be executed };

这也没关系

MyClass *obj = [[MyClass alloc] init];
obj.onTouch = nil;

但这会生成一条消息

MyClass *obj = [[MyClass alloc] init];
// no callback block defined.

这可能吗?

2 个答案:

答案 0 :(得分:2)

如果要强制设置某个参数,我会将其包含在初始值设定项中。

MyClass *obj = [[MyClass alloc] initWithBlock:^(NSInteger *index) { /* code*/ }];

然后,在MyClass

- (id)init {
  // This will result in a runtime error if you use the wrong initializer.
  NSAssert(NO, @"Use initWithBlock instead.");
}

- (id)initWithBlock(initWithBlock:^(NSInteger *)block) {
  self = [super init];
  if (self) {
    self.onTouch = block;
  }
  return self;
}

另请注意,尝试执行NULL阻止会导致崩溃,因此请务必执行以下操作:

if (self.onTouch) { self.onTouch(); }

无论你在哪里跑步。

答案 1 :(得分:1)

首先,我强烈推荐defining types to represent your blocks - 使它们更容易使用,特别是如果你需要重构参数。

你不能编写区分“我将此属性设置为nil”或“运行时将此属性初始化为nil”的代码,至少在没有一些疯狂的运行时代码来检查堆栈的情况下。我能想到的唯一选择就是使用null object pattern。在我详细说明之前,请记住我实际上并没有尝试过测试,但它应该可行。定义一个意味着“没有值”的块,并将您的属性设置为指向init上的该块。然后,您可以在运行时与NullBlock进行比较,以确定是否有人将该属性显式设置为nil(因为此时它将为零)或者给它一个真正的非零值。

或者,如果您不介意手动编写set访问器,则可以使用BOOL跟踪是否有人明确设置了该属性。然后当你调用块时,只检查是否有人实际设置了值。

@synthesize onTouchBlock=_onTouchBlock;
MyBlock _onTouchBlock;
BOOL _onTouchBlockWasSet;

- (void)setOnTouchBlock:(MyBlock)block {
 _onTouchBlockWasSet = YES;
 _onTouchBlock = block;
}

我不建议在初始值设定项中传递值,因为这会使其与该对象类型的创建联系起来。如果你想根据某些条件在代码中更改块,你将回到原点。此外,它会阻止您使用创建该对象的故事板。