Bridging ObjC Categories on Types with Struct Swift Overlay

I have a bridged projects with ObjC categories on types like NSURL or NSError. Swift does not see the category methods on the overlay structs (URL, Error), The only way to I found to work around this is by casting to the ObjC types in Swift (e.g. (url as NSURL).extensionMethod()). What is the recommended way to access the category methods from both ObjC and Swift?

1 Like

That’s because NSError conforms to Error. Other examples, like URL and NSURL, Data and NSData, String and NSString do not even have a subtyping relation.

But, they are designed to be easily convertible to each other either by casting or using initializers.

I know they are not related, just overlays. I just wanted to know how to write the extensions without duplicating code and without burdening the caller with casting. I guess for making a method available on both the Swift and ObjC types, I have to write the extension on both, and if I want to avoid duplicated code, delegate one implementation to the other.

Yes, if they aren’t related, you will have to extend both and delegate one method to the other if you want some new equal functionality, or extend one of them if you want to delegate to an existing method of the ‘pair type’. However, If it’s some existing functionality, I would recommend simply casting or converting rather than spending time on extending and delegating. It’s OK since you only need to cast at a certain moment when bridging. Besides, it would be as well semantically incorrect to extend. But it’s up to you of course.

Right, Swift doesn’t automatically copy over category methods because it’s possible they rely on the reference-type-ness of the self type. Unfortunately, the best answer right now is to redeclare such methods on the value types.

extension URL {
  public func extensionMethod() {
    (self as NSURL).extensionMethod()
  }
}

I hesitate to say this because it will make more work for us and because we’re unlikely to get to it any time soon, but it would be a reasonable feature request to have a special annotation for Objective-C methods that can safely be copied over to a bridged value type. Please file a feature request at https://bugs.swift.org if that’s something you’re interested in, and please include the sorts of category methods you’re defining so that we have some examples of real-world use cases.

Thanks! I‘ll write down some of our uses. Mostly it‘s for custom error domain handling and url/string tools.