Я работаю над проектом, в котором у меня есть требования по использованию синглтона.
при их использовании я придерживался следующего кода
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 делает что-то великое за кулисами? Скажите, пожалуйста, если кто-нибудь знает