我对基于块的回调有不了解。似乎有两种我知道的方法,我不知道何时应该使用一种方法,所以有人可以向我解释两者之间的差异,纠正我并给我一些提示,如果我需要的话任何。
我发现了一些代码,我发现了stackoverflow以及来自其他地方的库,所以感谢编写此代码的人。
typedef void (^MyClickedIndexBlock)(NSInteger index);
@interface YourInterface : YourSuperClass
@property (nonatomic, strong) MyClickedIndexBlock clickedIndexBlock
.m
//where you have to call the block
if (self.clickedIndexBlock != nil) {self.clickedIndexBlock(buttonIndex)};
// where you want to receive the callback
alert.clickedIndexBlock = ^(NSInteger index){NSLog(@"%d", index);};
我对上述内容的理解是:
MyClickedIndexBlock是NSInteger的typedef。使用名称“clickedIndexBlock”创建的属性,其类型为MyClickedIndexBlock(表示clickedIndexBlock可以是数字)。
块也可以用作方法,这就是为什么我可以调用self.clickedIndexBlock(buttonIndex);
但有些东西告诉我,这种作为@property的方法只支持一个参数 例如。 NSInteger的。
鉴于以下方法允许多个参数。
bluetoothMe.h
typedef void (^hardwareStatusBlock)(CBPeripheral *peripheral, BLUETOOTH_STATUS status, NSError *error);
- (void)hardwareResponse:(hardwareStatusBlock)block;
bluetoothMe.m
- (void)hardwareResponse:(hardwareStatusBlock)block {
privateBlock = [block copy];
}
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
NSLog(@"Did connect to peripheral: %@", peripheral);
privateBlock(peripheral, BLUETOOTH_STATUS_CONNECTED, nil);
NSLog(@"Connected");
[peripheral setDelegate:self];
[peripheral discoverServices:nil];
}
我的理解是创建一个强大的属性并执行[块复制]将保留块,直到应用程序终止。所以[block copy]和强者都保留了。 [块复制]应用于块以保留,否则当方法超出范围时块将消失。
ViewController.m
[instance hardwareResponse:^(CBPeripheral *peripheral, BLUETOOTH_STATUS status, NSError *error) {
if (status == BLUETOOTH_STATUS_CONNECTED)
{
NSLog(@"connected!");
}
else if (status == BLUETOOTH_STATUS_FAIL_TO_CONNECT)
{
NSLog(@"fail to connect!");
}
else
{
NSLog(@"disconnected!");
}
NSLog(@"CBUUID: %@, ERROR: %@", (NSString *)peripheral.UUID, error.localizedDescription);
}];
让我们看看我的问题是什么:
1)我何时会选择第一种方法而不是第二种方法,反之亦然?
2)第一个例子,块是属性的typedef。第二个例子,块被声明为一个方法。为什么不能将第一个示例声明为方法,为什么第二个示例不能将typedef声明为属性?
3)我是否需要为每种类型的委托方法创建一个typedef,我想要一个基于块的回调?
4)到目前为止,我只看到了一种支持的委托方法。如果我要在多个不相似的委托方法上创建基于块的回调,你能否告诉我一个如何实现每种方法的例子?
感谢您的反馈。这有时很难。需要尽可能多的帮助。 谢谢,
本
答案 0 :(得分:7)
问题
typedef
阻止完全独立(或正交)。所有组合都是 可能和允许。
void (^myClickedIndexBlock)(NSInteger index);
声明一个带有整数参数的块变量myClickedIndexBlock
并返回虚空。如果出现相同的块类型,则可以使用typedef
在您的计划中反复出现:
// Define MyClickedIndexBlock as *type* of a block taking an integer argument and returning void:
typedef void (^MyClickedIndexBlock)(NSInteger index);
// Declare myClickedIndexBlock as a *variable* of that type:
MyClickedIndexBlock myClickedIndexBlock;
有多个参数:
void (^privateBlock)(CBPeripheral *peripheral, BLUETOOTH_STATUS status, NSError *error);
或
typedef void (^hardwareStatusBlock)(CBPeripheral *peripheral, BLUETOOTH_STATUS status, NSError *error);
hardwareStatusBlock privateBlock;
您可以使用属性代替(实例)变量。在第一个例子中:
@property (nonatomic, copy) void (^myClickedIndexBlock)(NSInteger index);
将myClickedIndexBlock
声明为块属性,等同于
typedef void (^MyClickedIndexBlock)(NSInteger index);
@property (nonatomic, copy) MyClickedIndexBlock clickedIndexBlock;
与您的假设相反,块属性不限于块 只有一个参数。您也可以在第二个示例中使用属性, 有或没有typedef:
@property (nonatomic, copy) void (^privateBlock)(CBPeripheral *peripheral, BLUETOOTH_STATUS status, NSError *error);
或
typedef void (^hardwareStatusBlock)(CBPeripheral *peripheral, BLUETOOTH_STATUS status, NSError *error);
@property (nonatomic, copy) privateBlock;
您可以选择是否使用实例变量或块的属性。 我会使用属性(使用“copy”属性)。
是否键入def纯粹是一种品味问题。它有助于避免 如果在程序中重复出现相同的块类型,则会出错。在另一 手,Xcode自动完成似乎没有typedef更好(在我的 体验)。
答案 1 :(得分:3)
我强烈建议您阅读Blocks Programming Guide。
块不是方法。我不会解释Conceptual Overview中所说的内容,只是引用一些部分:
Blocks通常代表小的,自包含的代码片段。 [...]
它们允许您在稍后在方法实现的上下文中执行的调用时编写代码。
似乎你对语法感到困惑。
typedef void (^MyClickedIndexBlock)(NSInteger index);
它基本上只是定义一个名为 MyClickedIndexBlock 的类型,表示一个块,它接受NSInteger类型的单个参数并且不返回任何内容(void)。
它是不 NSInteger的typedef。
@property (nonatomic, strong) MyClickedIndexBlock clickedIndexBlock
是包含MyClickedIndexBlock的属性声明 不需要输入def块,编写
是完全有效的@property (nonatomic, strong) void(^clickedIndexBlock)(NSInteger index);
但为了清晰(或重复使用),您可以选择键入它们。请注意,属性名称位于^
。
您说明可以将块用作方法,因为您可以在示例中调用self.clickedIndexBlock(buttonIndex)
。但事实上,这是因为你已经声明了一个名为clickedIndexBlock
的属性,你可以这样称呼它。
你的问题有很多,但很大一部分是由于混乱和误解造成的。你提到的两种方法并没有什么不同。块是对象,可以作为参数,局部变量或ivars /属性进行操作,就像使用NSString或其他类型的对象一样。
答案 2 :(得分:0)
1)该块未对整数进行typedef。它的typedef将返回void并具有整数参数。精神1或方法2没有任何优势;如果声明,它们都可以有多个参数。
2)没有理由为这两种情况选择这种格式。它们都取得了相同的结果,但第一个可以说在语义上更好。
3)否。您可以向方法声明内联块。查看[NSArray enumerateObjectsUsingBlock:]
的标题,以获取内联块声明的示例。
4)您可以创建多个属性,并在必要时调用每个不同的块。