title: Swift - Singleton without global access
body: <p>I want to create a Swift Singleton without global access. The pattern which I want to create is to assure that always just one instance of a class exists but this class should not be accessible over the usual global <code>MyClass.shared</code> syntax. The reason for this is that I want the class to be fully and correctly testable (which is not really possible with global Singletons). I will then use dependency injection to pass the single instance from viewcontroller to viewcontroller. So the "access" issue is solved without a global static instance.</p>
  
  <p>What I could do is to do basically - nothing. Just create a normal class and trust on the discipline of all developers to not instantiate this class again and again but use it only injected as a dependency. But I would rather have some compiler enforced pattern which prohibits this.</p>
  
  <p>So the requirement is:</p>
  
  <ul>
  <li>assure during compile time that only one instance of a class is instantiated </li>
  <li>no global access</li>
  <li>the assurance that only one class is instantiated should not be enforced during Unit Tests, so it's possible to test it correctly</li>
  </ul>
  
  <p>My first attempt to solve this was something like this:</p>
  
  <p><a href="https://i.stack.imgur.com/el1Xq.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/el1Xq.png" alt="enter image description here"></a></p>
  
  <pre><code>class WebService {
      private static var instances = 0
  
      init() {
          assertSingletonInstance()
      }
  
      private func assertSingletonInstance() {
          #if DEBUG
          if UserDefaults.standard.bool(forKey: UserDefaultsKeys.isUnitTestRunning.rawValue) == false {
              WebService.instances += 1
              assert(WebService.instances == 1, "Do not create multiple instances of this class. Get it thru the shared dependencies in your module.")
          }
          #endif
      }
  }
  </code></pre>
  
  <p>Remark: passing an argument during launch creates a user defaults value which can be checked during runtime. This is how I know that the current run is a unit test.</p>
  
  <p>Generally this pattern works quite good. My only problem with this - I have to duplicate this code over and over again for every possible singleton. Which is not nice. I would prefer a reusable solution.</p>
  
  <h2>Singleton Protocol Extension</h2>
  
  <p>One solution for this was to create a Protocol Extension:</p>
  
  <pre><code>protocol Singleton {
      static var instances: Int { get set }
      func assertSingletonInstance()
  }
  
  extension Singleton {
      // Call this assertion in init() to check for multiple instances of one type.
      func assertSingletonInstance() {
          if UserDefaults.standard.bool(forKey: UserDefaultsKeys.isUnitTestRunning.rawValue) == false {
              Self.instances += 1
              assert(Self.instances == 1, "Do not create multiple instances of this class. Get it thru the shared dependencies in your module.")
          }
          #endif
      }
  }
  </code></pre>
  
  <p>And then use it in this way:</p>
  
  <pre><code>class WebService: Singleton {)
      static var instances = 0
  
      init() {
          assertSingletonInstance()
      }
  }
  </code></pre>
  
  <p>The problem with this approach is that the <code>instances</code> variable is not <code>private</code>. So someone could just set this variable to 0 before instantiating the class and the check would not work anymore.</p>
  
  <h2>Singleton Base Class</h2>
  
  <p>The other attempt was a <code>Singleton</code> base class. In this case a <code>private static var instances</code> can be used. </p>
  
  <pre><code>class Singleton {
      private static var instances = 0
  
      required init() {
          assertSingletonInstance()
      }
  
      private func assertSingletonInstance() {
          #if DEBUG
              if UserDefaults.standard.bool(forKey: UserDefaultsKeys.isUnitTestRunning.rawValue) == false {
                  Singleton.instances += 1
                  assert(Singleton.instances == 1, "Do not create multiple instances of this class. Get it thru the shared dependencies in your module.")
              }
          #endif
      }
  } 
  </code></pre>
  
  <p>The problem with this approach is - it does not work. Incrementing <code>Singleton.instance</code> adds 1 to the <code>static instances</code> of the <code>Singleton</code> type and not to the class which derives from the <code>Singleton</code> base class.</p>
  
  <p>Now I am left with either doing <em>nothing</em> and relying on the discipline and understanding of all developers or at least use the protocol extension with <code>internal</code> or <code>public</code> access. </p>
  
  <p>A sample implementation can be found <a href="https://github.com/DarkoDamjanovic/SolidRock.AppTemplate.iOS" rel="nofollow noreferrer">here</a>.</p>
  
  <p>Maybe someone has better ideas for a really clean solution to this problem. I appreciate any hints or a discussion about it. Thanks.</p>