请帮助我使用基于块的回调

Ben*_*Ben 3 objective-c ios objective-c-blocks ios5 ios6

我对基于块的回调不太了解.似乎有两种我知道的方法,我不知道何时应该使用一种方法,所以有人可以向我解释两者之间的差异,纠正我并给我一些提示,如果我需要的话任何.

我从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);};
Run Code Online (Sandbox Code Playgroud)

我对上述的理解是:

  1. MyClickedIndexBlock是NSInteger的typedef.使用名称"clickedIndexBlock"创建的属性,其类型为MyClickedIndexBlock(表示clickedIndexBlock可以是数字).

  2. 块也可以用作方法,这就是为什么我可以调用self.clickedIndexBlock(buttonIndex);

但有些东西告诉我,这种方法作为@property只支持一个参数,例如.NSInteger的.

鉴于以下方法允许多个参数.

bluetoothMe.h

typedef void (^hardwareStatusBlock)(CBPeripheral *peripheral, BLUETOOTH_STATUS status, NSError *error);

- (void)hardwareResponse:(hardwareStatusBlock)block;
Run Code Online (Sandbox Code Playgroud)

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];
 }
Run Code Online (Sandbox Code Playgroud)

我的理解是创建一个强大的属性并执行[块复制]将保留块,直到应用程序终止.所以[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);
}];
Run Code Online (Sandbox Code Playgroud)

那么让我们看看我的问题是什么:

1)我什么时候会选择第一种方法而不是第二种方法,反之亦然?

2)第一个例子,块是属性的typedef.第二个例子,块被声明为一个方法.为什么不能将第一个示例声明为方法,为什么第二个示例不能将typedef声明为属性?

3)我是否需要为每种类型的委托方法创建一个typedef,我想要一个基于块的回调?

4)到目前为止,我只看到了一种支持的委托方法.如果我要在多个不相似的委托方法上创建基于块的回调,你能否告诉我一个如何实现每种方法的例子?

感谢您的反馈.这有时很难.需要尽可能多的帮助.谢谢,

Mar*_*n R 7

问题

  • 无论是否typedef阻止,
  • 是否使用属性块,
  • 块是否具有单个或多个参数,

完全独立的(或正交).所有组合都是可能的并且允许.

void (^myClickedIndexBlock)(NSInteger index);
Run Code Online (Sandbox Code Playgroud)

声明一个块变量myClickedIndexBlock采用整数参数并返回void.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;
Run Code Online (Sandbox Code Playgroud)

有多个参数:

void (^privateBlock)(CBPeripheral *peripheral, BLUETOOTH_STATUS status, NSError *error);
Run Code Online (Sandbox Code Playgroud)

要么

typedef void (^hardwareStatusBlock)(CBPeripheral *peripheral, BLUETOOTH_STATUS status, NSError *error);
hardwareStatusBlock privateBlock;
Run Code Online (Sandbox Code Playgroud)

您可以使用属性代替(实例)变量.在第一个例子中:

@property (nonatomic, copy) void (^myClickedIndexBlock)(NSInteger index);
Run Code Online (Sandbox Code Playgroud)

声明myClickedIndexBlock为块属性,相当于

typedef void (^MyClickedIndexBlock)(NSInteger index);
@property (nonatomic, copy) MyClickedIndexBlock clickedIndexBlock;
Run Code Online (Sandbox Code Playgroud)

与您的假设相反,块属性不限于具有单个参数的块.您可以在第二个示例中使用属性,有或没有typedef:

@property (nonatomic, copy) void (^privateBlock)(CBPeripheral *peripheral, BLUETOOTH_STATUS status, NSError *error);
Run Code Online (Sandbox Code Playgroud)

要么

typedef void (^hardwareStatusBlock)(CBPeripheral *peripheral, BLUETOOTH_STATUS status, NSError *error);
@property (nonatomic, copy) privateBlock;
Run Code Online (Sandbox Code Playgroud)

您可以选择是否使用实例变量或块的属性.我会使用属性(具有"复制"属性).

是否键入def纯粹是一种品味问题.如果在程序中重复出现相同的块类型,则有助于避免错误.另一方面,没有typedef(根据我的经验),Xcode自动完成似乎更好.