특정 용도로 객체를 하나만 생성해서 공용으로 사용하고 싶을 때 사용하는 디자인 유형
하나의 프로그램에서 단 하나의 객체만 있어도 되는 경우 해당 객체를 한번만 생성하고 모든 곳에서 접근 가능하게 해주는 패턴이다. 싱글턴 패턴을 사용할 객체는 한번만 생성되어야 하고 모든 곳에서 접근이 가능한 전역 변수여야 한다.
private으로 한번만 생성하도록 해야하고 static을 통해 타입 프로퍼티를 선언해야 한다. iOS에서 많이 사용하는 방법 중 하나이다.
(단점이라기보다 주의할 점에 가깝다.)
The free function dispatch_once is no longer available in Swift. In Swift, you can use lazily initialized globals or static properties and get the same thread-safety and called-once guarantees as dispatch_once provided.
objective-c에서 싱글턴을 생성할 때는 dispatch_once를 이용해서 한번만 불리게 해야 하는 작업이 필요하다. 다른 언어에서도 마찬가지지만 싱글턴에르 생성하는 것은 멀티 쓰레딩 환경에서 Thread-Safe하지 않다. 즉, 여러 쓰레드가 동시에 여러 싱글턴을 생성하게 되면 경우에 따라서 Instance가 2개, 3개가 생성될 수 있다.
그러나 Swift의 경우 별도의 작업을 해주지 않아도 static을 사용해서 타입 프로퍼티로 인스턴스를 생성하면 사용 시점에 lazy가 되므로 최초 생성되기 전까지는 메모리에 올라가지 않고 Dispatch_once도 자동 적용된다. (별다른 추가적인 작업이 필요 없이 Instance가 여러개 생성되지 않는 Thread-Safe한 방법이 된다.)
let screen = UIScreen.main
let userDefault = UserDefaults.standard
let application = UIApplication.shared
let fileManager = FileManager.default
let notification = NotificationCenter.default
이렇게 사용할 수 있다.
class UserInfo {
var id: String?
var password: String?
var name: String?
}
-> User의 정보를 저장하는 클래스
// A ViewController
let userInfo = UserInfo()
userInfo.id = "SOKYTE"
// B ViewController
let userInfo = UserInfo()
userInfo.password = "123"
// C ViewController
let userInfo = UserInfo()
userInfo.name = "SOKYTE"
만약, 이런 식으로 A, B, C View Controller에서 각각 Info를 수정한다면 원하는 구현방식이 아닐 것이다. 하나의 인스턴스에서 정보가 저장되어야 하므로 최초 생성될 때 한번만 생성해서 전역에 두고 이후로는 해당 인스턴스에 접근 가능하도록 해야한다.
class UserInfo {
static let shared = UserInfo()
var id: String?
var password: String?
var name: String?
}
static을 이용해 인스턴스를 저장할 프로퍼티를 하나 생성하고
class UserInfo {
static let shared = UserInfo()
var id: String?
var password: String?
var name: String?
private init() { }
}
혹시라도 init 함수를 호출해서 Instance를 또 생성하는 것을 막기 위해 init() 함수 접근 제어자를 private로 지정하면 된다.
// A ViewController
let userInfo = UserInfo.shared
userInfo.id = "SOKYTE"
// B ViewController
let userInfo = UserInfo.shared
userInfo.password = "123456"
// C ViewController
let userInfo = UserInfo.shared
userInfo.name = "SOKYTE"
어느 클래스에서든지 shared라는 static 프로퍼티로 접근하면 하나의 인스턴스를 공유할 수 있다.