axl411
axl411

Reputation: 930

How do I bridge objc typedef NSString to Swift as String?

Say I have some objc code:

typedef NSString * ObjcNSString;

@interface ObjC : NSObject
+ (void)doThingsWithString:(nullable ObjcNSString)mid;
@end

The corresponding generated Swift interface for the objc code above is:

public typealias ObjcNSString = NSString

open class ObjC : NSObject {
    open class func doThings(with mid: String?)
}

This is causing problem if I use the code in Swift:

let str: ObjcNSString? = nil
ObjC.doThings(with: str) // Cannot convert value of type 'ObjcNSString?' (aka 'Optional<NSString>') to expected argument type 'String?'

But I really want to use the ObjcNSString type in Swift, is there any way to make it work?

Upvotes: 1

Views: 814

Answers (2)

axl411
axl411

Reputation: 930

The answer is to use NS_SWIFT_BRIDGED_TYPEDEF

As the title of the question:

How do I bridge objc typedef NSString to Swift as String?

I found NS_SWIFT_BRIDGED_TYPEDEF, use that for an ObjC typedef of NSString, then the type will be bridged as String to Swift.

Example

Without NS_SWIFT_BRIDGED_TYPEDEF

typedef NSString * ObjcNSString;

@interface ObjC : NSObject
+ (void)doThingsWithString:(nullable ObjcNSString)mid;
@end

The corresponding Swift interface is:

public typealias ObjcNSString = NSString

open class ObjC : NSObject {

    open class func doThings(with mid: String?)
}

And that will give me error when I do this:

let str: ObjcNSString? = nil
ObjC.doThings(with: str) // Cannot convert value of type 'ObjcNSString?' (aka 'Optional<NSString>') to expected argument type 'String?'

With NS_SWIFT_BRIDGED_TYPEDEF

Add NS_SWIFT_BRIDGED_TYPEDEF for the ObjC typedef:

typedef NSString * ObjcNSString NS_SWIFT_BRIDGED_TYPEDEF;

@interface ObjC : NSObject
+ (void)doThingsWithString:(nullable ObjcNSString)mid;
@end

Then the Swift interface becomes:

public typealias ObjcNSString = String

open class ObjC : NSObject {

    open class func doThings(with mid: ObjcNSString?)
}

And the same code compiles:

let str: ObjcNSString? = nil
ObjC.doThings(with: str)

So I achieved my goal:

But I really want to use the ObjcNSString type in Swift


If you look close to the difference between the Swift interfaces with or without NS_SWIFT_BRIDGED_TYPEDEF, you'll see by adding NS_SWIFT_BRIDGED_TYPEDEF we get a more desired Swift interface.

Upvotes: 3

Alan Scarpa
Alan Scarpa

Reputation: 3570

It looks like the code that was generated is not quite what you want.

The error you are getting is saying that your function is expecting a String type, but you are trying to use a ObjcNSString type.

To fix this, just change your function declaration to:

open class func doThings(with mid: ObjcNSString?)

But keep in mind, you can just use NSString in Swift. You don't need the typealias. You can just as well write your function like:

open class func doThings(with mid: NSString?)

Upvotes: 1

Related Questions