How to call protocol from another viewcontroller? - ios

I want to call protocol to my viewController from another viewController. I got error like below:
Type 'Hello' does not conform to protocol 'loginpageVCDelegate'
Here is my protocol in loginpageVC
protocol loginpageVCDelegate {
func onLoginFacebook(loginViewController : loginpageVC!)
}
And here is how I call it
class Hello : UIViewController, loginpageVCDelegate {
....
}
What did I do wrong? How can I fix it?

You should not call it here but instead implement it:
class Hello : UIViewController, loginpageVCDelegate {
func onLoginFacebook(loginViewController: loginpageVC!) {
}
}

To make the implementation of the function from your protocol optional, modify your protocol in loginpageVC to:
#objc protocol loginpageVCDelegate {
optional func onLoginFacebook(loginViewController : loginpageVC!)
}

Related

Protocol extensions where Self is generic

I have a BaseViewController that is defined this way:
open class BaseViewController<ViewModel: ViewModelType, View: BaseView>: UIViewController { ... }
I'm trying to write an extension for a protocol that has a default behaviour for all my BaseViewControllers. Something like this:
protocol MyProtocol {
func doStuff()
}
extension MyProtocol where Self: BaseViewController<BaseViewModel, BaseView> {
func doStuff() { ... }
}
However. If I only tells that the generic types are the BaseViewModel and BaseView it doesn't works for my subclasses, even though those are the most lower level classes used here.
How can I write my protocol extension in a way it will works for all my BaseViewController classes?

Conformance issues even after fulfilling requirements using protocol extensions for #objc protocols

Let us consider this example which compiles without any issues :
protocol AProtocol {
func veryImportantMethod()
}
protocol BProtocol : AProtocol {
}
extension BProtocol {
func veryImportantMethod() {
print("A's protocol requirement satisfied!")
}
}
class ConcreteClass : BProtocol {
}
However, if we do this :
#objc protocol AProtocol { //Added #objc here
func veryImportantMethod()
}
protocol BProtocol : AProtocol {
}
extension BProtocol {
func veryImportantMethod() {
print("A's protocol requirement satisfied!")
}
}
class ConcreteClass : BProtocol {
}
It doesn't compile with a message saying :
Type 'ConcreteClass' does not conform to protocol 'AProtocol'
However, if we actually implement it,
class ConcreteClass : NSObject, BProtocol {
func veryImportantMethod() { }
}
the code compiles. Why is this happening? Is there anything that I am missing here?
I am trying to achieve this form of protocol hierarchy for UITableViewDataSource and I really do not want to repeat tableView:cellForRowAtIndexPath: code across conformants.
The compiler wants to make sure that the class can be compiled with ObjC. Once you inherit from an ObjC class (like NSObject) the compiler knows it, but you implement the extension before that point. You could avoid the error by defining the protocol to be implemented by a class that inherits from NSObject, like this:
#objc protocol AProtocol {
func veryImportantMethod()
}
protocol BProtocol : AProtocol {
}
class BProtocolClass: NSObject {
}
extension BProtocolClass {
func veryImportantMethod() {
print("A's protocol requirement satisfied!")
}
}
class ConcreteClass: BProtocolClass {
}

Swift protocol extension method dispatch with superclass and subclass

