Ethan G Ethan G - 1 year ago 60
Objective-C Question

Converting to Swift 3 renamed my own Objective-C method

I have swift classes mixed in with my Objective-C code. With Swift 2.3, everything was fine and worked as expected.

I recently converted to Swift 3, and it updates several API calls because of all the renaming that occurred for Swift 3. That's fine; I get that.

But what's not fine is that Swift 3 seems to have renamed a method in one of my Objective-C classes. I own the Objective-C class and I called the method what I wanted:

. But now, after converting to Swift 3, I can't call
anymore in my Swift class. It's telling me it has been renamed to

That makes no sense. And the Objective-C class still calls the method
, so there is something under the covers going on here.

I have tried renaming the Objective-C
method to
, building (Swift fails because it says that the
method doesn't exist, which is good), and then renaming the method back to
. However, when I build after this, Swift goes back to thinking the method is called
. I was hoping this would trick Xcode into refreshing the Swift bridging and renaming the method back to the correct name
, but it did not.

How can I fix this?


The interface of my Objective-C class has this function declaration:

- (nullable NSArray<XMPPDeliveryInfoItem *> *)readDeliveryInfoItems;

But in the Generated Interface (see MartinR's comment below) for that class, the function declaration is this instead:

open func readItems() -> [XMPPDeliveryInfoItem]?

There are other functions in that class that are similar to the
function, such as this one:

- (nullable NSArray<XMPPDeliveryInfoItem *> *)sentDeliveryInfoItems;

And they look correct in the Generated Interface:

open func sentDeliveryInfoItems() -> [XMPPDeliveryInfoItem]?

So I can't figure out why I'm having this problem with only the one function.

Answer Source

The translation process is described in detail in

The relevant part for your question is (emphasis mine):

Prune a match for the enclosing type from the base name of a method so long as the match starts after a verb. For example,

extension UIViewController {
  func dismissViewControllerAnimated(flag: Bool, completion: (() -> Void)? = nil)


extension UIViewController {
  func dismissAnimated(flag: Bool, completion: (() -> Void)? = nil)

This pruning algorithm is – as far as I can see – implemented in StringExtras.cpp (and uses a lot of heuristics), and PartsOfSpeech.def contains a list of words which are considered a verb, such as


but not VERB(sent). That explains why – simplifying your example slightly –

@interface DeliveryInfo : NSObject


open class DeliveryInfo : NSObject {
    open func readItems()
    open func sentDeliveryInfoItems()

The type name is pruned after the verb "read", but not after the non-verb "sent". (You can verify that by changing the second method name to sendDeliveryInfoItems which is then mapped to sendItems().)

You can override the mapping with NS_SWIFT_NAME:

-(void)readDeliveryInfoItems NS_SWIFT_NAME(readDeliveryInfoItems());
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download