2

What is the best way to declare global variables in Swift? I am using Singletons to hold objects in memory. Besides I can access them from everywhere.

But since arrays are not thread-safe in swift, does this pattern also tackle concurrency? Are there better ways of storing e.g. network resources in global properties?

E.g.

class Repository {

    static let sharedInstance = Repository()

    var objects:[String] = []
}
midori
  • 450
  • 6
  • 19
  • 4
    Unrelated to the question at hand, this convoluted method of declaring a singleton dates back to Swift 1.x, but is no longer needed. Just `class Repository { static let sharedInstance = Repository() }` is all you need nowadays. – Rob Jul 30 '16 at 18:38
  • 2
    Re concurrency, no this is not thread-safe. To make this thread-safe, you'd make the `objects` private, and then define your own methods to retrieve and update that which is synchronized (using GCD or locks). – Rob Jul 30 '16 at 18:40
  • If you require thread safety to access properties or arrays then I recommend you implement a serial GCD queue to control that access. – Robotic Cat Jul 30 '16 at 18:41
  • Re "are there better ways of storing", this is a matter of opinion and debate, not welcomed here on Stack Overflow, but let it suffice to say that while singletons enjoy a certain convenience, they are often criticized for not making dependencies clear and explicit, making it difficult to track down issues and/or perform unit testing. Many would employ "dependency injection" to avoid using singletons. If you Google "why singletons are evil" and "dependency injection", it might lead you to appropriate resources. – Rob Jul 30 '16 at 18:45
  • That means that I have to implement getters / setters and maybe append / remove methods for each property. Is there a more elegant way without blocking all properties at once ? – midori Jul 30 '16 at 18:49
  • Sounds interesting @Rob. I will take a look. – midori Jul 30 '16 at 18:52
  • @midori You can have separate synchronization mechanisms (queue, lock, etc.) for each property, if you want. You don't have to limit yourself to a single synchronization mechanism for the whole `Repository`. – Rob Jul 30 '16 at 19:50

1 Answers1

1

Reading an array across threads is safe. It's the writing that is not. See this question for how to access array in thread-safe manner.

Your method to implement a shared instance is too verbose and will be deprecated in Swift 3. Use lazy initialization instead:

class Repository {
    static var sharedInstance = { Void -> Repository in
        let tmp = Repository()
        tmp.objects = ["Hello", "World"]
        return tmp
    }()

    var objects:[String] = []
}
Community
  • 1
  • 1
Code Different
  • 90,614
  • 16
  • 144
  • 163