개요
: 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 |