Синглтон и их синхронизация в быстром - PullRequest
0 голосов
/ 25 января 2019

Я работаю над проектом, в котором у меня есть требования по использованию синглтона. при их использовании я придерживался следующего кода

struct User{
    var someUserProperty: String?{
        willSet{
            print(UserManager.shared.sharedUser ?? "")
        }
    }
}

class UserManager{

    static var shared: UserManager = UserManager()

    public var sharedUser: User?

    /* Private to make this class singleton */
    private init() {
        self.sharedUser = User(someUserProperty: "someInitialValue")
    }

}

class Managers{
    static var userManager = UserManager.shared
}

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        Managers.userManager.sharedUser?.someUserProperty = "someDifferentValue"
    }

}

Этот код выдает ошибку в viewDidLoad, так как он устанавливает свойство User, и в наблюдателе этого свойства мы получаем тот же User объект.

Чтобы решить эту проблему, я искал и получил решение, которое привело меня к модификации в UserManager следующим образом

class UserManager{

    private let concurrentQueue = DispatchQueue(label: "ConcurrentQueue", attributes: .concurrent, target: nil)

    static var shared: UserManager = UserManager()

    public var sharedUser: User?{
        get{
            return concurrentQueue.sync {
                return self.privateSharedUser
            }
        }set{
            concurrentQueue.async(flags: .barrier){[unowned self] in
                self.privateSharedUser = newValue
            }
        }
    }

    private var privateSharedUser: User?

    /* Private to make this class singleton */
    private init() {
        self.sharedUser = User(someUserProperty: "someInitialValue")
    }

}

Я использовал очередь отправки, чтобы разрешить чтение из разных мест, но запись в режиме барьера, чтобы он не прерывал операции чтения. и это сработало.

Но также работает следующее решение, и это заставляет меня задуматься, потому что теперь я удалил все задачи с очередями и просто поставил get и set.

class UserManager{

    private let concurrentQueue = DispatchQueue(label: "ConcurrentQueue", attributes: .concurrent, target: nil)

    static var shared: UserManager = UserManager()

    public var sharedUser: User?{
        get{
            return self.privateSharedUser
        }set{
            self.privateSharedUser = newValue
        }
    }

    private var privateSharedUser: User?

    /* Private to make this class singleton */
    private init() {
        self.sharedUser = User(someUserProperty: "someInitialValue")
    }

}

Я думаю, что вышеприведенный код делает просто создание оболочки с именем sharedUser вокруг фактической переменной privateUser. Поэтому, когда мы устанавливаем что-то на sharedUser за сценой, это даст вам приватный privateSharedUser, адрес которого отличается от sharedUser. Это причина? Или Swift делает что-то великое за кулисами? Скажите, пожалуйста, если кто-нибудь знает

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...