본문 바로가기

Objective-C에서 인터페이스 공개시키기

기술적인 이야기/애플 플랫폼 개발 2023. 3. 13.
반응형

C 언어는 OOP 언어가 아니기 때문에 애초에 접근 제어(Access Control)와 관련된 기능이 없다. 그래서 보통은 헤더파일에 공개하기를 원하는 변수나 함수 등의 선언문을 작성해 놓고 필요한 곳에서 해당 헤더를 포함(include)시켜서 사용한다.

하지만 항상 헤더가 제공되는 법은 아니다. 만약 헤더 파일이 없다면 extern이라 불리는 키워드를 이용해 외부에서 구현된 기능을 적당히 참조하거나 호출하는 것이 가능하다.

예를 들어 아래의 코드가 있다고 치자.

int globalvalue = 0;

int foobar(int left, char *right) {
    ...
}

위 코드의 인터페이스가 없더라도 아래와 같이 선언하면 위의 변수와 함수를 그대로 쓸 수 있게 된다.

extern int globalvalue;
extern int foobar(int, char *);

여기서 사용된 extern 키워드는 현재 파일이 아닌 다른 곳에서 해당 전역변수나 함수 등이 구현되어 있다는 것을 알려주는 용도다.

이 방법은 지극히 C스러운 접근 제어의 모습을 보고 있다. 앞서 이야기했지만 C에는 접근 제어가 없고 그저 인터페이스가 공개되냐 마느냐의 차이 정도만 있을 뿐이니 말이다.

Objective-C도 C의 Superset인 만큼 기존의 extern을 이용한 인터페이스만 정의하는 것은 동일하게 사용할 수 있다. 위의 코드도 Objective-C에서 아무 문제 없이 쓸 수 있다는 말이다.

다만 문제는 Objective-C 만의 기능, 예를 들어 클래스나 NS_ENUM으로 정의한 타입의 경우가 있을 수 있다. 이들 타입은 기존의 extern을 사용할 수 없거나 혹은 호환성에 미묘한 문제가 있을 수 있다.

그래서 이 경우엔 별도의 방법을 동원해야 한다. 여기서는 몇 가지 예시를 정리해본다.

반응형

클래스 인터페이스 공개시키기

예를 들어 아래와 같은 클래스가 있다고 치자.

@interface SomeAnotherClass : NSObject
...
@end

@implement SomeAnotherClass
...
@end

이 클래스 자체를 노출시키려면 아래와 같이 할 수 있다.

@class SomeAnotherClass;

@class 지시어를 이용하면 클래스의 이름을 노출시킬 수 있다. 이제 별도의 헤더에 공개되지 않더라도 해당 클래스 인스턴스를 생성하는 것 정도는 할 수 있다.

클래스 멤버 인터페이스 노출시키기

클래스의 프로퍼티나 메서드 등을 노출시키는 방법은 기존의 카테고리를 이용한 확장(extension) 방법을 이용할 수 있다. 예를 들어 위의 예의 SomeAnotherClasssomePrivateMethod 메서드가 존재하지만 공개가 되어있지 않다면 아래와 같은 방법으로 인터페이스를 현재 스코프에 공개시킬 수 있다.

@interace SomeAnotherClass ()

- (void)somePrivateMethod;

@end

물론 위의 경우는 리턴도 매개변수 선언도 없는 단순한 형태이지만 당연하게도 해당 메서드의 모든 인터페이스 스펙을 정확하게 명시해야 한다. 그렇지 않으면 호출되지 않고 오류가 발생하는 것을 볼 수 있다.

728x90

NS_ENUM의 경우

C 언어 식으로 만든 enum으로 정의한 타입이라면 사실 extern을 사용하는 C의 방식을 그대로 써도 된다. 하지만 NS_ENUM의 경우는 Objective-C 뿐만 아니라 Swift 호환을 위한 몇 가지 선언이 첨가된 매크로 형태라서 extern을 그대로 붙이기엔 곤란할 수도 있다.

이럴 때는 extern을 붙이지 말고 그냥 인터페이스의 이름 선언 부분을 그대로 붙여서 인터페이스를 노출할 수 있다. 예를 들어 아래와 같은 타입을 선언했다고 치자.

typedef NS_ENUM(int, SomeAnotherType) {
    SomeAnotherTypeFoo = 0,
    SomeAnotherTypeBar,
    SomeAnotherTypeQue
}

SomeAnotherType이 공개되지 않았지만 무작정 쓰고 싶다면 아래와 같이 타입을 그대로 선언해 주는 방법이 있다.

typedef NS_ENUM(int, SomeAnotherType);

이후 SomeAnotherType을 그대로 쓸 수 있게 된다.

사족

이 글은 모든 경우를 다루는 글이 아니다. 그저 개인적인 경험에 기초하여 지식을 정리하는 글이라 한계가 명확하다.

물론 세상은 Swift로 옮겨가는 마당이라 Objective-C 글이 얼마나 유용할지는 좀 회의적이긴 하다. 하지만 개인적으로는 아직 써야 하는 입장이기에 의미가 없지는 않다. 그래서 누군가에게 이 글이 도움이 될 수 있다면 참 좋을 것 같다.

728x90
반응형

댓글