Swift class not conforming to Objective C Protocol - objective-c

I have this objective c protocol as mentioned below:
#protocol Class1<NSObject>
- (void)searchBy:(Enum1)searchType;
#end
And i am trying to make a swift class conform to that protocol . The stub which Xcode generated for me is as follows:
func search(by searchType: Enum1) {
}
But Xcode gives me an error while building that the class still doesn’t conform to protocol. What am i missing here?

Do you have your Objective-C header that contains the protocol and enum in the bridging header for swift to find?
So I created a new test app, and the view controller looks as follows:
import UIKit
class ViewController: UIViewController, Class1
{
func search(by searchType: Enum1) {
print("it works")
}
override func viewDidLoad() {
super.viewDidLoad()
let class1 = self as Class1
class1.search(by: Enum1.PlayerStateOff)
}
}
And my objective-C bridging header looks like this:
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "Foo.h"
And the ObjectiveC header Foo.h looks like this:
#import <Foundation/Foundation.h>
typedef NS_ENUM(NSInteger, Enum1) {
PlayerStateOff,
PlayerStatePlaying,
PlayerStatePaused
};
#protocol Class1<NSObject>
- (void)searchBy:(Enum1)searchType;
#end
#interface Foo : NSObject
#end
And it all compiles, runs, and prints "it works" just fine in Xcode 9.2. So it's probably your bridging header, but double-check everything you're doing against the above.

Related

Unable to call some methods from an Objective-C class in a Swift extension of that class

I have an objective-c class something like:
#interface MyClass: NSObject { }
- (MyObject *)coolMethod;
#end
#implementation MyClass
- (MyObject *)coolMethod {
return [self doCoolStuff];
}
#end
...and a Swift extension something like:
extension MyClass {
#objc func addedMethodInSwift() {
let coolObj = coolMethod() // <<<< compiler error - method not found
}
}
The code will not compile, because the compiler cannot find the implementation of coolMethod(), however certain other methods from the Objective-C class can be called from the Swift extension.
I have checked and the Objective-C header file is included in the project's bridging header, so it should be visible to Swift. The method in question is definitely visible in the header file.
Why can't coolMethod() be called from the Swift extension?
Check that both your objective-C class and the return type of the function (in your case MyObject.h) are included in the Bridging header. Methods with return types not included in the bridging header are not available from Swift.

can't access swift method from objective-c interface

I need to call my swift method from an Objective-C interface, however I keep getting Use of undeclared identifier 'MySwiftClass'.
My swift class works fine on other places. I have #import "myApp-Swift.h" in my objc file and #objc before my swift class. I am not really good with Objective-C, so any help would be really appreciated.
#interface myInterface ()
-(void) logger:(NSArray<MyArray*>*) events withCallback:(void (^)(NSError*)) callback;
#end
#implementation myInterface
-(void) logger:(NSArray<MyArray*>*) events withCallback:(void (^)(NSError*)) callback{
..
[MySwiftClass mySwiftMethod]
..
}
#end
My swift class:
import Foundation
#objcMembers
public class MySwiftClass: NSObject {
#objc
class func mySwiftMethod(){
}
}

Can not find Swift Protocol declaration in Obj-C class

I have created on Class in Swift and that class and its protocol I am using in Obj-C enabled project but I am getting below error while compiling my project.
cannot find protocol declaration for 'SpeechRecognizerDelegate'; did
you mean 'SFSpeechRecognizerDelegate'?
Can anyone guide me on this how can I use Swift class protocol in my Obj-C class.
Here is my Swift code:
protocol SpeechRecognizerDelegate : class {
func speechRecognitionFinished(_ transcription:String)
func speechRecognitionError(_ error:Error)
}
class SpeechRecognizer: NSObject, SFSpeechRecognizerDelegate {
open weak var delegate: SpeechRecognizerDelegate?
}
Protocol use in Obj-C:
#import "ARBot-Swift.h"
#interface ChatScreenViewController : JSQMessagesViewController <SpeechRecognizerDelegate>
Let me know if required more info.
Thanks in Advance.
in Swift:
#objc public protocol YOURSwiftDelegate {
func viewReceiptPhoto()
func amountPicked(selected: Int)
}
class YourClass: NSObject {
weak var delegat: YOURSwiftDelegate?
}
in Objective-C headerFile.h
#protocol YOURSwiftDelegate;
#interface YOURController : UIViewController < YOURSwiftDelegate >
in Objective-C Implementation.m
SwiftObject * swiftObject = [SwiftObject alloc] init];
swiftObject.delegate = self
Define your Swift protocol like this inside your Swift file.
#objc protocol SpeechRecognizerDelegate: class{
func speechRecognitionFinished(_ transcription:String)
func speechRecognitionError(_ error:Error)
}
Create a Swift Module inside your project setting then use it. You can find here complete blog for the mix language coding.
Then use Protocol inside Objective C class,
We required to add protocol inside Objective C file -
#import "ARBot-Swift.h"
#interface ChatScreenViewController : JSQMessagesViewController <SpeechRecognizerDelegate>
Then you need to conform to the protocol methods -
- (void)viewDidLoad {
[super viewDidLoad];
SpeechRecognizer * speechRecognizer = [[SpeechRecognizer alloc] init];
speechRecognizer.delegate = self;
}
#pragma mark - Delegate Methods
-(void)speechRecognitionFinished:(NSString *) transcription{
//Do something here
}
-(void)speechRecognitionError:(NSError *) error{
//Do something here
}
I had a similar issue after following (import header + Objc annotation on protocol). I got the warning when using Swift code from Objective C headers. Solved by only importing into the implementation .m files.
Add #objc attribute to your protocol:
#objc protocol SpeechRecognizerDelegate : class {
//...
}
Include Swift Classes in Objective-C Headers Using Forward Declarations
//MySwiftClass.swift
#objc protocol MySwiftProtocol {}
#objcMembers class MySwiftClass {}
// MyObjcClass.h
#class MySwiftClass;
#protocol MySwiftProtocol;
#interface MyObjcClass : NSObject
- (MySwiftClass *)returnSwiftClassInstance;
- (id <MySwiftProtocol>)returnInstanceAdoptingSwiftProtocol;
// ...
#end

