본문 바로가기

iOS/Objective C

[Objective-C] 2. Class - Method & Property

1. 개요

클래스가 무엇인지 설명하기보다는 어떻게 작성하면 될 지를 위주로 설명합니다.

 

2. 기본 작성법

Objective C는 헤더 파일과 구현 파일로 나뉜다. 먼저 헤더 파일을 작성해보자.

 

Human.h

#import <Foundation/Foundation.h>

@interface Human: NSObject {

- (void)print:(NSString *)message;

+ (void)printWithName:(NSString *)name
              message:(NSString *)message;
}

먼저 헤더 파일에서는 클래스의 설계를 작성한다. 흔한 객체 지향 언어에서 class '클래스명'의 문법이 아닌 @interface '클래스명'의 문법을 가진다. 그리고, NSObject는 Objective-C의 루트 클래스로 Objective-C의 런타임과 상호작용하는 엔트리 포인트 역할을 한다. 메모리 관리, 메소드 호출 등의 기본 객체 동작을 관리하는 역할이다.

 

가장 앞의 '-', '+'는 각각 인스턴스 접근자, 클래스 접근자를 의미한다. 인스턴스 메서드는 초기화가 된 이후 초기화된 인스턴스 객체를 통해 사용이 가능하다. 클래스 메서드는 초기화 없이 사용이 가능하다.

NSObject

 

 

Human.m

#import <Foundation/Foundation.h>

@implementation Human {

- (void)print:(NSString *)message {
        NSLog(message);
    }

+ (void)printWithName:(NSString *)name
              Message:(NSString *)message {
        NSLog(@"name: %@ message: %@", name, message);
    }
}

구현 파일에서는 설계한 클래스를 실제로 구현하게 된다. 

 

 

3. 함수 호출

어떤 객체, 클래스의 함수는 다음과 같이 호출할 수 있다. 처음 보면 너무 어색할 수 있다. 자주 사용하다보면 익숙해진다.

[Human printWithName:@"Gong" message:@"Hello World"];

 

 

4. Property

다른 언어와 똑같이 Objective-C 클래스는 Property를 가질 수 있다. Property를 사용하면 getter, setter를 자동으로 생성해준다. 작성법은 다음과 같다.

 

Human.h

#import <Foundation/Foundation.h>

@interface Human: NSObject {

@property(nonatomic, copy, readonly) NSString *name;
@property(nonatomic, assign, readonly) NSInteger height;

- (instancetype)initWithName:(NSString *)name
                      height:(NSInteger)height;

}

property는 다양한 속성을 가질 수 있다. 쉽고 대표적인 것들만 소개하면 다음과 같다.

  • 원자성
    • nonatomic: 여러 스레드의 접근 과정에서 원자성을 보장하지 못한다. 대신 빠르다. (대부분의 경우 nonatomic을 권장한다.)
    • atomic: 여러 스레드의 접근 과정에서 원자성을 보장한다. 대신 느리다.
  • 객체의 메모리 관련
    • assign: 스칼라 타입(Primitive)에 사용한다. 
    • weak: 해당 프로퍼티를 소유하지 않아, Reference Count를 증가시키지 않는다.
    • strong: 해당 프로퍼티를 소유하여, Reference Count를 증가시킨다.
    • copy: strong과 유사하지만, setter 과정에서 소유하지 않고 복사한다.
  • 읽기/쓰기
    • readonly: 불변 타입이다.
    • readwrite: 가변 타입이다.
  • Nullability
    • nullable: null을 허용한다.
    • nonnull: null을 허용하지 않는다.

 

 

 

Human.m 

#import <Foundation/Foundation.h>

@implementation Human {

- (instancetype)initWithName:(NSString *)name
                      height:(NSInteger)height {
        if (self = [self init]) {
            _name = [name copy];
            _height = height;
        }
        return self;
    }

}

먼저, [self init]을 호출하면 객체 초기화를 시도한다. 이 과정에서 성공하면 if 문 내부로 진입한다. 객체의 property는 앞에 underscore('_')를 붙이고 접근한다. 유의할 점은 레퍼런스 타입은 copy를 해주어야 한다. copy를 하지 않으면 외부에서 Reference Count가 사라지면 객체의 property의 값 또한 null이 된다.

 

 

5. 객체 할당 및 초기화

이제 실제로 클래스를 사용해보자. 먼저, 객체는 모두 레퍼런스 타입임을 유의해야 한다. 따라서, 객체의 할당 과정인 [Human alloc]을 수행한다. 메모리 할당이 완료되면, 이를 토대로 초기화를 진행한다. 그리고 그 값은 역시 레퍼런스 타입인 포인터에 저장한다.

Human *human = [[Human alloc] initWithName:@"Gong" height:190];

 

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

[Objective-C] 3. 프로토콜(Protocol)  (0) 2022.02.27
[Objective-C] 1. 개요  (0) 2022.02.27