Error conforming to a self made protocol in Swift - ios

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.

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?

Problem with type constrained protocols defined in a separate module

I'm running into an issue where type constrained protocols defined in a separate module aren't acknowledging the constrained type.
For example if I define the following protocol:
public protocol SomeVCProtocol where Self: UIViewController {
func something()
}
And conform to it:
extension SomeViewController: SomeVCProtocol {
func something() { }
}
let someVC: SomeVCProtocol = SomeViewController()
someVC.something()
someVC.present(UIViewController(), animated: true)
There's no issue here. I can call the protocol-specific methods and UIViewController methods. However the moment I define SomeVCProtocol in a separate module, I no longer have access to the UIViewController methods. Is this just a shortcoming of Swift, or am I just missing something?

Cannot satisfy protocols (with associatedtype) comformance

I'm working with CleanSWift in my new project and I'm facing that it's too wordy. To automate some of the basic stuff, I wrote following tools (simplified):
// MARK: - Presenter
protocol Presenter {
associatedtype DisplayLogic
var viewController: DisplayLogic? { get set }
}
protocol PresentationLogic {
func show(_ error: Error)
}
extension PresentationLogic where Self: Presenter, Self.DisplayLogic: DefaultDisplayLogic {
func show(_ error: Error) {
}
}
// MARK: - Display logic
protocol DefaultDisplayLogic: class {
// func present(_ error: Error)
}
protocol TableViewDisplayLogic: DefaultDisplayLogic {
// func reloadTableView(with sections: [Section])
}
When I try to implement the code above, generics seems to be broken. I'm getting an error saying "Type 'MyPresenter' does not conform to protocol 'PresentationLogic'." However, everything seems fine to me.
// MARK: - Controller
protocol MyDisplayLogic: DefaultDisplayLogic {
}
class MyViewController: UIViewController, MyDisplayLogic {
}
// MARK: - Interactor
protocol MyBusinessLogic {
}
class MyInteractor: MyBusinessLogic {
var presenter: MyPresentationLogic?
func test() {
presenter?.show(TestError.unknown)
}
}
// MARK: - Presenter
protocol MyPresentationLogic: PresentationLogic {
}
class MyPresenter: Presenter, MyPresentationLogic {
weak var viewController: MyDisplayLogic? // ** Here I get the error. **
}
Any ideas? Thank you.
Currently, MyPresenter doesn't fulfill the requirements of the where clause of the PresentationLogic extension, so it can't use the default implementation of show(_:). Specifically, it doesn't pass the test for Self.DisplayLogic: DefaultDisplayLogic. Therefore, it doesn't conform to PresentationLogic, and so it also doesn't conform to MyPresentationLogic, which inherits from PresentationLogic.
But why not? I think it's caused by how Swift works: protocols can't conform to themselves. In MyPresenter, Self.DisplayLogic is MyDisplayLogic. Though it is a descendent protocol of DefaultDisplayLogic, it still seems to function as "a protocol trying to conform to itself", so it doesn't work.
To demonstrate this, you can replace weak var viewController: MyDisplayLogic? with weak var viewController: MyViewController, and the error will go away, since it's a concrete type that conforms to DefaultDisplayLogic. Also, if you change Self.DisplayLogic: DefaultDisplayLogic in the where clause to Self.DisplayLogic == MyDisplayLogic, the error will go away because you are requiring a specific type rather than a conformance.
In your case, a possible solution is to make MyPresenter a generic class. For example:
class MyPresenter<ConcreteDisplayLogic: DefaultDisplayLogic>: Presenter, MyPresentationLogic {
weak var viewController: ConcreteDisplayLogic?
}
That will allow you to use the same where clause constraints for your default implementation of show(_:), while providing a type-safe, generic implementation of MyPresenter.
There is a limitation to this approach: you can't change the type of the value of viewController for a single instance of MyPresenter.

Swift delegate does not inherit NSObject

I am trying to implement some sort of delegate broadcaster (Observer Pattern) in Swift to register multiple delegates. To use the "isEqual" function I need the generic to inherit from NSObject
To avoid duplicate code I prepared a generic DelegateBroadcaster:
import UIKit
class DelegateBroadcaster<T : NSObject>: NSObject {
var delegates : [T]
override init() {
delegates = []
}
func addDelegate(newDelegate : T) {
delegates.append(newDelegate)
}
func removeDelegate(oldDelegate : T) {
for i in 0...delegates.count-1 {
if (oldDelegate.isEqual(delegates[i])) {
delegates.removeAtIndex(i)
break
}
}
}
}
and subclass this for any specific broadcaster.
import UIKit
class NavigationControllerBroadcaster : DelegateBroadcaster<UINavigationControllerDelegate> {
}
But I get a strange error: "DelegateBroadcaster requires that 'UINavigationControllerDelegate' inherit from NSObject"
This is strange because the class reference by apple (Class Reference) says that UINavigationControllerDelegate inherits from NSObject.
So why do I get an error?
You are confusing class NSObject (NSObject class) and protocol NSObject (NSObject protocol, in Swift called NSObjectProtocol).
UINavigationControllerDelegate is a protocol and cannot inherit from class NSObject, it inherits from NSObjectProtocol (switch your documentation to Swift, you will see the difference).
UINavigationControllerDelegate is not a concrete type, it is a Protocol and therefore cannot be used as the type signature for the DelegateBroadcaster

How to call protocol from another viewcontroller?

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!)
}

Resources