Objective-C 블록구문
아직까지도 잘 사용하지 않는 블록 구문, 오브젝티브-C 핸드북을 보면서 내가 알고 있는 내용과 책의 내용이 맞는지 비교하면서 훓어 보고 있는데 어느 정도 대충? 맞는 부분이 많다.
스위프트(Swift)도 함께 병행 해야 하는 시점이 다가 오는걸 직감할 수 있다.
여기저기 사람 구하는 곳에서 보면 Swift가 옵션이 아니라 필수가 되어 가고 있다는걸 느낄 수 있다.
오늘 Swift4.0 문법 도서를 한 권 구입했다. 긴 겨울 사무실에서 공부를 해 볼까 한다.
오늘은 잘 사용하지 않는 블록 구문에 대한 내용을 정리 하고자 한다.
잘쓰면 엄청 편리한 블록인데, 우선 GCD(Grand Central Dispatch)에 대한 정의 부터 옮겨 본다.
Grand Central Dispatch(GCD)와 블록
Mac OS X 10.6 이후 버전이나 iPhone OS4.0부터 등장한 기술 중에 'Grand Central Dispatch'(GCD)가 있습니다. 'GCD'는 CPU코어를 포함해 시스템 레벨에서 이용할 수 있는 연산장치로 태스크를 분산시키는 기술입니다. 이러한 태스크를 기술할 때도 블록을 사용합니다. 'GCD'의 API는 'libdispatch.dylib' 라는 라이브러로 구현되며 각 API에서 태스크로 블록을 전달합니다. 'GCD'는 전달받은 블록을 연산장치에 효율적으로 분산시키고 블록을 실행합니다. 블록 자신이 어떻게 분산되었는지는 관계 없이 하나의 태스크로 실행시킵니다.
멀티코어 CPU가 일반화되고 앞으로도 코어의 증가나 CPU이외의 연산장치를 이용하는 기술이 발전해 감에 따라 블록과 'GCD'의 조합은 더욱 중요시될 것입니다. -오브젝티브-C핸드북 에서 -
라고 책에서 정의 해두었네요 ^^
GCD 에 관해서는 따로 공부를 하는 것이 좋다. 나도 잘 모른다. 그냥 사용하는 곳이 있으면 가져다 사용하는 정도인데 멀티코어 프로세싱에 관심이 있는 사람들은 자료를 찾아 보길 권한다.
그럼 간단하게 살펴 보도록 하겠습니다.
블록 구문을 사용하면 함수를 정의하지 않고 로컬 함수를 변수와 같이 생성할 수 있다고 되어 있는데 잘 이해 안된다.
구문 정의는 다음과 같다.
반환형 (^블록명)(파라미터 타입)
예시를 보면
int (^square)(int); 라고 정의해두고
구현은
square = ^(int x) {
return x * x; //x를 제곱하여 리턴
};
사용 예시는
square(2);
일반적인 함수와 별 차이를 모르겠다.
그런데 이 블록을 특정 메서드의 파라미터로 사용하는 방법은 유용한 것 같다.
블록을 파라미터로 하는 메서드는 변수를 선언하지 않고 블록 자체를 파라미터로 기술하는데 NSArray클래스의
- (void)enumerateObjectsUsingBlock:(void (NS_NOESCAPE ^)(ObjectType obj, NSUInteger idx, BOOL *stop))block API_AVAILABLE(macos(10.6), ios(4.0), watchos(2.0), tvos(9.0));
메서드는 NSArray 클래스의 인스턴스가 가진 엘리먼트를 순서대로 블록에 전달하는 메서드이다.
열개의 인자를 가진 배열 theArray가 있다고 할 때 인자의 값을 제곱해서 로그를 출력하는 방법은 다음과 같다.
[theArray enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
//파라미터 'obj' 는 각 엘리먼트임 , 10개의 엘리먼트가 있으므로 10번 호출됨.
NSInteger xx = [obj integerValue]; //NSNumber형일 때 NSInteger로 형변환
NSLog(@"%ld x %ld = %ld", (long)xx, (long)xx, xx*xx);
}];
블록을 파라미터로 갖는 메서드를 구현하는 방법은 다양한데 내가 진행했던 프로젝트에서 사용했던 예제를 보겠다.
typedef void(^ActionlBlock)(id control, NSInteger index);
typedef형태로 선언을 해두고 메서드의 인자로 추가해서 사용하는 방법이다.
- (void) setBarItemWithLeftBackControl:(id)target handler:(ActionlBlock)action;
구현부에서는
- (void) setBarItemWithLeftBackControl:(id)target handler:(ActionlBlock)action {
//기능을 기술한다.
}
사용할 때는 다음과 같이
[self setBarItemWithLeftBackControl:self handler:^(id control, NSInteger index) {
[[UIManager sharedInstance] popViewController:self withData:nil animated:YES];
}];
메서드의 인자로 취해서 해당 컨트롤의 action을 처리하는 블록을 만들어 사용하면 된다. 자바스크립트의 콜백 메서드랑도 비슷한 느낌인데 사용하는 방식에 따라 다를 것 같다.
책에서 말하는 블록을 파라미터로 갖는 메서드에 대한 정의를 옮겨 본다.
블록이 'int'타입의 파라미터를 한 개 가지며 'int'타입을 반환하는 예
- (void)calcRange:(NSRange)range usingBlock:(int (^)(int x))block;
구현은
- (void)calcRange:(NSRange)range usingBlock:(int (^)(int x))block
{for (int i=0; i < range.length; i++) {
//블록 호출은 블록 변수에 '( )' 를 붙혀서 '( )' 내에 파라미터를 기술함
NSLog(@"%d : %d", i, block(i));
}
}
사용예시는 다음과 같다.
MyClass *c = [MyClass new];
[c calcRange:NSMakeRange(0,10) usingBlock:^(int x) {
return x * x; //제곱해서 리턴
}];
아주 매력적인 문법이다.
'프로그래밍 > Xcode-iOS' 카테고리의 다른 글
diff: /Podfile.lock: No such file or directory (0) | 2018.05.02 |
---|---|
금액 한글 변환 소스(objective-c, iOS, 아이폰) (0) | 2018.04.20 |
.png pngcrush caught libpng error 해결 방법 (0) | 2017.11.02 |
Objective-C @property 의 설정자 (0) | 2017.11.01 |
Objective-C 카테고리 정의 (0) | 2017.11.01 |