简体   繁体   English

如何在Swift中的单例类中使用NSCoding

[英]How can I use NSCoding with a singleton class in Swift

For the user model in my iOS app, I use a singleton. 对于我的iOS应用中的用户模型,我使用单例。 I want to save the user object with NSCoding . 我想用NSCoding保存用户对象。

No problem to save it but how assign the decoded user to the shared instance of my singleton? 保存它没问题,但是如何将解码后的用户分配给我的单例的共享实例?

And another question, is it a good idea to use singleton for user object? 还有一个问题,对用户对象使用单例是个好主意吗?

What you need to do is an unorthodox approach to the singleton pattern implementation. 您需要做的是一种非常规的单例模式实现方法。 Usually in swift you do this: 通常,您很快就会这样做:

class MySingleton {
static let sharedInstance = MySingleton()
    init() {
       println("BBB")
    }
}

You cannot use it this way because all the setup work is deferred to the initialiser whereas you want to do some conditioning before you actually create the instance. 您不能以这种方式使用它,因为所有设置工作都推迟到了初始化程序,而您想在实际创建实例之前进行一些调整。 The easiest way to do what you need and preserve thread-safety is to use dispatch_once from the depths of apple's C library: 做您需要的并保持线程安全的最简单方法是从Apple的C库的深处使用dispatch_once:

class MySingleton : NSObject {
    class var sharedInstance: MySingleton {
        struct Statics {
            static var instance: MySingleton? = nil
            static var dispatchOnceToken: dispatch_once_t = 0
        }

        dispatch_once(&Statics.dispatchOnceToken) {
           if let data: NSData = .... (get your data here) {
               let decodedInstance = NSKeyedUnarchiver.unarchiveObjectWithData(data: data) as! MySingleton
           Statics.instance = decodedInstance
           } else {
              Statics.instance = MySingletion()
           }
        }
        return Statics.instance!
    }
}

As a side note - what I usually do is that I use Core Data object for modelling user and therefore save myself lots of pain with persistence. 附带说明-我通常要做的是使用Core Data对象对用户进行建模,因此避免了持久性困扰。 I keep user as a field on some singleton class dedicated to keeping general application state, access tokens, etc. The class initialiser recovers user object from persistence and assigns it to it's field. 我将用户作为字段保留在某个单例类中,该类专门用于保持常规应用程序状态,访问令牌等。类初始化程序从持久性中恢复用户对象,并将其分配给它的字段。

And last but not least - always think twice before introducing any singleton into the app, as this pattern can so easily be abused! 最后但并非最不重要的一点-在向应用程序中引入任何单例之前,请三思而后行,因为这种模式很容易被滥用!

Meh. In principle, no, this is possibly bad form, but in practice I've had very good success with it, and have had to go to great contortions in code bases where I didn't do it this way. 原则上,不,这可能是不好的形式,但是在实践中我取得了很好的成功,并且不得不在代码库中大加修改,而我不是这样做的。 Singletons are a venerable part of Cocoa. 单身人士是可可的古老部分。 There's a broad movement (myself included) trying to move away from them, but it's not always clear that the pain is worth it. 有一个广泛的运动(包括我自己)试图摆脱他们,但并非总是很清楚痛苦是值得的。 I'm not going to make much noise about whether you should or shouldn't here, let's talk about how. 我不会在您是否应该在这里大吵大闹,让我们来谈谈如何做。

The answer is to remember that Cocoa singletons are not Singletons. 答案是要记住,可可单身人士不是单身人士。 They're "shared singletons." 他们是“共享单身人士”。 They're just some instance. 他们只是一个例子。 So set it. 所以设置它。

struct User {
    static var sharedUser = User()
}

func decodeSomething() {
    User.sharedUser = ... some decoded user ...
}

This form isn't thread safe, which can be fine. 这种形式不是线程安全的,可以。 If you need it to be thread-safe you can do that in the usual ways ( dispatch_sync , dispatch_barrier_async ). 如果您需要它是线程安全的,则可以按照通常的方式( dispatch_syncdispatch_barrier_async )进行操作。 And you can add a didSet handler if you want to post a notification or notify observers some other way that the user has changed. 如果要发布通知或以其他方式通知观察者用户已更改,则可以添加didSet处理程序。 But this whole approach works fine. 但是,整个方法很好用。

As you have more experience, you will probably decide that you hate this for some reason that you can't exactly articulate, vaguely retailed to "testability" (many of us do), and you'll come up with other solutions. 随着您拥有更多的经验,您可能会由于某种原因而讨厌这种做法,因为您无法准确表达,或者隐约零售到“可测试性”(我们中的许多人这样做),并且您会提出其他解决方案。 But really this is fine. 但这真的很好。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM