Define method with closure in an #objc protocol - objective-c

I have the following protocol definition:
#objc protocol PersonDataStore {
func findPersonWithId(remoteId: String, completionBlock: ((Person) -> Void)!)
// ...
}
The error I get is that the second parameter cannot be represented in Objective-C. I researched the blocks/closures topic but I have a hard time getting my head around it since it is so conceptually different.
Is this just a matter of syntax or is it really not possible to define an Objective-C protocol with a closure in Swift?

I believe your problem is that your class Person is not a subclass of NSObject. Add #objc to the declaration of your Person class or make it a subclass of NSObject and your protocol definition should work.

Related

Implement an Objective-C method with light weight generics in Swift

I have to implement this method in a DataSource protocol of an Objective-C library
(nullable id<SomeClass>)someMethod;
I am trying to implement it in my class in Swift, specifically, the AppDelegate, with what I believe keeps equal the signature
extension AppDelegate: LIBDataSource {
#objc func someMethod<T: SomeClass>() -> T? {
return nil // temporary
}
}
The problem is that
As it is, I have a warning and an error. The error says Method cannot be marked #objc because it has generic parameters (the warning below is also shown)
If I remove #objc, the warning says Non-#objc method 'someMethod()' cannot satisfy optional requirement of #objc protocol LIBDataSource
Is there a way to implement a generic Obj-C method of a Obj-C protocol in Swift? Or do I have to do a separate Objective-C class to accomplish this?
The syntax
id<SomeClass>
is nothing to do with lightweight generics, it means "any Objective-C class as long as it conforms the protocol SomeClass". Your method doesn't need to be generic but it does need to return an object that conforms to the SomeClass protocol. It's signature should probably be something like
func someMethod() -> SomeClass?

Method cannot be a member of an #objc protocol while using Dictionary

I am coding in swift. I have written a protocol
#objc protocol ServerDelegate {
optional func onDownloadDataComplete (downloadedData data : [Dictionary<String,Any>],result : ResultType,error : String)
}
First I received "Method cannot be a member of an #objc protocol because the type of the parameter 2 cannot be represented in Objective-C" for my enum but I fixed it by adding #objc. Now I am receiving this for Array of Dictionary. How to fix it?
As #originaluser2 said Any cannot be represented in #objc so I created a new class, added data members which I needed, inherited it with NSObject and returned its array instead of dictionary and all is good now.

Must my swift function's return type inherit from NSObject

I have some swift function in a swift object of type Helper that returns an object of class Parameter. Parameter is defined as:
class Parameter { }
And my function like this:
func getParameter() -> Parameter { }
When accessing the methods from Helper only those that don't return anything show up. However, getParameter is uncallable. My assumption is that its return type is invisible to Obj-C. Must Parameter extend NSObject in order to work?
If you want to have your Swift classes available to Objective-C, they must inherit from an Objective-C bridged class. That's why your ViewControllers are always available, and for free-standing classes, you must make their superclass NSObject. You can also specifically note in code they are bridged by marking them: #objc class Parameter: NSObject{}

Swift equivalent of id<MyProtocol>?

The question is in the title. In Objective-C, if I want to have a property (like a delegate) that HAS to adhere to a certain protocol it can be defined like so:
#property (weak) id<MyDelegate> delegate;
How can I do this in Swift?
A protocol is a type, so you can use it as a declared variable type. To use weak, you must wrap the type as an Optional. So you would say:
weak var delegate : MyDelegate?
But in order for this to work, MyDelegate must be an #objc or class protocol, in order to guarantee that the adopter is a class (not a struct or enum, as they cannot be weak).
I think the exact oposite is:
weak var delegate: protocol<MyDelegate>?
I prefer this old, objc, style over the swift syntax because in swift first is the base class and then all the adopted protocols. This may be confusing in case your protocol does not have "Delegate" suffix as you won't know whether DataAdoption(for example) is super class or a protocol.
Use the protocol like a type, so:
weak var delegate:MyDelegate?
It is also good to know the equivalent for the Objective-C id<MyProtocolName> in the method declaration in Swift is protocol<MyProtocolName>. For Example:
// Objective-C
-void myMethodWithSome:(id <MyProtocolName>)param {
// ...
}
// Swift
func myMethodWithSome(param: protocol<MyProtocolName>) {
//...
}
Update for method declarations
Objective-C
-void myMethodWithSome:(id <MyProtocolName>)param {
// ...
}
Swift
func myMethodWithSome(param: MyProtocolName) {
//...
}

Concrete class type conforming to protocol in Swift

I need to declare a variable with type UIViewController that conforms to a custom protocol I made. Normally, I would do this in ObjC:
UIViewController<MyProtocol> *thingie;
But, I have no idea how to accomplish that in swift.
I'm just casting the object for now, till something useful shows up:
let conformingObject = viewController as MyProtocol
You may achieve something similar by using generics. Something like this:
class SomeClass<T where T: UIViewController, T: MyProtocol> {
var thingie: T
}