티스토리 뷰

반응형
SMALL

이번 포스트에서는 Objective-C에서 제공하는 하부 C언어 기능 중 블록에 대해 살펴보도록 하겠습니다.

블록은 Apple이 추가한 것으로 표준 ANSI C 정의에는 포함되지 않았습니다.

블록은 함수와 유사하게 생겼으며 동작 방식도 함수와 유사합니다. 또한 함수와 마찬가지로 Parameter를 넘겨줄 수도 있습니다.

다만, 함수와 다른 점은 블록은 함수나 메소드 안에서 정의할 수도 있고, 자신과 동일한 범위에 있다면, 블록 바깥에서 정의된 변수에도 접근이 가능합니다. 하지만 일반적으로 이러한 변수에 접근은 가능하지만 값을 변경할 수는 없습니다. 만약 이 값을 변경하고 싶다면 __block(block 앞에 _가 2번) 을 사용하면 블록 내에서 이런 변수의 값을 변경할 수 있게 됩니다. 블록은 함수와 메소드의 Parameter로 넘겨질 수 있습니다.

블록이 갖는 장점 중 하나는 시스템이 실행 중인 어플리케이션 프로세스나 스레드에서 블록을 분산해서 처리할 수 있도록 할 수 있다는 점입니다.

void printHelloWorld(void) {
	NSLog(@"Hello World.");
}

위 코드는 기본적인 함수입니다. hello world를 출력해주는 함수입니다. 이 함수를 블록을 구현해보면 아래와 같습니다.

^(void) {
	NSLog(@"Hello World");
}

Objective-C에서는 블록을 변수에 대입할 수도 있습니다.

void (^printHelloWorld) (void) = 
	^(void) {
    	NSLog(@"Hello World");
    };

변수에 대입하였으므로 끝에는 세미콜론(;)이 반드시 들어가야 합니다. 아무 인수도 들어가지 않고, 아무 값도 반환하지 않는 블록의 포인터형으로 printHelloWorld를 정의하였습니다. 이렇게 변수로 참조한 블록은 함수와 동일한 방식으로 사용할 수 있습니다. 아래처럼 말이죠.

printHelloWorld();

그럼 간단하게 1부터 n까지 합산한 값을 출력하는 함수를 블록을 사용하여 구현해보도록 하겠습니다.

#import <Foundation/Foundation.h>

void (^calculateNumber) (int) = {
	^(int n) {
    	int i, resultNumber = 0;
        
        for (i = 1; i <= n; ++i) {
        	resultNumber += i;
        }
        NSLog(@"Result Number from 1 to %i is %i", n, resultNumber);
    }
};

int main(int argc, char *argv[]) {
	@autoreleasepool {
		calculateNumber(10);
        calculateNumber(50);
        calculateNumber(100);
    }
}

실행 결과는 아래와 같습니다.

올바르게 잘 실행되는 모습을 살펴 볼 수 있습니다.

다음 코드는 블록 내에서 접근할 수 있는 변수의 범위를 알 수 있는 예제 코드입니다. 

#import <Foundation/Foundation.h>

int main(int argc, char *argv[]) {
	@autoreleasepool {
    	int num = 10;
        
        void (^printNumber)(void) = {
        	^(void) {
	        	NSLog(@"num = %i", num);
            }
        };
        
        num = 20;
        printNumber();
    }
	return 0;
}

블록이 정의된 범위 내에 존재하는 변수에 접근할 수 있는 것을 볼 수 있습니다. 출력된 값을 확인해보면 num = 10 이라고 출력되는 것을 확인할 수 있습니다. 분명 20으로 지정했는데 적용이 되지 않았네요 그렇죠? 그 이유는 블록이 실행될 시점이 아니라 정의되었을 시점의 값이 사용되기 때문입니다.

 

그렇다면, 블록 밖에 정의된 변수에 대해 접근은 가능하지만 블록 밖에 정의된 변수의 값을 수정하는 것이 불가한 지에 대하여 알아보도록 하겠습니다. 한 줄을 추가해줍니다.

#import <Foundation/Foundation.h>

int main(int argc, char *argv[]) {
	@autoreleasepool {
    	int num = 10;
        
        void (^printNumber)(void) = {
            ^(void) {
        		NSLog(@"num = %i", num);
	            num = 30; // Compile Error
            }
        };
        
        num = 20;
        printNumber();
    }
	return 0;
}

실제 입력을 해보면 아래와 같이 오류가 발생합니다. 즉, 값을 변경할 수 없다는 것입니다.

다만, int num = 10;을 아래와 같이 수정한다면,

__block int num = 10;

문제 없이 컴파일 되는 것을 확인할 수 있습니다.

자 그러면, 본 예제의 첫 번째 부분에서 블록이 정의되었을 시점의 값이 사용된다는 것을 확실하게 알 수 있는 예제를 한 번 더 살펴보고 마무리하도록 하겠습니다.

#import <Foundation/Foundation.h>

int main(int argc, char *argv[]) {
	@autoreleasepool {
    	__block int num = 10;
        
        void (^printNumber)(void) = {
        	^(void) {
	        	NSLog(@"num = %i", num);
            	num = 30;
            }
        };
        
        num = 20;
        printNumber();
    }
	return 0;
}

__block이 들어가면서 실행 시점의 값이 사용되었고 값이 변경되었으므로 다음 줄에는 새로 바뀐 값이 보이는 것을 알 수 있습니다.

이번 포스트에서는 Objective-C에서 제공하는 하부 C 언어 기능 중 Block에 대해 알아보았습니다.

반응형
LIST
반응형
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함