Swift 3.0 Extension - Methods are not getting called in Child class - ios

I have an Extension implementation problem when I am converting my code from swift 2.3 to swift 3.0.
Problem statement: -
1) Each inherited class asking for protocol implementation
2) Not able to call methods which are already implemented in Extension.
Please check below code for more understanding.
protocol MyExtension {
static func addTwoNumber(number1: Double, number2: Double)
}
extension MyExtension {
static func addTwoNumber(number1: Double, number2: Double) {
//implementation
}
static func subTractTwoNumbers(number1: Double, number2: Double) {
//implementation
}
}
internal class firstClass: MyExtension {
static func multiplyTwoNumbers(number1: Double, number2: Double) {
//implementation
// if I call subTractTwoNumbers in this class it is giving me an error
subTractTwoNumbers(10, 10)
//and asking me to implement protocol method as well ie
//static func addTwoNumber(number1: Double, number2: Double)
}
}
Please let me know, what I am doing wrong.

Replace this
subTractTwoNumbers(10, 10)
With
subTractTwoNumbers(number1: 10, number2: 10) // you must have to pass the argument lables name to call the function.
If you don’t want an argument label for a parameter, write an underscore (_) instead of an explicit argument label for that parameter
static func subTractTwoNumbers(_: Double, _: Double) {
//implementation
}
Also, you have written one extra curly braces at the end.

Write function in extension as below
extension MyExtension {
func addTwoNumber(number1: Double, number2: Double) {
//implementation
}
func subTractTwoNumbers(number1: Double, number2: Double) {
//implementation
}
}

Related

swift protocol conformance with duplicate function names

class A {
func test(string: String, another defaultValue: String = "") {
///...
}
}
class B {
func test(string: String, different defaultValue: Bool = true) {
///...
}
}
protocol Test {
func test(string: String)
}
extension A: Test {
func test(string: String) {
self.test(string: string)
}
}
extension B: Test {
func test(string: String) {
self.test(string: string)
}
}
When I do this I get the following error
Function call causes an infinite recursion
How to confirm to the protocol Test to the classes which have similar function names
When A or B conform to Test, there is no way for the program to know which .test you're calling, cause the internal .test methods in A & B have default values.
To resolve the ambiguity, you can be specific:
extension A: Test {
func test(string: String) {
self.test(string: string, another: "")
}
}
extension B: Test {
func test(string: String) {
self.test(string: string, different: true)
}
}
You have to call class methods with full signature:
extension A: Test {
func test(string: String) {
self.test(string: string, another: "")
}
}
extension B: Test {
func test(string: String) {
self.test(string: string, different: true)
}
}
As swift allows method overloading, you may use the same function name with different signatures.
In your example class methods have different signatures, comparing to the protocol methods, so it is fine. However class methods have default values and can be called without full signature and in this case it is ambiguous as the signature become the same.

How to handle Protocol Delegate when converting Objective-C to Swift

