Jeffery Thomas Jeffery Thomas - 5 months ago 25
Swift Question

Convenience Failable Initializers assign self

I'm trying to write a initializer for NSURL which can throw on failure.

I would very much like it to look like this.

extension NSURL {
convenience init?(string: String, throwOnNil: Bool) throws {
if let URL = NSURL(string: string) {
self = URL
} else if throwOnNil {
throw MyURLError(string: string)
} else {
return nil
}
}
}


But that syntax is no longer supported:
error: cannot assign to value: 'self' is immutable
.


That syntax only works for struct and enum.

Here is the only thing I've come up with

extension NSURL {
convenience init?(string: String, throwOnNil: Bool) throws {
if throwOnNil && NSURL(string: string) == nil {
throw MyURLError(string: string)
}

self.init(string: string)
}
}


Which constructs the URL twice.

HELP! There must be a better approach that I'm not finding.




UPDATE

It turns out that self assignment in an initializer works for structs and enums but not for classes. The example I was basing my ideal code from was a struct.

Answer

Have you considered a factory method on NSURL? It gets you most of the way there.

extension NSURL {
  static func initialize(string: String, throwOnNil: Bool) throws -> NSURL? {
    if let URL = NSURL(string: string) {
      return URL
    } else if throwOnNil {
      throw MyURLError(string: string)
    } else {
      return nil
    }
  }
}
Comments