Swift - create custom class of type `Array`

2019-08-11 08:57发布

问题:

How can I create a custom class in swift that is of type Array? To be exact, I have a custom class of type Car, and now I want to create a singleton that is an array of Cars. (Because I want to be able to access it from anywhere in my app).

My workaround is to define my singleton as NSMutableArray. But I see that causes my some problems in my code. So I wish to define it as swift array. How can I do it?

My code now is:

class MyCars: NSMutableArray {
    class var sharedInstance: MyCars {
        struct Static {
            static var instance: MyCars?
            static var token: dispatch_once_t = 0
        }

        dispatch_once(&Static.token) {
            Static.instance = MyCars()
        }

        return Static.instance!
    }
}

回答1:

To create a singleton array of Car you don't need to create a new class - just a struct with a static member:

struct MyCars {
    static var sharedInstance = Array<Car>()
}

Note that the sharedInstance is initialized once - read this answer for more info

Addendum

In case you want to use MyCars to refer to an array of Car, you can just define a typealias and use a different name for the struct containing the singleton, such as:

typealias MyCars = Array<Car>

struct Singleton {
    static var myCars = MyCars()
}


回答2:

As I understand it, a singleton represents a class or structure for which there can be only one instance, ever. Even if someone tries to instantiate a new copy of the singleton they will wind up with a pointer back to the sole instance. (I got that idea from the Big Nerd Ranch Guide to iOS Programming, but it doesn't appear to be controversial). I don't think that the struct solution proposed above meets this criteria. For example, in a playground create the the suggested struct (I've substituted 'String' type for 'Car' type to make testing easier):

struct MyCars {
    static var sharedInstance = Array<String>()
}

Then initialize the structure and show that the initialization "took":

MyCars.sharedInstance = ["Granada", "Pinto", "Chevette"]
println( MyCars.sharedInstance )
// prints all three car names

Now try to create a copy of the data and show it works, then modify the copy:

var myCars = MyCars.sharedInstance
println( myCars )
// the above prints all three cars
myCars.append("Gremlin")

Do the two variables point to different sets? Test:

println( MyCars.sharedInstance )
// the above prints three cars
println( myCars )
// the above prints four cars 

So, in a Playground environment you do not get a singleton using a struct with a static var. This is unfortunate, as it would otherwise be a very simple way to implement a singleton array. I'm having big difficulties with this problem. A partial solution has been spelled out in this post. In this solution you do get to reference the singleton using subscripts (so the singleton is somewhat array-like). But other array features (e.g. normal assignments) are missing. That is, you can't use the following:

MySingletonClass.sharedInstance = [ "Granada", "Pinto", "Chevette" ]

Note: I'm pretty new to Swift; the above assertions don't carry much authority. There are changes going from Swift 1.1 to Swift 1.2 in how singletons are defined and those changes are summarized here. The mechanism used by Swift 1.1 to define singletons is confusing, but Martin Rue has a very readable, step-by-step development spelled out here.

Good luck! - George