I'm trying to convert a speech recognition code to Swift, Protocol defined in ViewController.h as:
#interface ViewController : UIViewController<SpeechRecognitionProtocol>
{
NSMutableString* textOnScreen;
DataRecognitionClient* dataClient;
MicrophoneRecognitionClient* micClient;
SpeechRecognitionMode recoMode;
bool isMicrophoneReco;
bool isIntent;
int waitSeconds;
}
I got stuck converting below function at ViewController.h:
micClient = [SpeechRecognitionServiceFactory createMicrophoneClient:(recoMode)
withLanguage:(language)
withKey:(primaryOrSecondaryKey)
withProtocol:(self)];
This function is defined in the SpeechSDK.framework as:
#interface SpeechRecognitionServiceFactory : NSObject
/*
#param delegate The protocol used to perform the callbacks/events upon during speech recognition.
*/
+(MicrophoneRecognitionClient*)createMicrophoneClient:(SpeechRecognitionMode)speechRecognitionMode
withLanguage:(NSString*)language
withKey:(NSString*)primaryOrSecondaryKey
withProtocol:(id<SpeechRecognitionProtocol>)delegate;
#end
this protocol looks like this in my converted ViewController.Swift:
import UIKit
protocol SpeechRecognitionProtocol {
func onIntentReceived(result: IntentResult)
func onPartialResponseReceived(response: String)
func onFinalResponseReceived(response: RecognitionResult)
func onError(errorMessage: String, withErrorCode errorCode: Int)
func onMicrophoneStatus(recording: DarwinBoolean)
func initializeRecoClient()
}
class ViewController: UIViewController, SpeechRecognitionProtocol {
var myDelegate: SpeechRecognitionProtocol?
finally I am calling this function inside ViewController.swift. I am getting following error after withProtocol: cannot convert value of type 'SpeechRecognitionProtocol.Protocol' to expected argument type 'SpeechRecognitionProtocol!' :
func initializeRecoClient() {
let language: String = "en-us"
let path: String = NSBundle.mainBundle().pathForResource("settings", ofType: "plist")!
let settings = NSDictionary(contentsOfFile: path)
let primaryOrSecondaryKey = settings?.objectForKey("primaryKey") as! String
micClient = SpeechRecognitionServiceFactory.createMicrophoneClient(recoMode!,
withLanguage: language,
withKey: primaryOrSecondaryKey,
withProtocol: SpeechRecognitionProtocol)
}
You shouldn't declare the SpeechRecognitionProtocol yourself (not sure you added this just for demonstration purposes or whether your actually have that in your code). SpeechRecognitionProtocol is already declared in SpeechRecognitionService.h and available to Swift - this is the one you need to use.
The object implementing that protocol is ViewController. Assuming your initializeRecoClient is a method of that class, the call would need to look like:
micClient = SpeechRecognitionServiceFactory
.createMicrophoneClient(recoMode!,
withLanguage: language,
withKey: primaryOrSecondaryKey,
withProtocol: self)
The SpeechSDK API didn't choose a particularly good name for that factory method.
The withProtocol argument doesn't take the protocol object itself (as the name suggests), but the object implementing the protocol (obviously).
P.S.: Not sure what SpeechAPI version you use, I had to implement those Swift methods to make ViewController conform to SpeechRecognitionProtocol:
func onPartialResponseReceived(response: String!) {}
func onFinalResponseReceived (response: RecognitionResult) {}
func onError (errorMessage: String!,
withErrorCode errorCode: Int32) {}
func onMicrophoneStatus (recording: Bool) {}
func onIntentReceived (result: IntentResult) {}

Overloaded functions in swift error [duplicate]

This question already has answers here:
Compiler error: Method with Objective-C selector conflicts with previous declaration with the same Objective-C selector
(6 answers)
Closed 7 years ago.
I am new to swift and have an error in the following code. I have one function with two different parameters. Xcode(version 6) is giving an error on the second definition with a parameter as a function which takes one value.Here is the code:
func performOperation(operation: (Double, Double) -> Double) {
if(operandStack.count >= 2){
displayValue = operation(operandStack.removeLast(), operandStack.removeLast())
enter()
}
}
func performOperation(operation: Double -> Double){
if(operandStack.count >= 1){
displayValue = operation(operandStack.removeLast())
enter()
}
}
Update:
Another solution is add private before method definition (Source):
private func performOperation(operation: (Double, Double) -> Double) {
if(operandStack.count >= 2){
displayValue = operation(operandStack.removeLast(), operandStack.removeLast())
enter()
}
}
private func performOperation(operation: Double -> Double){
if(operandStack.count >= 1){
displayValue = operation(operandStack.removeLast())
enter()
}
}
Original Answer:
Looks like your methods are defined in class that is inherited from some Objective-C class, for example:
class TestClass : NSObject {
func test(a : String) {}
func test(a : UInt) {}
}
Compiler will produce such error:
Method 'test' with Objective-C selector 'test:' conflicts with
previous declaration with the same Objective-C selector.
To fix that you need avoid inheritance from Objective-C class:
class TestClass {
func test(a : String) {}
func test(a : UInt) {}
}
This variant will work correct.
The problem is that Objective-C doesn't support methods overloading, but Swift does. That's why you need create pure Swift class.

ObjC protocol Implementation in Swift

Ok here is the big problem. I had a library written in ObjC(this). There we had a defined protocol. When I tried to use it in swift file I get constantly:
Type "XXX" does not conform to protocol "XXX"
To simplify things I made up a test project - it should be created as Swift project.
Then create ObjC header file(I called it StupidProtocol.h) with following protocol inside(please note each name and value to exactly match the given including uppercase/lowercase):
#protocol MyProtocol <NSObject>
- (NSString *)getAxisLabel:(id)axis Value:(CGFloat)value;
#end
In bridging header:
#import "StupidProtocol.h"
And then back in Swift file:
class ViewController: UIViewController, MyProtocol
{
func getAxisLabel(axis: AnyObject!, value: CGFloat) -> String! {
return ""
}
}
And baam we got this error again even though auto-complete finishes the getAxisLabel function for me.
I strongly suspect that the problem is with argument "value" and it's function parameter "Value".
Any help will be highly appreciated.
EDIT
Please note that this library is not technically mine, so I cannot change it. I need a way to use it in Swift without changing it's original declaration. My example is only to simplify my problem.
WHAT I TRIED
I have tried following scenarios with no success:
'has different arguments name from those required by protocol' error
func getAxisLabel(axis: AnyObject!, Value value: CGFloat) -> String! {
return ""
}
'has different arguments name from those required by protocol' error
func getAxisLabel(axis: AnyObject!, Value: CGFloat) -> String! {
return ""
}
'type does not conform to protocol'
func getAxisLabel(axis: AnyObject!, Value: CGFloat) -> NSString! {
return ""
}
SOLUTION
See accepted answer
I don't know if this is a bug or not. The Objective-C protocol method
- (NSString *)getAxisLabel:(id)axis Value:(CGFloat)value;
(with uppercase "V" in Value:) is mapped to Swift as
func getAxisLabel(axis: AnyObject!, value: CGFloat) -> String!
(with lowercase "v" in value:), but none of
func getAxisLabel(axis: AnyObject!, value: CGFloat) -> String! { }
func getAxisLabel(axis: AnyObject!, Value: CGFloat) -> String! { }
is accepted by the compiler to satisfy the protocol requirement.
As a workaround, you can annotate the method with an explicit
Objective-C selector name:
class ViewController: UIViewController, MyProtocol
{
#objc(getAxisLabel:Value:)
func getAxisLabel(axis: AnyObject!, value: CGFloat) -> String! {
return ""
}
}

Declare function that takes generic type that conform to “can be multiplied” in Swift

How to declare function that takes generic type that conform to “can be multiplied” in Swift ?
For example :
func sq <T: "Can be multipied">(x: T) -> T {
return x*x
}
So that I could square Float, Double, CGFloat etc ... It this possible at all ?
You can define your own protocol like this:
protocol Multipliable {
func *(lhs: Self, rhs: Self) -> Self
}
func sq<T: Multipliable>(value:T) -> T {
return value * value
}
extension Int: Multipliable {}
extension Double: Multipliable {}
sq(10) // -> 100
sq(10.0) // -> 100.0
I believe you have to extend every class that you want to conform to this protocol, I don't know of any way for it to work without using an extension.
Here's an interesting article on the implementation of the Equatable protocol:
http://nshipster.com/swift-default-protocol-implementations/

Resources