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: readDeliveryInfoItems
. But now, after converting to Swift 3, I can't call .readDeliveryInfoItems()
anymore in my Swift class. It's telling me it has been renamed to .readItems()
.
That makes no sense. And the Objective-C class still calls the method readDeliveryInfoItems
, so there is something under the covers going on here.
I have tried renaming the Objective-C readDeliveryInfoItems
method to readDeliveryInfo
, building (Swift fails because it says that the readInfo()
method doesn't exist, which is good), and then renaming the method back to readDeliveryInfoItems
. However, when I build after this, Swift goes back to thinking the method is called readInfo()
. I was hoping this would trick Xcode into refreshing the Swift bridging and renaming the method back to the correct name readDeliveryInfoItems()
, but it did not.
How can I fix this?
UPDATE TO ADD MORE INFO
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 readDeliveryInfoItems
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.
Roughly speaking (and I am oversimplifying), if the suffix on a method name is a verb object matching the return type, the suffix is dropped.
A simpler example would be a method called
readString
that returns an NSString.Your method falls within those parameters (I told you I was oversimplifying but you can see, roughly, how that's true), so you get the treatment.
Personally, I regard this as a bug, especially because in some cases the change can result in name clash and make calling the method impossible (esp. when the Objective-C API is not yours and you cannot change it). For an example, see this question: Swift 3 (Omit Needless Words) causing two functions to have the same name
The translation process is described in detail in
The relevant part for your question is (emphasis mine):
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 –becomes
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 tosendItems()
.)You can override the mapping with
NS_SWIFT_NAME
: