1

我知道有关 Obj C 块编程的高级概念。但是,我对 Obj C 代码中的块编程几乎没有疑问。块编程的几个概念如下所述,所以我对每个概念的问题也如下:

  1. 它支持异步操作: 问:请问,这是什么意思?块代码支持什么样的异步操作?

  2. 块代码独立于其他代码工作(执行): 问:这是否意味着它在不同的线程中运行?无论其他代码同时执行,此代码是否都会执行?

  3. Q:块枚举是什么意思?

有人请教我这个吗?

4

1 回答 1

3

块用于各种事情。您使用它们的方式可以使它们非常强大。

例如,块通常被用作执行委托方法通常所做的事情的一种方式,即它们作为参数传递并存储在一边,然后在某些操作完成后调用。这样,它们可以用作“异步操作”,因为它们可以在以后调用。

可以将块视为异步的用法示例是在委托方法中调用它们以使其比委托更易于使用:

typedef void (^BlockAlertViewCompletion)(UIAlertView* alert, NSInteger clickedButton);

@interface BlockAlertView : UIAlertView <UIAlertViewDelegate>
-(void)showWithCompletion:(BlockAlertViewCompletion)completion;
@property(nonatomic, copy) BlockAlertViewCompletion completionBlock;
@end

@implementation BlockAlertView
@synthesize completionBlock = _completionBlock;
-(void)showWithCompletion:(BlockAlertViewCompletion)completion;
{
  // Store the block for latter use
  self.completionBlock = completion;
  self.delegate = self; // Make ourselves as the delegate of UIAlertView
  [self show];
}

// Then much later, the delegate method will be called ASYNCHRONOUSLY
-(void)alertView:(UIAlertView*)alert clickedButtonAtIndex:(NSInteger)buttonIndex
{
  // Then call the block here to signal the called a button has been clicked
  self.completionBlock(alert, buttonIndex);
}

-(void)dealloc { [_completionBlock release]; [super dealloc]; }
@end

// Usage:
BlockAlertView* alert = [[[BlockAlertView alloc] initWithTitle:@"Hello" message:@"Hello World!" delegate:nil cancelButtonTitle:@"Hi yourself" otherButtonTitles:@"I'm not very polite",nil];
// This will show the alert immediately (will call [alert show] eventually)
[alert showWithCompletion:^(UIAlertView* alert, NSInteger btnIndex)
 {
     // But this code in the block will only be called when the delegate method
     // of UIAlertView will be triggered, so this code will be executed asynchronously / later, and not right away
     NSLog(@"Button %d clicked", btnIndex);
 }];
// So after the alert view has been shown on screen, the rest of the code below will continue executing
NSLog(@"The alert view has been shown on the screen, but the completionBlock passed a the parameter to showWithCompletion: has not been executed yet and will only execute when the delegate method is called");
[alert release];

严格来说,块并不真正独立于其他代码执行。它们基本上是添加了上下文以捕获周围变量的函数指针。它们可以在您想要的任何线程中执行。如果您直接在当前线程中执行它们,如下例所示,它们不会与其他代码并发:

// Declare some block
dispatch_block_t block = ^{ NSLog(@"Hello world"); };
// Execute it right away
block(); // this executes the same way that is you have wrote the NSLog here, so this is not concurrent with the rest of the code.

但是使用 GCD,您可以在独立线程上将块添加到 GCD 队列并要求该线程执行该块。从这个意义上说,块中声明的代码独立于应用程序的其余部分执行

dispatch_block_t block = ^{  NSLog(@"Hello world"); };
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
// Execute the block on a secondary queue, in parallel with the current code. This is concurrent execution, the block will execute independently to the rest of the code.
dispatch_async(queue, block);

您还可以解释“块独立于其他代码执行”的想法,因为它们捕获了它们的上下文和它们需要的变量,并且可以稍后使用这些变量的值在创建块时捕获......即使变量已更改和/或超出范围:

-(void)createBlockAndCaptureVariables
{
  int a = 5;
  int b = 12;
  // Create a block. It will capture the values of a and b at that time
  dispatch_block_t block = ^{ NSLog(@"a*b = %d", a*b); };
  // Even if you change the values of a and b later…
  a = 7;
  b = 25;
  // when you execute the block here, it won't be affected by the fact that a and b have changed
  [self testBlock:block]; // Will log a*b = 60
}
-(void)testBlock:(dispatch_block_t)aBlock
{
  // And the block can be executed here and print the value of a*b, even if a and b
  // Are out of scope and not accessible in this testBlock method.
  aBlock();
}

希望这些小例子有所帮助。

于 2012-09-16T15:44:04.200 回答