Swift does not resolve overloaded methods for classes marked with @objc
| Originator: | kristopherdjohnson | ||
| Number: | rdar://17411225 | Date Originated: | 22-Jun-2014 11:31 AM |
| Status: | Open | Resolved: | |
| Product: | Developer Tools | Product Version: | 6.0 |
| Classification: | Serious Bug | Reproducible: | Always |
Summary:
In a normal Swift class, one can overload a method with different implementations for different argument types, and the appropriate overload will be called.
However, if a the @objc attribute is added to a class to allow interoperation with Objective-C, or if an extension containing overloads is declared for an existing Objective-C class, then while the Swift compiler does allow compilation of the class with overloaded methods, the wrong overload may be called at runtime. It seems that the first method declared in the class is called regardless of argument type.
Steps to Reproduce:
Paste this into a Swift playground:
import Foundation
@objc class Foo {
func bar(value: Double) -> String {
println("Calling bar(Double) with value \(value)\n")
return NSString(format:"%f", value)
}
func bar(value: Int) -> String {
println("Calling bar(Int) with value \(value)\n")
return NSString(format:"%d", value)
}
}
let foo = Foo()
let fooDouble = foo.bar(12.2)
let fooInt = foo.bar(12)
Expected Results:
Would expect the value of fooInt to be "12", and for the console output to be this:
Calling bar(Double) with value 12.2
Calling bar(Int) with value 12
Alternatively, I would expect the Swift compiler to issue an error or warning indicating that overloaded methods are not supported with @objc
Actual Results:
The value of fooInt is "0.000000", and this is the console output:
Calling bar(Double) with value 12.2
Calling bar(Double) with value 2.13025656856374e-314
If "@objc" is removed from the class declaration, then the expected output is generated.
Version:
Xcode 6.0 (6A216f)
Notes:
An example for a class is presented here, but the same problem occurs if declaring a class extension for an Objective-C class. For example, if one declares this extension on UIStepper, the first method is called even if the argument is an Int, leading to unexpected behavior when the Int bit pattern is interpreted as a Double:
extension UIStepper {
// Set value if proposed new value is within minimumValue...maximumValue
func ifInRangeSetValue(proposedValue: Double) -> Bool {
if minimumValue <= proposedValue && proposedValue <= maximumValue {
value = proposedValue
return true
}
else {
return false
}
}
func ifInRangeSetValue(proposedValue: Int) -> Bool {
return ifInRangeSetValue(Double(proposedValue))
}
}
For additional commentary and workarounds, see https://gist.github.com/kristopherjohnson/9b061e07832917da8a6c
Configuration:
Attachments:
Comments
Please note: Reports posted here will not necessarily be seen by Apple. All problems should be submitted at bugreport.apple.com before they are posted here. Please only post information for Radars that you have filed yourself, and please do not include Apple confidential information in your posts. Thank you!