I'm using a Swift file, a sub-class of UIViewController in a project which is basically built previously in Objective-C. The bridging-header file is added by Xcode. I'm getting following error:
Cannot find protocol declaration for 'AVCapturePhotoCaptureDelegate'
This is my VC:
import UIKit
import AVFoundation
class ScanTargetAVFViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
}
}
extension ScanTargetAVFViewController: AVCapturePhotoCaptureDelegate {
}
EDIT:
I've tried removing #import "MyProject-Swift.h" from one of the objective-c file and it works now. However, I need to reference Swift code from my Objective-C files. Any clue?
Try importing the MyProject-Swift.h file into MyObjectiveC.m rather than MyObjectiveC.h. If there are Swift classes you need to reference in MyObjectiveC.h you can use the class directive.
#class MySwiftClass;
Related
I am a newbie for objc. I have written a class exposing it to the JS side using swift. The content in that file looks like as follows,
import Foundation
#objc(AppLinkModule)
class AppLinkModule: NSObject{
#objc
static var appLink: String?
#objc
func setLink(link: String){
AppLinkModule.appLink = link;
}
#objc
func getLink(_ resolve: RCTPromiseResolveBlock, rejecter reject: RCTPromiseRejectBlock) -> Void {
resolve(AppLinkModule.appLink);
AppLinkModule.appLink = nil;
}
}
The AppLinkModule.m file is as follows,
#import "React/RCTBridgeModule.h"
#interface RCT_EXTERN_MODULE(AppLinkModule, NSObject)
RCT_EXTERN_METHOD(getLink)
#end
What I actually want is to call the setLink method from the AppDelegate.m file or else directly set to the static variable appLink. Some instructions to achieve this will be greatly appreciated.
This looks fine.
If you want to call getLink() from your App Delegate, you'll need to import the Auto-generated Swift Bridging Header File that Xcode creates when you compile your code. This will allow the Objective-c AppDelegate.m file to find your exposed swift code.
#import <ProjectName-Swift.h> will allow your Swift to be exposed to the AppDelegate, and you already have marked the class and functions #objc so they will be visible.
Then you just need to either create a singleton or shared instance of your AppLinkModule (React Native Modules are all run statically) or you need to instantiate your module class.
Once you've done so, you can call this function in the AppDelegate like so:
[[[AppLinkModule ] shared ] getLink];
I'm merging my Swift project with already existing Objective-C code. I need to call some important methods of Swift class from objective C app delegate. I tried all methods given in net, but it was no use. Can any one help me out?
Yes, it's possible but with some limitations.
You can use only classes which inherited from NSObject, with public attribute and marked with #objc. At Objective-C code you should import "ProductModuleName-Swift.h" file which generated by compiler.
Here is an example of Swift class:
import Foundation
#objc public class ExampleClass: NSObject {
#objc public var someInstanceProperty = "Property"
#objc public func someFunction() {
print("Some function")
}
}
Notice that this class inherited from NSObject and have #objc and public attributes. After command+B you can take a look at generated bridge header through Assistance editor:
Then you should import the bridge header at your Objective-C class.
#import "ProductModuleName-Swift.h"
And then you can use your Swift class at Objective-C code like any other Objective-C class:
__auto_type const someClass = [ExampleClass new];
[someClass someFunction];
NSLog(#"%#", someClass.someInstanceProperty);
Here is an additional information from Apple:
Importing Swift into Objective-C
I'm not able to import Swift class into Objective-C.
Xcode version: 10.1
Swift: 4.2
My steps:
Create empty Single-View Objective-C project called "test".
Create Swift class (mytestclass.swift)
Create bridging empty header "test-Swift.h"
Try to use in ViewController.m like this: #import "test-Swift.h"
[[MyTestClass init] calculate];
mytestclass.swift
import Foundation
#objc public class MyTestClass: NSObject {
#objc public func calculate() {
print("TEST")
}
}
After compilation I get:
/Users/xxx/Desktop/test/ViewController.m:19:7: Use of undeclared
identifier 'MyTestClass'
What am I missing?
Your problem is in step
3- Create bridging empty header "test-Swift.h"
You shouldn't create that file manually , as it's created when you add the swift file to your Objective-C , also you need to replace this line
[[MyTestClass init] calculate];
with
[[[MyTestClass alloc] init] calculate];
or
[[MyTestClass new] calculate];
Here is a working demo
I'm currently working on some Swift classes in my ObjC project.
The problem I have is the following:
I have this protocol declared in ClassA.h:
#protocol MyProtocol <NSObject>
- (void)complexMethodWithArg1:(id)arg1 arg2:(id)arg2 arg3:(id)arg3;
- (Folder *)currentDestinationFolder;
- (Flow)currentFlow;
#end
Pretty standard stuff.
Now my goal is to have a swift class with a property that is an object implementing this protocol.
So naturally, I add my class to the swift bridging header:
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
#import "ClassA.h"
and declare my property in my swift file under ClassB which is a UIViewController that implement ANOTHER protocol
class ClassB : UIViewController, AnotherProtocol {
var delegate:MyProtocol?
}
Problem here is: I want to call a bunch of my delegate methods in viewDidLoad. It's working for all of them except ONE method that gets not autocompletion and errors the compilation if entered manually:
override func viewDidLoad() {
self.delegate?.currentDestinationFolder() // works great, no problem
self.delegate?.currentFlow() // works great, no problem
self.delegate?.complexMethodWithArg1(arg1: arg1, arg2: arg2, arg3: arg3) // PROBLEM : no autocompletion, error if entered manually !
super.viewDidLoad()
}
I have no idea what's going on, it's not related to optional or required protocol methods, not related to the fact that my delegate property is optional (tried unwrapped).
Has anybody face some similar issue? seems like some kind of bug?
I went ahead and tried to reproduce the problem on an empty project.
MyProtocol.h (taking the declaration from your question and comments)
#import Foundation;
#import UIKit;
#class CAPNavigationBar;
#protocol MyProtocol <NSObject>
- (void)setupNavigationItemInNavigationBar:(CAPNavigationBar *)navigationBar
navigationItem:(UINavigationItem *)navigationItem
inViewController:(UIViewController *)viewController;
#end
CAPNavigationBar.h (just a mock)
#import Foundation;
#interface CAPNavigationBar : NSObject
#end
ViewController.swift
import UIKit
class ViewController: UIViewController {
var delegate: MyProtocol?
override func viewDidLoad() {
super.viewDidLoad()
let capNavigationBar = CAPNavigationBar()
self.delegate?.setupNavigationItemInNavigationBar(capNavigationBar, navigationItem: nil, inViewController: self)
}
}
Bridging header
#import "MyProtocol.h"
#import "CAPNavigationBar.h"
Summary
Everything is working as expected.
You have either a simple typo somewhere or you are not importing correctly all the types into Swift. Especially make sure that you are not importing types only as forward declarations.
In a Project having already ObjC, I'm adding a Swift Class
import AddressBookUI
class MyVC : UITableViewController, ABPeoplePickerNavigationControllerDelegate {
}
MyApp-Swift.h:289:42: Cannot find protocol declaration for 'ABPeoplePickerNavigationControllerDelegate'; did you mean 'UINavigationControllerDelegate'?
No, Swift, I really mean ABPeoplePickerNavigationControllerDelegate. Really wondering what I am doing wrong here...
FWIW, the reason this works with ABRecord in pure Swift, but not in the Objective-C compatibility header is that there is a typealias which the latter apparently doesn't translate back correctly:
typealias ABRecordRef = ABRecord
see https://developer.apple.com/library/prerelease/ios/documentation/AddressBook/Reference/ABRecordRef_iPhoneOS/index.html#//apple_ref/c/tdef/ABRecordRef
Might be worth filing a Radar 📡
I need to add
#import <AddressBookUI/AddressBookUI.h>
in my Briding-Header.h. One could think the import in my Swift file was enough. It was not.
That said, now I have a new problem when implementing
func peoplePickerNavigationController(peoplePicker: ABPeoplePickerNavigationController!, didSelectPerson person: ABRecord!, property: ABPropertyID, identifier: ABMultiValueIdentifier) {
}
Here comes the next error:
-Swift.h:297:110: Expected a type
It has a problem with the ABRecord type in
didSelectPerson:(ABRecord)
Doesn't help if I also import AddressBook in Briding Header or Swift File.
You can check the code I've used here
Pure Swift project, no Objective-C involved
For me, this is compiling fine without using any Bridging-Header
import UIKit
import AddressBook
import AddressBookUI
class ViewController: UITableViewController, ABPeoplePickerNavigationControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
func peoplePickerNavigationController(peoplePicker: ABPeoplePickerNavigationController!, didSelectPerson person: ABRecord!, property: ABPropertyID, identifier: ABMultiValueIdentifier) {
}
}
I'm adding relevant frameworks (AddressBook, AddressBookUI) to the link binary with libraries phase of my target
Objective-C Project, with Bridging Header
My Bridging-Header.h:
#import <AddressBook/AddressBook.h>
#import <AddressBookUI/AddressBookUI.h>
make sure your Bridging-Header is properly referenced in your target
swift VC code is the same as above
Fixed my second Problem thanks to #neonacho on Twitter. Instead of ABRecord I had to use ABRecordRef to compile. Not sure why Diego's code works and not mine. So it became
func peoplePickerNavigationController(peoplePicker: ABPeoplePickerNavigationController!,
didSelectPerson person: ABRecordRef!, property: ABPropertyID, identifier: ABMultiValueIdentifier) {
}
and it works.