Method names changed in Swift class used by Objective C Classes

The following code is Swift class that is being used by objective C classes in a mixed project.

It is followed by the corresponding interface in the xxx-Swift.h file.

The method (func) names are changed in the xxx-Swift.h file. I did not expect this at all.

1. Where can I find this documented.

2. When is the xxx-Swift.h file generated an updated


import Foundation

open class DisplayFormatter : NSObject

{

@objc public var mode : UInt

@objc public var precision : UInt

@objc public var useSeperator : Bool

@objc var fieldFormat : String;

override init()

{

mode = 0

precision = 2

useSeperator = false

fieldFormat = String( " ")

}

@objc public func setFormatString (formatStr : String)

{

fieldFormat = formatStr

}

@objc public func getDecimalFormattedString (value : Double) -> String

{

let numberFormatter = NumberFormatter()

if ( fieldFormat.count > 0)

{

numberFormatter.positiveFormat = fieldFormat

numberFormatter.formatterBehavior = .behavior10_4

numberFormatter.numberStyle = .decimal

numberFormatter.minimumFractionDigits = 0

numberFormatter.maximumFractionDigits = Int(precision)

}

if (!useSeperator)

{

numberFormatter.groupingSeparator = ""

}

let n = NSNumber.init(value: value)

let returnString = numberFormatter.string(from: n)

return returnString!;

}

@objc public func getScientificFormattedString (value : Double) -> String

{

let numberFormatter = NumberFormatter()

if ( fieldFormat.count > 0)

{

numberFormatter.positiveFormat = fieldFormat

numberFormatter.formatterBehavior = .behavior10_4

numberFormatter.numberStyle = .scientific

numberFormatter.minimumFractionDigits = 0

numberFormatter.maximumFractionDigits = Int(precision)

}

if (!useSeperator)

{

numberFormatter.groupingSeparator = ""

}

let n = NSNumber.init(value: value)

let returnString = numberFormatter.string(from: n)

return returnString!;

}

@objc public func getCurrencyFormattedString (value : Double) -> String

{

let numberFormatter = NumberFormatter()

if ( fieldFormat.count > 0)

{

numberFormatter.positiveFormat = fieldFormat

numberFormatter.formatterBehavior = .behavior10_4

numberFormatter.numberStyle = .currency

numberFormatter.minimumFractionDigits = 0

numberFormatter.maximumFractionDigits = Int(precision)

}

if (!useSeperator)

{

numberFormatter.groupingSeparator = ""

}

let n = NSNumber.init(value: value)

let returnString = numberFormatter.string(from: n)

return returnString!;

}

@objc public func getFormattedString( value : Double) -> String

{

if (mode == 0)

{

return getDecimalFormattedString(value: value)

}

else if (mode == 1)

{

return getScientificFormattedString(value: value)

}

else if (mode == 2)

{

return getCurrencyFormattedString(value: value)

}

/

return "???"

}

}

SWIFT_CLASS("_TtC5iMult16DisplayFormatter")

@interface DisplayFormatter : NSObject

@property (nonatomic) NSUInteger mode;

@property (nonatomic) NSUInteger precision;

@property (nonatomic) BOOL useSeperator;

@property (nonatomic, copy) NSString * _Nonnull fieldFormat;

- (nonnull instancetype)init OBJC_DESIGNATED_INITIALIZER;

- (void)setFormatStringWithFormatStr:(NSString * _Nonnull)formatStr;

- (NSString * _Nonnull)getDecimalFormattedStringWithValue:(double)value SWIFT_WARN_UNUSED_RESULT;

- (NSString * _Nonnull)getScientificFormattedStringWithValue:(double)value SWIFT_WARN_UNUSED_RESULT;

- (NSString * _Nonnull)getCurrencyFormattedStringWithValue:(double)value SWIFT_WARN_UNUSED_RESULT;

- (NSString * _Nonnull)getFormattedStringWithValue:(double)value SWIFT_WARN_UNUSED_RESULT;

@end

I'm not sure where/if the rules in the Swift->Obj-C direction are documented, but the [inmplemented] proposal for the other direction is here:


github.com/apple/swift-evolution/blob/master/proposals/0005-objective-c-name-translation.md


Basically, you can apply those rules in the reverse direction. Or, just look in the -Swift.h file to find out how they translated. (Also, autocompletion on the Obj-C side is your friend here.) If you want to override the Obj-C names, you can use an @objc(<name>) annotation.


Note that your method naming in the above fragment is idiomatic for neither Swift nor Obj-C. In particular, methods that return their result should not start with "get". (That's reserved by convention for methods that return values in an inout parameter.)

What is an @objc(<name>) annotation?


Please show me on the following code snippet. I would like to preserve the name of the method if at all possible.


@objc public func getFormattedString2(inputValue value : Double) -> String

{

return getFormattedString(value: value)

}


Thanks in advance.

Well, what do you mean by "preserve"? The Swift method name here is "getFormattedString2(inputValue:)", and the default Obj-C name from that is "getFormattedString2WithInputValue:", which is how the entire name is preserved.


If you mean, preserve just the "getFormattedString2" fragment, giving the Obj-C name "getFormattedString2:", you can do that by saying that there is no 1st argument keyword:


    @objc public func getFormattedString2(_ value : Double) -> String


If you mean you want to keep the "inputValue" keyword in Swift, and omit it in Obj-C (which seems like an odd choice, but OK):


    @objc(getFormattedString2:) public func getFormattedString2(inputValue value : Double) -> String


IOW, the method name inside the parentheses is the Obj-C selector you want. IIRC, the compiler will complain if you have the wrong number of ":" characters in the selector.


But, seriously, I recommend you don't do any of this. It's good that you care what your Obj-C APIs are, but it's really not good that you ignore the widely-established Obj-C naming conventions.

Method names changed in Swift class used by Objective C Classes
 
 
Q