[iOS] Singleton 과 Type Property

김상우·2022년 5월 20일
0

Singleton Pattern (싱글톤) 이란

  • A 라는 클래스가 있을 때, 앱 전체에서 특정 용도로 하나의 인스턴스만 생성해서 공용으로 사용하고 싶을때 사용하는 디자인 유형

Type Property (타입 프로퍼티)

  • 클래스 , 구조체 , 열거형에서 사용된다.

  • 저장 타입 프로퍼티, 연산 타입 프로퍼티가 있다.

class Human {
    static let name: String = "ksw"     // 저장 타입 프로퍼티
    static var alias: String {             // 연산 타입 프로퍼티
        return name + "hello"
    }
}
  • static 을 사용하면 오버라이딩 불가능, class 를 사용하면 오버라이딩이 가능하다.

  • 타입 프로퍼티는 인스턴스가 생성될 때마다 "매번 생성"되는 "기존 프로퍼티"와 다르다.

  • 인스턴스가 생성된다고 매번 해당 인스턴스의 멤버로 매번 생성되는 것이 아니라, 언제 누가 한번 불러서 메모리에 올라가면 그 뒤로는 생성되지 않고, 언제 어디서든 이 타입 프로퍼티에 접근할 수 있게 된다.


타입 프로퍼티로 싱글톤 만들기

  • 타입 프로퍼티를 사용해서 싱글톤을 만들면 이렇게 만들 수 있다.
class MyClass {
	static let shared = MyClass()
  	var someValue: Int?
} 
  • shared 는 타입 프로퍼티이기 때문에 단 한번만 생성되고 그 뒤로는 참조가 된다. -> Singleton

  • 사용은 다음과 같이 할 수 있다.

    -> AViewController.swift

let myClass = MyClass.shared
myClass.someValue = 100

-> BViewController.swift

let myClass = MyClass.shared
print(myClass.someValue)	// 100

타입 프로퍼티에 대해 오해했던 것

개발하고 있는 앱에서 다음과 같이 뒤로가기 버튼을 공통적으로 사용할 일이 많아서 다음과 같은 클래스를 정의했었다. 각각 AViewController.swift, BViewController.swift 의 모습이다.

플로우 : Home -> A -> B

즉 B에서 뒤로가기를 누르면 화면 A가, A에서 뒤로가기를 누르면 Home 이 나와야한다.

// Fooiy 라는 앱에서 사용할 버튼들
class FooiyButtons {
    // 타입 프로퍼티
    static let backButton: UIButton = {
        let button = UIButton()
        let image = UIImage(named: "Icon_arrow")
        button.setImage(image, for: .normal)
        return button
    }()
    
}

그래서 위와 같이 FooiyButtons 안에 타입 프로퍼티로 backButton 을 정의하고 AViewController.swift 와 BViewController.swift 에서 이렇게 사용했다.

  • A.ViewController.swift
// FooiyButtons 클래스의 타입 프로퍼티를 가져온다.
let backButton = FooiyButtons.backButton

// 클릭하면 pop ViewController
backButton.rx.tap.bind{ [weak self] in
    guard let self = self else { return }
    self.navigationController?.popViewController(animated: true)
    print("log1")
}.disposed(by: disposeBag)
  • B.ViewController.swift
// FooiyButtons 클래스의 타입 프로퍼티를 가져온다.
let backButton = FooiyButtons.backButton

// 클릭하면 pop ViewController
backButton.rx.tap.bind{ [weak self] in
    guard let self = self else { return }
    self.navigationController?.popViewController(animated: true)
    print("log2")
}.disposed(by: disposeBag)

즉, 같은 코드를 서로 다른 곳에 2번 작성했다.

그런데 B에서 뒤로가기 버튼을 한 번 눌렀을때, A로 돌아가는 것이 아니라, Home 까지 2번 뒤로가게 되는 현상이 발생했다.

왜냐하면 A에서 이미 FooiyButtons 의 backButton 을 선언했는데, B에서 새롭게 FooiyButtons.backButton 을 선언한다고 해서 별개의 버튼이 생성되는 것이 아니기 때문이었다.

다시 말하면, 타입 프로퍼티는 메모리에 한번 올라가면 그 뒤로는 생성되지 않고, 다른 곳에서 그 타입 프로퍼티에 접근하기 때문 !

B에서 backButton 을 누르면 BViewController.swift 의 popViewController 도 실행이 되고, AViewController.swift 의 popViewController 도 실행이 되기 때문에 2번 뒤로가게 되는 현상이 발생하게 되는 거였다.


profile
안녕하세요, iOS 와 알고리즘에 대한 글을 씁니다.

0개의 댓글