Swift에서 dispatch_once singleton 모델 사용
스위프트에 적합한 싱글톤 모델을 개발 중입니다.지금까지 스레드 이외의 세이프 모델을 입수할 수 있었습니다.
class var sharedInstance: TPScopeManager {
get {
struct Static {
static var instance: TPScopeManager? = nil
}
if !Static.instance {
Static.instance = TPScopeManager()
}
return Static.instance!
}
}
싱글톤 인스턴스를 스태틱구조로 래핑하면 복잡한 명명 스키마 없이 싱글톤 인스턴스와 충돌하지 않는 단일 인스턴스가 가능해져 상당히 비공개로 만들 수 있습니다.확실히 이 모델은 안전하지 않습니다. 덧붙이려고 했어요.dispatch_once'이것'은 다음과 같습니다.
class var sharedInstance: TPScopeManager {
get {
struct Static {
static var instance: TPScopeManager? = nil
static var token: dispatch_once_t = 0
}
dispatch_once(Static.token) { Static.instance = TPScopeManager() }
return Static.instance!
}
}
on on on on on on on on on on on on on on 에 컴파일러 오류가 요.dispatch_once 표시:
식의 형식 'Void'를 형식 '()'으로 변환할 수 없습니다.
여러 가지 다른 종류의 구문을 사용해 봤는데 모두 같은 결과가 나온 것 같습니다.
dispatch_once(Static.token, { Static.instance = TPScopeManager() })
의의 what what what of of of of of of of of of of of of 의 적절한 용법은 입니까?dispatch_onceSwift ★★★★★★★★★★★★★★★★★★★★★★★★★?에 이 줄 요.() 메세지에 , 「이러다 「이러다」, 「이러다」, 「이러다」의 가 될 생각합니다.dispatch_once_t이치노
tl;dr: Swift 1.2 이상을 사용하는 경우 클래스 상수 접근 방식을 사용하고 이전 버전을 지원해야 하는 경우 중첩 구조 접근 방식을 사용합니다.
Swift에 대한 제 경험상, 느린 초기화 및 스레드 안전성을 지원하는 싱글톤 패턴을 구현하기 위한 세 가지입니다.
클래스 상수
class Singleton {
static let sharedInstance = Singleton()
}
은 Swift가 상수 변수)를 lazy하게 에 느린 하며, "Swift"의 .let이것은 싱글톤을 인스턴스화하기 위해 공식적으로 권장되는 방법입니다.
클래스 상수는 Swift 1.2에서 도입되었습니다.이전 버전의 Swift를 지원해야 하는 경우 아래의 중첩 구조 접근법 또는 전역 상수를 사용하십시오.
중첩 구조
class Singleton {
class var sharedInstance: Singleton {
struct Static {
static let instance: Singleton = Singleton()
}
return Static.instance
}
}
여기서는 클래스 상수로 중첩 구조의 정적 상수를 사용합니다.이는 Swift 1.1 이전 버전에서 정적 클래스 상수가 없는 경우의 회피책이며 함수에 정적 상수 및 변수가 없는 경우의 회피책으로도 기능합니다.
디스패치_1회
기존의 Objective-C 접근 방식은 Swift에 이식되었습니다.중첩된 구조 접근법보다 장점이 없다는 것은 확실하지만 구문 차이가 흥미롭기 때문에 여기에 두겠습니다.
class Singleton {
class var sharedInstance: Singleton {
struct Static {
static var onceToken: dispatch_once_t = 0
static var instance: Singleton? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = Singleton()
}
return Static.instance!
}
}
유닛 테스트에 대해서는 이 GitHub 프로젝트를 참조하십시오.
둘 된다는 것을 .dispatch_once)
class WithSingleton {
class var sharedInstance: WithSingleton {
struct Singleton {
static let instance = WithSingleton()
}
return Singleton.instance
}
}
이를 통해 정적 구조 요소의 느리고 스레드 세이프한 자동 초기화를 활용하여 실제 구현을 소비자로부터 안전하게 숨기고 모든 것을 읽기 쉽도록 컴팩트하게 구분하여 가시적인 글로벌 변수를 제거합니다.
애플은 느린 이니셜라이저가 스레드 세이프하다는 것을 명확히 했습니다.★★★★★★★★★★★★★★★★★★,dispatch_once symant (유사 보호)
글로벌 변수(구조체 및 enum의 스태틱멤버도 마찬가지)의 레이지 이니셜라이저는 글로벌에 처음 액세스 할 때 실행되며 초기화가 원자적인지 확인하기 위해 dispatch_1회 실행됩니다.이를 통해 코드 내에서 dispatch_one을 사용하는 쿨한 방법이 가능해집니다.이니셜라이저를 사용하여 글로벌 변수를 선언하고 프라이빗 마크를 붙이기만 하면 됩니다.
Swift 1.2 이상의 경우:
class Singleton {
static let sharedInstance = Singleton()
}
정확성 증명(모든 신용은 여기에 있음)을 통해 싱글톤에 대해 이전 방법을 사용할 이유가 거의 또는 전혀 없습니다.
업데이트: 이제 공식 문서에 설명된 대로 싱글톤을 정의하는 공식 방법이 되었습니다!
의 우려에 대해서static »classstatic해도 좋다class변수를 사용할 수 있게 됩니다.싱글톤은 서브클래스가 되지 않습니다.그것은 베이스 싱글톤의 여러 인스턴스가 발생하기 때문입니다.「」를 사용합니다.static멋지고 재빠른 방법으로 시행하고 있습니다.
Swift 1.0 및 1.1의 경우:
최근 Swift의 변화(대부분의 새로운 접근 제어 방식)에 따라 싱글톤에 대한 글로벌 변수를 보다 깔끔하게 사용하는 쪽으로 기울고 있습니다.
private let _singletonInstance = SingletonClass()
class SingletonClass {
class var sharedInstance: SingletonClass {
return _singletonInstance
}
}
Swift 블로그 기사에서 언급한 바와 같이 다음과 같습니다.
글로벌 변수(구조체 및 enum의 스태틱멤버도 마찬가지)의 레이지 이니셜라이저는 글로벌에 처음 액세스 할 때 실행되며 초기화가 원자적인지 확인하기 위해 dispatch_1회 실행됩니다.이를 통해 코드 내에서 dispatch_one을 사용하는 쿨한 방법이 가능해집니다.이니셜라이저를 사용하여 글로벌 변수를 선언하고 프라이빗 마크를 붙이기만 하면 됩니다.
이 싱글톤 작성 방법은 스레드 세이프, 고속, 레이지이며 ObjC에도 무료로 브리지 됩니다.
이제 Swift 1.2 이후에서는 클래스의 정적 변수/정수를 지원합니다.따라서 정적 상수를 사용할 수 있습니다.
class MySingleton {
static let sharedMySingleton = MySingleton()
private init() {
// ...
}
}
그것을 하는 더 좋은 방법이 있다.클래스 선언 위에 있는 클래스의 글로벌 변수를 다음과 같이 선언할 수 있습니다.
var tpScopeManagerSharedInstance = TPScopeManager()
변수 중 가 "init"으로 호출됩니다.dispatch_once재빠르다레퍼런스를 취득하고 싶은 클래스에서, 다음의 조작을 실시합니다.
var refrence = tpScopeManagerSharedInstance
// or you can just access properties and call methods directly
tpScopeManagerSharedInstance.someMethod()
따라서 기본적으로 공유 인스턴스 코드 블록 전체를 제거할 수 있습니다.
스위프트 싱글톤은 코코아 프레임워크에서 클래스 함수로 노출된다.NSFileManager.defaultManager(),NSNotificationCenter.defaultCenter()g서클른른른른 。
class MyClass {
private static let _sharedInstance = MyClass()
class func sharedInstance() -> MyClass {
return _sharedInstance
}
}
.MyClass.sharedInstance().
Apple의 설명서에 따르면 Swift에서 가장 쉬운 방법은 static type 속성을 사용하는 것이라고 여러 번번이 반복되고 있습니다.
class Singleton {
static let sharedInstance = Singleton()
}
단, 단순한 컨스트럭터 호출을 넘어 추가 셋업을 수행하는 방법을 찾는 경우 즉시 호출된 닫힘을 사용하는 것이 중요합니다.
class Singleton {
static let sharedInstance: Singleton = {
let instance = Singleton()
// setup code
return instance
}()
}
이것은 스레드 세이프가 보장되며 한 번만 느긋하게 초기화됩니다.
스위프트 4 이상
protocol Singleton: class {
static var sharedInstance: Self { get }
}
final class Kraken: Singleton {
static let sharedInstance = Kraken()
private init() {}
}
Apple의 샘플 코드를 보고 이 패턴을 발견했습니다.Swift가 통계학을 어떻게 다루는지 모르겠지만, C#에서는 이 방법이 안전할 것입니다.Objective-C interop의 속성과 방법을 모두 포함합니다.
struct StaticRank {
static let shared = RankMapping()
}
class func sharedInstance() -> RankMapping {
return StaticRank.shared
}
class var shared:RankMapping {
return StaticRank.shared
}
한마디로
class Manager {
static let sharedInstance = Manager()
private init() {}
}
파일과 초기화를 읽을 수 있습니다.
및 의 레이지 했을 때 되며, """ ("enum")"으로 됩니다.
dispatch_once초기화가 원자성이라는 것을 확인합니다.
Objective-C에서 Swift singleton 클래스를 사용할 예정이라면 이 셋업에서는 컴파일러가 적절한 Objective-C 유사 헤더를 생성합니다.
class func sharedStore() -> ImageStore {
struct Static {
static let instance : ImageStore = ImageStore()
}
return Static.instance
}
그런 다음 Objective-C 클래스에서 스위프트 이전의 방식으로 싱글톤을 부를 수 있습니다.
[ImageStore sharedStore];
이것은 단지 나의 간단한 구현입니다.
첫 번째 해결책
let SocketManager = SocketManagerSingleton();
class SocketManagerSingleton {
}
코드 뒷부분:
func someFunction() {
var socketManager = SocketManager
}
두 번째 솔루션
func SocketManager() -> SocketManagerSingleton {
return _SocketManager
}
let _SocketManager = SocketManagerSingleton();
class SocketManagerSingleton {
}
또한 코드 후반부에서 혼란을 줄이기 위해 괄호를 유지할 수 있습니다.
func someFunction() {
var socketManager = SocketManager()
}
final class MySingleton {
private init() {}
static let shared = MySingleton()
}
그럼 불러주세요.
let shared = MySingleton.shared
용도:
class UtilSingleton: NSObject {
var iVal: Int = 0
class var shareInstance: UtilSingleton {
get {
struct Static {
static var instance: UtilSingleton? = nil
static var token: dispatch_once_t = 0
}
dispatch_once(&Static.token, {
Static.instance = UtilSingleton()
})
return Static.instance!
}
}
}
사용방법:
UtilSingleton.shareInstance.iVal++
println("singleton new iVal = \(UtilSingleton.shareInstance.iVal)")
1.2 이상의 스위프트에서 가장 좋은 접근법은 한 줄짜리 싱글톤이다.
class Shared: NSObject {
static let sharedInstance = Shared()
private override init() { }
}
이 접근법에 대한 자세한 내용은 이 링크를 참조하십시오.
Apple Docs(Swift 3.0.1)에서
여러 스레드에 동시에 액세스해도 한 번만 느긋하게 초기화할 수 있는 static type 속성을 사용할 수 있습니다.
class Singleton {
static let sharedInstance = Singleton()
}
초기화를 넘어 추가 설정을 수행해야 하는 경우 폐쇄 호출 결과를 글로벌 상수에 할당할 수 있습니다.
class Singleton {
static let sharedInstance: Singleton = {
let instance = Singleton()
// setup code
return instance
}()
}
는 ★★★★★★★★★★★★★★★★★★★★★★★★★★★를 추천합니다.enum(Java)와할 수 있습니다
enum SharedTPScopeManager: TPScopeManager {
case Singleton
}
참고로 Jack Wu/hpique의 Nested Structure 구현의 Singleton 구현 예를 소개합니다.또, 어카이브(archive)가 어떻게 기능할 수 있는지를 실장하고 있습니다.저는 이 완전한 예를 찾을 수 없었습니다. 그래서 이것이 누군가에게 도움이 되기를 바랍니다!
import Foundation
class ItemStore: NSObject {
class var sharedStore : ItemStore {
struct Singleton {
// lazily initiated, thread-safe from "let"
static let instance = ItemStore()
}
return Singleton.instance
}
var _privateItems = Item[]()
// The allItems property can't be changed by other objects
var allItems: Item[] {
return _privateItems
}
init() {
super.init()
let path = itemArchivePath
// Returns "nil" if there is no file at the path
let unarchivedItems : AnyObject! = NSKeyedUnarchiver.unarchiveObjectWithFile(path)
// If there were archived items saved, set _privateItems for the shared store equal to that
if unarchivedItems {
_privateItems = unarchivedItems as Array<Item>
}
delayOnMainQueueFor(numberOfSeconds: 0.1, action: {
assert(self === ItemStore.sharedStore, "Only one instance of ItemStore allowed!")
})
}
func createItem() -> Item {
let item = Item.randomItem()
_privateItems.append(item)
return item
}
func removeItem(item: Item) {
for (index, element) in enumerate(_privateItems) {
if element === item {
_privateItems.removeAtIndex(index)
// Delete an items image from the image store when the item is
// getting deleted
ImageStore.sharedStore.deleteImageForKey(item.itemKey)
}
}
}
func moveItemAtIndex(fromIndex: Int, toIndex: Int) {
_privateItems.moveObjectAtIndex(fromIndex, toIndex: toIndex)
}
var itemArchivePath: String {
// Create a filepath for archiving
let documentDirectories = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
// Get the one document directory from that list
let documentDirectory = documentDirectories[0] as String
// append with the items.archive file name, then return
return documentDirectory.stringByAppendingPathComponent("items.archive")
}
func saveChanges() -> Bool {
let path = itemArchivePath
// Return "true" on success
return NSKeyedArchiver.archiveRootObject(_privateItems, toFile: path)
}
}
이러한 기능 중 일부를 인식하지 못한 경우, 다음은 제가 사용하고 있는 Swift 유틸리티 파일입니다.
import Foundation
import UIKit
typealias completionBlock = () -> ()
extension Array {
func contains(#object:AnyObject) -> Bool {
return self.bridgeToObjectiveC().containsObject(object)
}
func indexOf(#object:AnyObject) -> Int {
return self.bridgeToObjectiveC().indexOfObject(object)
}
mutating func moveObjectAtIndex(fromIndex: Int, toIndex: Int) {
if ((fromIndex == toIndex) || (fromIndex > self.count) ||
(toIndex > self.count)) {
return
}
// Get object being moved so it can be re-inserted
let object = self[fromIndex]
// Remove object from array
self.removeAtIndex(fromIndex)
// Insert object in array at new location
self.insert(object, atIndex: toIndex)
}
}
func delayOnMainQueueFor(numberOfSeconds delay:Double, action closure:()->()) {
dispatch_after(
dispatch_time(
DISPATCH_TIME_NOW,
Int64(delay * Double(NSEC_PER_SEC))
),
dispatch_get_main_queue()) {
closure()
}
}
싱글톤 클래스는 다음과 같은 방법으로 빠르게 만들 수 있습니다.
class AppSingleton: NSObject {
//Shared instance of class
static let sharedInstance = AppSingleton()
override init() {
super.init()
}
}
저는 이 구현을 선호합니다.
class APIClient {
}
var sharedAPIClient: APIClient = {
return APIClient()
}()
extension APIClient {
class func sharedClient() -> APIClient {
return sharedAPIClient
}
}
스위프트에서의 내 실장 방식은...
Configuration Manager.swift
import Foundation
let ConfigurationManagerSharedInstance = ConfigurationManager()
class ConfigurationManager : NSObject {
var globalDic: NSMutableDictionary = NSMutableDictionary()
class var sharedInstance:ConfigurationManager {
return ConfigurationManagerSharedInstance
}
init() {
super.init()
println ("Config Init been Initiated, this will be called only onece irrespective of many calls")
}
아래와 같이 어플리케이션의 임의의 화면에서 globalDic에 접속합니다.
읽기:
println(ConfigurationManager.sharedInstance.globalDic)
기입:
ConfigurationManager.sharedInstance.globalDic = tmpDic // tmpDict is any value that to be shared among the application
올바른 유일한 접근법은 다음과 같습니다.
final class Singleton {
static let sharedInstance: Singleton = {
let instance = Singleton()
// setup code if anything
return instance
}()
private init() {}
}
접속처
let signleton = Singleton.sharedInstance
이유:
static은 여러 에 동시에 에도 한 되므로 type을 사용할 .dispatch_onceinit다른 클래스에서 인스턴스를 만들 수 없습니다.final다른 클래스가 싱글톤 클래스를 상속하지 않도록 합니다.
함수 David는 것 .instanceMethodlet 같은 일을 하고 있다sharedInstance이 값을 글로벌 상수로 선언하기만 하면 됩니다.
let gScopeManagerSharedInstance = ScopeManager()
class ScopeManager {
// No need for a class method to return the shared instance. Use the gScopeManagerSharedInstance directly.
}
func init() -> ClassA {
struct Static {
static var onceToken : dispatch_once_t = 0
static var instance : ClassA? = nil
}
dispatch_once(&Static.onceToken) {
Static.instance = ClassA()
}
return Static.instance!
}
과거의 싱글톤을 실현하는 것은 글로벌 변수, 내부 변수, 디스패치 세 가지 방법에 지나지 않는다.
여기 좋은 싱글톤 두 개가 있다.(주: 어떤 종류의 글을 쓰든 민영화의 init() 방법에 유의해야 한다.Swift에서는 오브젝트의 컨스트럭터 디폴트가 모두 public이므로 init을 private로 변경할 수 있습니다.이 클래스의 다른 오브젝트는 디폴트 초기화 메서드로 오브젝트를 작성할 수 없습니다.)
방법 1:
class AppManager {
private static let _sharedInstance = AppManager()
class func getSharedInstance() -> AppManager {
return _sharedInstance
}
private init() {} // Privatizing the init method
}
// How to use?
AppManager.getSharedInstance()
방법 2:.
class AppManager {
static let sharedInstance = AppManager()
private init() {} // Privatizing the init method
}
// How to use?
AppManager.sharedInstance
스위프트 5.2
하다, 쓰다, 쓰다, 쓰다, 쓰다, 쓰다, 쓰다, 쓰다, 쓰다, 쓰다, 이런 식으로 수 요.Self : .
static let shared = Self()
그리고 다음과 같은 유형 안에 있어야 합니다.
class SomeTypeWithASingletonInstance {
static let shared = Self()
}
이것은 스레드 세이프 기능을 갖춘 가장 단순한 것입니다.다른 스레드는 원하는 경우에도 동일한 싱글톤 객체에 액세스할 수 없습니다.스위프트 3/4
struct DataService {
private static var _instance : DataService?
private init() {} //cannot initialise from outer class
public static var instance : DataService {
get {
if _instance == nil {
DispatchQueue.global().sync(flags: .barrier) {
if _instance == nil {
_instance = DataService()
}
}
}
return _instance!
}
}
}
저는 제 독신에게 상속을 허락하라고 요구했지만, 실제로 허락한 해결책은 없었습니다.그래서 생각해낸 건
public class Singleton {
private static var sharedInstanceVar = Singleton()
public class func sharedInstance() -> Singleton {
return sharedInstanceVar
}
}
public class SubSingleton: Singleton {
private static var sharedInstanceToken: dispatch_once_t = 0
public class override func sharedInstance() -> SubSingleton {
dispatch_once(&sharedInstanceToken) {
sharedInstanceVar = SubSingleton()
}
return sharedInstanceVar as! SubSingleton
}
}
- 됩니다.
Singleton.sharedInstance()우선 그것은 의 예를 돌려줄 것이다.Singleton - 를 할 때
SubSingleton.sharedInstance()우선 그것은 의 예를 돌려줄 것이다.SubSingleton조했했다 - 「」입니다.
SubSingleton.sharedInstance()Singleton참말이다
첫는 하위 이 이 방법을 할 수 입니다.dispatch_once_t, 「 」가 「 」를 확인해 주세요.sharedInstanceVar1번으로 하다.
좀 더 다듬어 보겠습니다만, 이것에 대해 강한 감정을 가지고 있는 사람이 있는지 어떤지(수동으로 갱신할 필요가 있는 것 이외에는) 확인해 보는 것도 재미있을 것 같습니다.
이것이 나의 실장입니다.또한 프로그래머가 새 인스턴스를 만드는 것도 방지합니다.
let TEST = Test()
class Test {
private init() {
// This is a private (!) constructor
}
}
다음 구문을 사용합니다.
public final class Singleton {
private class func sharedInstance() -> Singleton {
struct Static {
//Singleton instance.
static let sharedInstance = Singleton()
}
return Static.sharedInstance
}
private init() { }
class var instance: Singleton {
return sharedInstance()
}
}
이는 Swift 1.2부터4까지 동작하며 다음과 같은 장점이 있습니다.
- 구현 서브클래스를 사용하지 않도록 사용자에게 경고합니다.
- 추가 인스턴스 생성 방지
- 느린 생성과 고유한 인스턴스화를 보장합니다.
- 을 허용하여 을합니다.
Singleton.instance
언급URL : https://stackoverflow.com/questions/24024549/using-a-dispatch-once-singleton-model-in-swift
'programing' 카테고리의 다른 글
| 부트스트랩3의 sr-only는 무엇입니까? (0) | 2023.04.19 |
|---|---|
| 여러 줄 셸 변수를 지정하려면 어떻게 해야 합니까? (0) | 2023.04.19 |
| 변경을 잃지 않고 마지막으로 푸시되지 않은 git 커밋을 언커밋하는 방법 (0) | 2023.04.19 |
| 특정 파일을 변경한 모든 커밋을 나열하려면 어떻게 해야 합니까? (0) | 2023.04.14 |
| 동적 셀 액세스 (0) | 2023.04.14 |