Is there any way to throw error from singleton class init?

Hi..i am trying to create a singleton class .Inside init function/constructor of singleton class some operation is being performed. if any of the operation fails then i have to throw error.
Sample code for the singleton:

//Singleton class
public class Singleton {
    // This line is throwing error which is correct because we are not handle error
    public static let singleton = Singleton()
    //
    private init() throws {
        //Custom error
        throw Custom(code: 19, message: "Message",kind: .customerror)
       print("Hello")
    }
   deinit {
        //
        print("Deinit")
    }   
}
Error :
Call can throw, but errors cannot be thrown out of a global variable initializer

Other version :

//Singleton class
public class Singleton {
    
    public static let singleton = {
       do {
            return try Singleton();
       } catch {
          print(error)
       }
      return nil
    }()
    //
    private init() throws {
        throw Custom(code: 19, message: "Message",kind: .customerror)
       print("Hello")
    }
   deinit {
        //
        print("Deinit")
    }
}

In above code i am able to catch error inside closure but not able to throw error from closure .
I want to do something like this

//
do {
  try Singleton. singleton
 } catch {
  // Catch error here
 print(error)
} 

From my current understanding it seem's i cannot catch error .only way i found to check whether there is error or not is to check if value of singleton property is nil or not .
if value of singleton property is nil then there is error .i have to create another property storing error in the Singleton class so the user can check error message .

Question :
Is there any other method available for throwing error from singleton class ?

You could define your singleton as a Result:

public static let singleton: Result<Singleton, Error> = Result { try Singleton() }

Then every time you access it you do it like this:

try Singleton.singleton.get()

And it'll throw an error if an error was thrown by the initialiser.

I'd suggest however you make the let private and wrap it in a helper static function. This way clients don't have to see the get():

public static func singleton() throws -> Singleton {
    try _singleton.get()
}
...
try Singleton.singleton()

The wrapper has to be a function since you can't throw from a property.

1 Like

We're still missing some details about what your singleton is meant to do. What does it mean to access a singleton that could throw on construction?

When singletons are defined this way (static immutable properties that never change) then they are set up once for the entire lifetime of the process. Whatever result came out of trying to construct it will be there with no way to kick start it to try again. @michelf's, Result example is quite nifty in this regard. Though you'd need to handle the possibility of the error everywhere you access the singleton...even though the possibility would have only ever occurred once.

When I've needed to resort to global constant instances like this that could throw on construction, I've just used try! because the instance itself was so critical to the application that if it failed on construction then there's nothing the app could do safely anyway. The crash report would contain the error and I could triage it as needed.

But if the instance is some auxiliary helper of some kind (maybe a custom logging subsystem?) then using Result or even just Optional with nil coalescing in the case of failure could be fine, too. This assumes the callers that use the singleton reference wouldn't be bothered too much if the instance just wasn't there.

Terms of Service

Privacy Policy

Cookie Policy