《Programming with Objective-C》第八章 Working with Blocks

Blocks are Objective-C objects, which means they can be added to collections like NSArray or NSDictionary.

 

Block語法——無參數版本

定義(Block的值)

^{
    NSLog(@"This is a block");
}

 

聲明

void (^simpleBlock)(void);

相似int i;html

 

賦值

simpleBlock = ^{
    NSLog(@"This is a block");    
}

相似i = 2;ide

 

聲明的時候定義

void (^simpleBlock)(void) = ^{
    NSLog(@"This is a block");
}

相似int i = 2;函數

 

調用

simpleBlock();

 

Block語法——帶參數版本

定義

^(double firstValue, double secondValue)
{
    return firstValue * secondValue;
}

or學習

^double (double firstValue, double secondValue) 
{
    return firstValue * secondValue;
}

 

聲明

double (^multiplyTwoValues)(double, double);

 

賦值

multiplyTwoValues = ^(double firstValue, double secondValue) 
{
    return firstValue * secondValue;
};

 

聲明的時候定義

double (^multiplyTwoValues)(double, double) =
^(double firstValue, double secondValue) 
{
    return firstValue * secondValue;
};

 

調用

double result = multiplyTwoValues(2,3);

 

__block修飾符

int anInteger = 42;

void (^testBlock)(void) = ^{    //此時只是Block定義,並無執行裏面的函數
    NSLog(@"Integer is: %i", anInteger);
};

anInteger = 84;

testBlock();    //Block調用 輸出42

 

Value is captured when the block is defined.atom

Block定義的時候,將值複製一份給本身,因此該值已經不受外界影響。spa

 

__block int anInteger = 42;

void (^testBlock)(void) = ^{    //此時只是Block定義,並無執行裏面的函數
    NSLog(@"Integer is: %i", anInteger);    
};

anInteger = 84;

testBlock();    //Block調用 輸出84

 

Because anInteger is declared as a __block variable, its storage is shared with the block declaration.指針

此時Block裏面的值與外面的值共享同一分內存code

 

Block與self的恩怨情仇

It’s important to take care when capturing self because it’s easy to create a strong reference cycle when capturing self.htm

 

由於變量默認是__strong修飾(詳見這裏),因此要時刻注意在block裏面對self的引用(只要出現了self關鍵字就算引用了,由於block會自動capture)blog

假如self裏面定義了一個block,那麼self有一個指向block的strong指針(好比該block是self的一個strong成員變量);假如block裏面使用了self,則block也默認拷貝了一個指向self的strong指針,此時造成strong reference cycle.

解決方法:在Block前面建立一個__weak類型的指向self的指針,並在block裏面使用該指針。

例子

__weak typeof(self) weakSelf = self;    //學習下這種寫法哦 typeof(self)
self.simpleBlock = ^{
    [weakSelf f];
};
...
self.simpleBlock();

可是,假如Block裏面又有一個Block,怎麼辦?最好是強引用weakSelf,此時strongSelf強引用的是weakSelf而不是self,因此不會造成strong reference cycle

__weak typeof(self) weakSelf = self;    //學習下這種寫法哦 typeof(self)
self.simpleBlock = ^{
    [weakSelf f];
    __strong typeof(weakSelf) strongSelf = weakSelf;
    self.simpleBlock2 = ^{
        [strongSelf f];
    };
    self.simpleBlock2();
};
...
self.simpleBlock();

圖解

一個函數最好只有一個Block參數,且最好是在最後一個

A Block Should Always Be the Last Argument to a Method.

It’s best practice to use only one block argument to a method.

 

使用typedef定義一個block

typedef int (^Sum)(int, int);
Sum mySum = ^(int a, int b){
    return a+b;
}

or

typedef void (^XYZSimpleBlock)(void);
@property (copy) XYZSimpleBlock blockProperty;

 

使用copy修飾block的property

@property (nonatomic, copy) Sum mySum;
@property (nonatomic, copy) void (^blockProperty)(void);

非ARC下就必須寫copy,because a block needs to be copied to keep track of its captured state outside of the original scope在ARC下寫不寫copy都無所謂,so it's a best practice to set copy property for block whether it's ARC or not.

相關文章
相關標籤/搜索