Cannot find protocol declaration for 'ABPeoplePickerNavigationControllerDelegate' - ios

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.

Related

Is it possible to call objective C application delegate method from Swift class of the same project?

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

Cannot find protocol declaration for 'AVCapturePhotoCaptureDelegate'

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;

Using GTM v5 TAGCustomFunction in Swift

I'm integrating GTM v5 (GTM + Firebase) in a Swift project, and I want to be able to call some methods when tags are triggered. However, it doesn't seem to work with Swift, although similar implementations in Objective C and Android projects did work.
Here's the class conforming to the TAGCustomFunction protocol :
import Foundation
import GoogleTagManager
final class Tags: NSObject, TAGCustomFunction {
func execute(withParameters parameters: [AnyHashable : Any]!) -> NSObject! {
print("YEAH ! IT WORKS !")
return nil
}
}
Everything is working well, even though I see these kind of logs:
GoogleTagManager info: Processing logged event: applicationStart with parameters: (null)
But the log I'm printing is not showing…
I'm sure about the configuration of the container since this one is correctly loaded, and I use the exact same container for my Objective C project, in which it works perfectly.
I think TAGCustomFunction needs to have class/method #objc annotations, and the class-level #objc annotation needs to specify the class name, i.e.
import Foundation
import GoogleTagManager
#objc(Tags)
final class Tags: NSObject, TAGCustomFunction {
#objc func execute(withParameters parameters: [AnyHashable : Any]!) -> NSObject! {
print("YEAH ! IT WORKS !")
return nil
}
}
After reading this SO post, I suddenly remembered that a Swift project could embed some objective C classes.
The solution to my problem was ridiculously easy to set up once I realized that, eventhough I've never had to do it before.
I created a new Cocoa Touch Class like the following :
Here is the .m :
#import "MyCustomTagClass.h"
#import "MySwiftClass-Swift.h"
#implementation MyCustomTagClass
- (NSObject*)executeWithParameters:(NSDictionary*)parameters {
[MySwiftClass myMethod];
}
#end
And here is the .h :
#import <Foundation/Foundation.h>
#import <GoogleTagManager/TAGCustomFunction.h>
#interface MyCustomTagClass : NSObject <TAGCustomFunction>
- (NSObject*)executeWithParameters:(NSDictionary*)parameters;
#end
Note that I import a header for my Swift class, which is automatically generated by Xcode. Just add -Swift.h after the name of your class to import it, just as I did in the .m example above.
Last, but not least, update your Swift class with #objc annotations at class and method declaration lines :
import Foundation
#objc class MySwiftClass: NSObject {
//...
#objc static func myMethod() {
// do something...
}
}
I hope this helped !

Objective-C protocol method invisible in Swift

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.

Use of undeclared type 'Object'

This is so weird. Normally I could understand a class not being declared, but this is claiming the Object class itself is not declared. NSObject works, but the way my project is setup I need it to be a pure Swift Object. My class header looks like this:
import UIKit
import Foundation
class Person: Object {
I know foundation isn't really necessary, I just added it because I wasn't sure if that was causing me issues. The issue is occurring in both actual projects and playgrounds as well as in Xcode 6 and the latest Xcode 7 beta with Swift 2.0
if you are using Realm then import
import RealmSwift
Complete syntax of class.
import UIKit
import RealmSwift
class User: Object {
}
If you face any difficulty to implement this code. Watch below video
Link: https://youtu.be/5Z8tBKwk6-c
Just remove : Object. Pure Swift classes don't need to inherit from a superclass
Pure Swift object doesn't inherit from a superclass:
class Person {}
You can read Classes and Structures
For RealmSwift
import Foundation
import RealmSwift
class Note: Object{
#objc dynamic var id = 0
#objc dynamic var title = ""
#objc dynamic var created = Date()
#objc dynamic var text = ""
override static func primaryKey() -> `enter code here`String? {
return "id"
}
}

Resources