개요

: C 언어에 새로 추가된 확장 기능이다.
: "자동(지역) 변수와 함께 동작하는 익명 함수"라고 할 수 있다.


블록 변수 선언과 사용
int (^blk)(int); 
: 지역 변수, 함수 인자, 정적 지역 변수, 정적 전역 변수, 전역 변수로 선언이 가능하다.
typedef int (^blk_t)(int);로 복잡성을 피할 수 있다. 이렇게 하면 blk_t 타입으로 변수를 선언할 수 있다.
: 블록 포인터로도 사용이 가능하다.
typedef int (^blk_t)(int);
blk_t blk = ^(int count){return count + 1};
blk_t *blkptr = &blk;
(*blkptr)(10);


자동 변수 캡처

int val = 10;
const char *fmt = "val = %d\n";
void (^blk)(void) = ^{ printf(fmt, val); };

val = 2;
fmt = "These values were changed. val = %d\n";
blk();

// 결과: "val = 10"

fmt, val은 블록 리터럴이 선언될 때 이미 캡쳐되어 있어서, 블록 리터럴 선언 이후에 값이 변경되더라도 블록 리터럴 내부의 값은 절대 영향을 받지 않는다.


__block 지시어 
: __block 지시어를 사용하면 지역변수를 캡처하지 않고 블록 리터럴 내부에서 수정도 가능하다.

int val = 0;
void (^blk)(void) = ^{val = 1;};
// 컴파일 에러 발생! 블록 리터럴 밖에서 선언한 지역 변수에 값을 할당했기 때문!

__block int val = 0; 으로 코드를 변경해야 한다.


캡처된 자동 변수

그렇다면 이 코드도 컴파일 에러가 발생할까? 

id array = [[NSMutableArray alloc] init];
void (^blk)(void) = ^{
    [array addObject:@2];
};
// 컴파일 에러가 발생하지 않는다. 이 경우 캡쳐된 것은 NSMutableArray 클래스 객체에 대한 구조체 인스턴스의 포인터이다.

id array = [[NSMutableArray alloc] init];
void (^blk)(void)=^{
    array = [[NSMutableArray alloc] init];
};
// 컴파일 에러 발생! 

C 배열은 블록에 의해 자동으로 캡쳐될 수 없다.
const char text[] = "hello";
void (^blk)(void) = ^{
    printf("%c\n", text[2]);
};
// 컴파일 에러 발생. 

그러므로 포인터를 사용해야 한다.
const char *text = "hello";
void (^blk)(void) = ^{
    printf("%c\n", text[2]);
}
// 정상동작 한다.

'IOS > Objective-C' 카테고리의 다른 글

Block의 모든것(3)  (0) 2017.01.02
Block의 모든것(2)  (0) 2017.01.02
ARC 규칙  (0) 2017.01.01
GCD(Grand Central Dispatch)(2)  (0) 2016.12.19
GCD(Grand Central Dispatch)(1)  (0) 2016.12.19
Posted by 홍성곤
,