^(코딩캣)^ = @"코딩"하는 고양이;

[번역글] Thread-safe한 싱글톤(singleton) 패턴과 그 사용법(2)

Language/Objective-C & Swift
2021. 9. 24. 09:40

이 글은 Sachithra Siriwardhane 님의 글 Thread-safe singletons and their usage in Swift를 바탕으로 작성되었습니다.

Thread-safe한 싱글톤(singleton)과 그 사용법

개발자라면 다들 ‘싱글톤 패턴(singleton pattern)’에 대해 알고 있을 것이고 사용해 보셨을 것이며, iOS 어플리케이션에서 구현이 가능하실 것입니다. 이 글은 입문자 또는 싱글톤 디자인 패턴(design pattern)을 적절하게 사용하기 위한 배경 지식 향상을 원하는 분들에게 도움이 되어 드리고자 작성되었습니다. 이 글에서는 다음과 같은 주제들을 다뤄볼 것입니다.

 

Swift/Objective-C에서 싱글톤 패턴의 작성

다음 소스는 데이터를 수집하여 관련된 호출자에게 이 데이터를 반환하기 위해 준비된 EventLogger 클래스를 싱글톤으로 작성한 기본적인 예제입니다.

// Swift
import Foundation

final public class EventLogger {
    public static let shared = EventLogger()
    
    private var eventFired: [String: Any] = ["initialization":"Property initialized"]
    
    private init() {
    }
    
    private func readLog(for key: String) -> String? {
        return eventFired[key] as? String
    }
    
    private func writeLog(key: String, content: Any) {
        eventFired[key] = content
    }
}

아래는 Swift 코드에 해당하는 Objective-C 코드이지만 완전히 일치하지는 않을 것입니다.

// Objective-C
@interface EventLogger : NSObject
@end

@implementation EventLogger {
    NSDictionary * eventFired;
}

+ (instancetype)sharedEventLogger {
    static dispatch_once_t once = 0;
    static id sharedInstance = nil;
    
    dispatch_once(&once, ^{
        sharedInstance = [[self alloc] init];
    });
    
    return sharedInstance;
}

- (instancetype)init {
    if (self = [super init]) {
        self->eventFired = [[NSDictionary alloc] initWithObjectsAndKeys:@"initialization",@"Property initialized", nil];
    }
    return self;
}

- (void)dealloc {
    // ...
}

- (NSString *)readLogForKey:(nonnull NSString *)key {
    return [self->eventFired valueForKey:key];
}

- (void)writeLogForKey:(nonnull NSString *)key andContent:(nullable id)content {
    [self->eventFired setValue:content forKey:key];
}
@end

여기서 EventLogger는 파생 클래스가 생겨나지 않도록 final 키워드로 선언되었습니다.

 

public static let shared = EventLogger()

shared라고 이름이 적힌 이 상수는 EventLogger 클래스형 인스턴스를 참조하는 싱글톤입니다. 여기서 static 키워드는 클래스 자체에 소속된 프로퍼티이지 그 클래스의 인스턴스에 소속된 프로퍼티가 아니라는 뜻입니다. 이는 해당 프로퍼티를 보다 전역적인 범위에서 접근 가능하도록 해 줍니다.

 

private init()

클래스의 생성자는 클래스 외부에서 새 인스턴스가 만들어지지 못하도록 private로 선언되었는데 이는, 이 클래스의 생성자가 이 클래스 내부적으로만 호출될 수 있도록 보장해 줍니다.

 

다음은 싱글톤이 사용되는 예입니다. readLog 메소드가 옵셔널 문자열을 반환함에 따라 값을 ‘언랩(unwrap)’하여 사용하기 위해 옵셔널 바인딩이 사용되었습니다.

// Swift
if let contents = EventLogger.shared.readLog(for: "initialization") {
    print(contents)
} else {
    print("File not found")
}
// Objective-C
NSString * contents = [[EventLogger sharedEventLogger] readLogForKey:@"initialization"];

if (contents != nil) {
    NSLog(contents);
} else {
    NSLog(@"File not found");
}

 

카테고리 “Language/Objective-C & Swift”
more...