Protocol declared in Objective-C Framework is not visible in Swift

As the title says I have trouble using a protocol declared in Objective-C framework in a Swift app. I will try to describe the situation in detail below.
I have a framework that has mixed Objective-C and Swift code.
This is similar to what I have in the file with protocol definition.
// MyLibrary.h
#protocol MyDelegate <NSObject>;
#interface ClassThatUsesMyDelegate
#property (weak, nonatomic, nullable) id<MyDelegate>delegate;
#end
#protocol MyDelegate
- (void)aMethod;
#end
Objective-C code is wrapped in a module as such:
// module.modulemap
module MyObjCLibrary {
header "MyLibrary.h"
export *
}
Then I have Swift code that uses the Objective-C code via import MyObjCLibrary where all of the declared above in MyLibrary.h is visible and usable.
The umbrella header of the framework has #import "MyLibrary.h". Which should expose all the code from MyLibrary.h to anyone who uses my framework.
Here is where the problem starts. When I embed this framework in my test app I can use any Swift code from my library as well as ClassThatUsesMyDelegate from MyLibrary.h. Howerver, when I try to use the protocol MyDelegate I get a compiler error that this type has not been declared. Example of usage below:
// MyViewController.swift
import UIKit
import MyFramework
class MyViewController: UIViewController {
...
}
extension MyViewController: MyDelegate { // Error: Use of undeclared type 'MyDelegate'
func aMethod() {
...
}
}
EDIT: This seems to be the case only with protocols, everything else like varibles, classes, enums etc are accessible.

Combinating Swift & Objective C files

I have a bit complicated classes in swift and Objective-C combinated together:
Keypad.h:
#import "MyApp-Swift.h"
#interface Keypad : UIViewController {
...
SwiftViewController *swiftViewController; // this is written in swift
...
}
This worked well.
Then I created a new swift file:
AnotherSwiftViewController.swift
#objc class AnotherSwiftViewController: UITableViewController {
func myMethod() {
let keypad = appDelegate.getTabs().selectedViewController as! Keypad // I need get ObjC Keypad class
}
}
And I need to use there the ObjcC Keypad class.
So I added it to the MyApp-Bridging-Header.h:
MyApp-Bridging-Header.h
...
// lot of other Obj-C files imported
...
#import "Keypad.h"
...
And I get the error:
> .../MyApp-Bridging-Header.h:31:9: note: in file included from .../MyApp-Bridging-Header.h:31: #import "Keypad.h"
> .../Keypad.h:13:9: error: 'My_App-Swift.h' file not found \#import "My_App-Swift.h"
> <unknown>:0: error: failed to import bridging header '.../MyApp-Bridging-Header.h'
Any ideas?
/// EDIT:
Maybe will help:
I'm using
#import "My_App-Swift.h"
In the Keypad.h file, not in standard Keypad.m, because I have there that SwiftViewController *swiftViewController; property
Maybe it will help
You have a good point in your ///Edit.
In Keypad.h remove #import "MyApp-Swift.h" and add a forward declaration of your Swift class as follows:
...
#class SwiftViewController;
#interface Keypad : UIViewController {
...
This should do it assuming Keytab.h references SwiftViewController only by pointer and your bridging header is imported correctly otherwise.
See section Referencing a Swift Class or Protocol in an Objective-C Header in https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/MixandMatch.html.