"Unable to override" init "that was marked as unavailable" prevents overriding an empty init

I have a situation where I am trying to override NSError to provide me with an instance of the error. I am going to reuse a lot.

My code worked until I updated Xcode and converted to Swift 2.

 public class NAUnexpectedResponseTypeError: NSError { public convenience init() { let messasge = "The object fetched by AFNetworking was not of an expected type." self.init( domain: "MyDomain", code: 6782, userInfo: [NSLocalizedDescriptionKey: messasge] ) } } 

The compiler says Cannot override 'init' which has been marked unavailable . I was able to crack it by doing this:

 public class NAUnexpectedResponseTypeError: NSError { public class func error() -> NSError { let message = "The object fetched by AFNetworking was not of an expected type." return NAUnexpectedResponseTypeError( domain: "MyDomain", code: 6782, userInfo: [NSLocalizedDescriptionKey: message] ) } } 

So my question is:

  • Is there a way to add an empty init method in this situation?
  • If yes to 1, is this a bad idea for some reason?
  • Is my workaround with a class method an appropriate way to fix this problem?

EDIT:

I came up with another workaround that I like better than a workaround using the class method. I'm still not happy that I cannot override the empty init method.

 public class NAUnexpectedResponseTypeError: NSError { public convenience init(message: String?) { var errorMessage: String if let message = message { errorMessage = message } else { errorMessage = "The object fetched by AFNetworking was not of an expected type." } self.init( domain: "MyDomain", code: 6782, userInfo: [NSLocalizedDescriptionKey: errorMessage] ) } } 
+5
source share
2 answers

Since NSError immutable, there is no reason to create multiple instances of the same data. Just create one, persistent instance:

 let NAUnexpectedResponseTypeError = NSError(domain: "MyDomain", code: 6782, userInfo: [NSLocalizedDescriptionKey: "The object fetched by AFNetworking was not of an expected type."] ) 

If you have a situation that is not constant, then it is almost always better to extend, rather than a subclass of NSError . For instance:

 extension NSError { class func MyError(code code:code, message: String) -> NSError { return NSError(domain: "MyDomain", code: code, userInfo: [NSLocalizedDescriptionKey: message]) } } 

This type of extension (as a category) has a long history in ObjC and is a good template for Swift (if you cannot easily use enum ErrorTypes, which are even better than Swift).

In many cases, it’s even easier for me to simply have a top-level function for this, rather than extending an NSError . For instance:

 private func makeError(code code:code, message: String) -> NSError { return NSError(domain: "MyDomain", code: code, userInfo: [NSLocalizedDescriptionKey: message]) } 

(Personally, I use these functions all the time in Swift when I have to use NSError . In ObjC I usually used categories on NSError . I don’t know why I changed, but it feels more natural.)

+3
source

You cannot override the empty init, it is marked as inaccessible, therefore you should not do anything with it.

You have another workaround though

 public class NAUnexpectedResponseTypeError: NSError { public convenience init(message: String = "The object fetched by AFNetworking was not of an expected type.") { self.init( domain: "MyDomain", code: 6782, userInfo: [NSLocalizedDescriptionKey: message] ) } } 

I have not tested it, but it should work.

Since you are using swift 2.0, why not align your instance with the error type and not subclass NSError? That would be cleaner and more idiomatic.

+3
source

Source: https://habr.com/ru/post/1232144/


All Articles