I found an interesting behaviour which seems like a bug...
Based on the behaviour described the following articles:
https://medium.com/ios-os-x-development/swift-protocol-extension-method-dispatch-6a6bf270ba94
http://nomothetis.svbtle.com/the-ghost-of-swift-bugs-future
The output is not what I expect, when I add SomeSuperclass, rather than directly adopting the protocol.
protocol TheProtocol {
func method1()
}
extension TheProtocol {
func method1() {
print("Called method1 from protocol extension")
}
func method2NotInProtocol() {
print("Called method2NotInProtocol from protocol extension")
}
}
// This is the difference - adding a superclass
class SomeSuperclass: TheProtocol {
}
// It works as expected when it simply adopts TheProtocol, but not when it inherits from a class that adopts the protocol
class MyClass: SomeSuperclass {
func method1() {
print("Called method1 from MyClass implementation")
}
func method2NotInProtocol() {
print("Called method2NotInProtocol from MyClass implementation")
}
}
let foo: TheProtocol = MyClass()
foo.method1() // expect "Called method1 from MyClass implementation", got "Called method1 from protocol extension"
foo.method2NotInProtocol() // Called method2NotInProtocol from protocol extension
Do you know if this is a bug, or by design? A colleague suggested perhaps mixing inheritance and protocol extensions might not work as expected. I was intending to use the protocol extension to provide a default implementation... if I can't do it, then I will sadly have to mark it #objc and go back to an optional protocol.
From the post The Ghost of Swift Bugs Future, here are the rules for dispatch for protocol extensions that are mentioned at the end of the post.
IF the inferred type of a variable is the protocol:
AND the method is defined in the original protocol THEN the
runtime type’s implementation is called, irrespective of whether
there is a default implementation in the extension.
AND the method is not defined in the original protocol, THEN the
default implementation is called.
ELSE IF the inferred type of the variable is the type THEN the type’s implementation is called.
So in your condition, you're saying that method1() is defined in the protocol and it has been implemented in the subclass. But your superclass is adopting the protocol but it is not implementing the method1() and subclass just inherits from the Superclass and doesn't adopt to the protocols directly. That's why I believe that is the reason when you call foo.method1(), it doesn't invoke the the subclass implementation as stated by point 1 & 2.
But when you do,
class SomeSuperclass: TheProtocol {
func method1(){
print("super class implementation of method1()")}
}
class MyClass : SomeSuperclass {
override func method1() {
print("Called method1 from MyClass implementation")
}
override func method2NotInProtocol() {
print("Called method2NotInProtocol from MyClass implementation")
}
}
and then when you call,
let foo: TheProtocol = MyClass()
foo.method1() // Called method1 from MyClass implementation
foo.method2NotInProtocol()
So what could be the workaround for this bug (which seems to be a bug) is that, you need to implement the protocol method in the superclass and then you need to override the protocol method in the sub class. HTH
Please check the code below:
import UIKit
protocol TheProtocol {
func method1()
func method2NotInProtocol()
}
extension NSObject {
func method1() {
print("Called method1 from protocol extension")
}
func method2NotInProtocol() {
print("Called method2NotInProtocol from protocol extension")
}
}
// This is the difference - adding a superclass
class SomeSuperclass :NSObject, TheProtocol {
override func method1() {
print("Called method1 from SomeSuperclass implementation")
}
}
// It works as expected when it simply adopts TheProtocol, but not when it inherits from a class that adopts the protocol
class MyClass : SomeSuperclass {
override func method1() {
print("Called method1 from MyClass implementation")
}
override func method2NotInProtocol() {
print("Called method2NotInProtocol from MyClass implementation")
}
}
let foo: TheProtocol = MyClass()
foo.method1() // expect "Called method1 from MyClass implementation", got "Called method1 from protocol extension"
foo.method2NotInProtocol() // Called method2NotInProtocol from protocol extension
Instead of writing extension to TheProtocol, write extension to a abstract class(NSObject in above code). This works as expected.
An option that hasn't been considered is to split up your protocol into several smaller ones, such that the superclass does not need to conform to protocols containing methods it does not intend to implement. The subclass can then subscribe to these other protocols separately.

Override function error in swift

I got a struct :
struct ErrorResultType: ErrorType {
var description: String
var code: Int
}
and a protocol:
protocol XProtocol {
func dealError(error: ErrorResultType)
}
Now I want to make an extention of UIViewController:
extension UIViewController: XProtocol {
func dealError(error: ErrorResultType) {
// do something
}
}
So I can subclass from this and override the function like:
class ABCViewController: UIViewController {
--->override func dealError(error: ErrorResultType) {
super.dealError(error)
// do something custom
}
}
But it goes wrong with: Declarations from extensions cannot be overridden yet
It doesn't make any sense to me. When I replace all ErrorResultType with AnyObject, the error won't appear any more.
Anything I missed?
For now the method in the extension must be marked with #objc to allow overriding it in subclasses.
extension UIViewController: XProtocol {
#objc
func dealError(error: ErrorResultType) {
// do something
}
}
But that requires all types in the method signature to be Objective-C compatible which your ErrorResultType is not.
Making your ErrorResultType a class instead of a struct should work though.
If i am not making mistake this is connected with Swift official extension mechanism for adding methods to classes.
Conclusion :
At the moment, it's not possible to override entities declared in
extension by subclassing, like so:
class Base { }
extension Base {
var foo: String { return "foo" }
}
class Sub: Base {
override var foo: String { return "FOO" } // This is an error
}
Please check this resource for more information : https://github.com/ksm/SwiftInFlux/blob/master/README.md#overriding-declarations-from-extensions

Error conforming to a self made protocol in Swift

I've created a protocol in one of my ViewControllers above the class declaration like so:
#class_protocol protocol CRAAddCredentialDelegate {
func didAddCredential()
}
class CRAAddCredentialTableViewController: UITableViewController {
....
}
However, when I try to conform to this protocol:
class CRAMainViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, CRAAddCredentialDelegate {
....
}
I get an error:
What am I doing wrong?
Have you added the function didAddCredential() to your CRAMainViewController class?
By adding the , CRAAddCredentialDelegate to the list of protocols, you're indicating that your class will provide all of the variables and functions that protocol includes.
So you need to actually provide them.
class CRAAddCredentialTableViewController: UITableViewController {
func didAddCredential() {
// add code here
}
....
}
You should implement the required protocol. In your case func didAddCredential() declared in the protocol CRAAddCredentialDelegate is not implemented , so its giving error.

Resources