Delegate not working - ios

I have a protocol declared in a class
public protocol demoDelegate {
func willShowdemoResult(DemoGraph: UIView)
}
Now I am calling this in the same class where the protocol is declared.
public class Demo:UIViewController {
public var delegate : demoDelegate!
//some code
self.delegate.willShowdemoResult(self.demoGraph())
}
where demo graph returns a UI graph
func demoGraph() -> UIView {
//some code
return demoGraphView
}
I am getting an error that unexpectedly found nil while wrapping an optional value. I know the reason that I have not initialised the delegate. Can somebody guide me How to initialise the delegate here.
The function is being called in other class
class DemoResult: UIViewController, demoDelegate{
func willShowdemoResult(DemoGraph: UIView)
// some code
}
Please Help

You are getting the error, because Demo.delegate is nil when calling:
delegate.willShowdemoResult(self.demoGraph())
Before you make this call, make sure, that you have set the delegate property. I would recommend this right after initializing Demo or right after DemoResult got the address of the Demo-instance.
Let's assume, you have stored an instance of Demo in DemoResult.demoVC. Then you can set the delegate in DemoResult like this:
demoVC.delegate = self
BTW: It's better to use optional types to store delegates:
public var delegate: demoDelegate?
When delegate is optional, delegate?.willShowdemoResult(self.demoGraph()) won't crash, if delegate has not been initialized yet.

Related

How to create the Delegate Design Pattern within an Xcode Playground in Swift 5?

I encountered some kind of a problem while using a Swift Playground and trying to set up a simple Delegate Design.
The problem seems to be the fact, that protocols can not be marked as public but the source folder in a Playground is considered as a new Module. Therefore I can't find a solution for this problem.
Here is my code so far (IN THE SOURCE FOLDER, THE VIEWCONTROLLER IS IN THE PLAYGROUND FILE)
//MARK: - Imports
import UIKit
//MARK: - Protocols
protocol UIManagerDelegate {
func didChangePage(forward: Bool)
}
//MARK: - Properties & Initialisers
public class UIManager {
// Properties
private let parentView : UIView
private var delegate: UIManagerDelegate
// Initialisers
public init(for view: UIView, delegate: UIManagerDelegate) {
self.parentView = view
self.delegate = delegate
}
}
The error message I get is the following: Initializer cannot be declared public because its parameter uses an internal type. And when trying to mark the protocol as public, this also produces an error.
Do you guys have any idea on how to fix this issue?
Thanks a lot for your help in advance.
make the delegate public
public protocol UIManagerDelegate

Is it posible to create a default implementation of willSet on a class protocol

What I am trying to do is notify an object when it gets replaced as a delegate from my services object. I was wondering if there is a way to create a default implamintation of willSet so I do not have to duplicate code for each service object I create:
protocol BaseServiceDelegate: class {
var delegate: BaseServiceDelegate? {get set}
func servicesDelegateReferanceWasRemoved(service: BaseServiceDelegate)
}
extension BaseServiceDelegate {
willSet(newValue){
delegate?.servicesDelegateReferanceWasRemoved(self)
self = newValue
}
}
Im really not sure where to start with the syntax of the extension or if this is possible. The error with the above code is on the 'willSet' line: "Exspected declaration"
Thank you for your time
still not sure if its possible but i made some edits to insure you have access to the delegate object defined
the best answer I can find is to define a base Protocol:
protocol baseProtocol {
func informOfAction()
}
then implement this on your delegates that would like to also have this functionality:
protocol childProtocol: baseProtocol {
func somethingHappend()
func somethingElseHappend()
}
and when you create the object that conforms to childProtocol have the custom will set there
var delegate: childProtocol? {
willSet{
delegate?.informOfAction()
}
}
not as nice as i was looking for but not too bad, an extra 3 lines on all my objects similar to 'delegate'

Check if optional protocol method is implemented in Swift?

I have a swift protocol:
#objc protocol SomeDelegate {
optional func myFunction()
}
I one of my classes I did:
weak var delegate: SomeDelegate?
Now I want to check if the delegate has myFunction implemented.
In objective-c I can do:
if ([delegate respondsToSelector:#selector(myFunction)]) {
...
}
But this is not available in Swift.
Edit: This is different from: What is the swift equivalent of respondsToSelector? I focus on class protocols not on classes.
How do I check if my delegate has an optional method implemented?
Per The Swift Programming Language:
You check for an implementation of an optional requirement by writing
a question mark after the name of the requirement when it is called,
such as someOptionalMethod?(someArgument). Optional property
requirements, and optional method requirements that return a value,
will always return an optional value of the appropriate type when they
are accessed or called, to reflect the fact that the optional
requirement may not have been implemented.
So the intention is not that you check whether the method is implemented, it's that you attempt to call it regardless and get an optional back.
You can do
if delegate?.myFunction != nil {
}
I've found it successful to add an extension to the protocol that defines basic default implementation and then any class implementing the protocol need only override the functions of interest.
public protocol PresenterDelegate : class {
func presenterDidRefreshCompleteLayout(presenter: Presenter)
func presenterShouldDoSomething(presenter: Presenter) -> Bool
}
then extend
extension PresenterDelegate {
public func presenterDidRefreshCompleteLayout(presenter: Presenter) {}
public func presenterShouldDoSomething(presenter: Presenter) -> Bool {
return true
}
}
Now any class needing to conform to the PresenterDelegate protocol has all functions already implemented, so it's now optional to override it's functionality.
I normally implement it like this:
self.delegate?.myFunction?()
if the delegate methods returns a value:
var result = defaultValue
if let delegateResult = self.delegate?.myFunction?() else {
result = delegateResult
}
//do something with result
Declaration
#objc public protocol nameOfDelegate: class {
#objc optional func delegateMethod(_ varA: int, didSelect item: Item)
}
Implimetation
if let delegate = nameOfDelegate {
delegate.delegateMethod?(1, didDeselect: node)
}
I know this question is 5 years old, but I would like to share what I found. My solution works as of 2021, XCode 11+, Swift 5.
Say I wanted to figure out whether the function sign follows the GIDSignInDelegate protocol and also know what all the optional functions for GIDSignInDelegate are.
I have to look at the source code of the GIDSignIn module, and this is how.
Click on jump to definition on the main module that is imported. It will lead to a file like this:
Copy the entire line, import GoogleSignIn.GIDSignIn and paste it in the ViewController or whatever .swift file (doesn't really matter).
Within the swift file, right click on the GIDSignIn part of the import line GoogleSignIn.GIDSignIn and jump to definition. This will lead you to the actual module with all the available functions (the functions not marked optional may be stubs, which are required functions in the delegate protocol):
From this file, I can see that there is a sign function that is a stub of GIDSignInDelegate and an optional sign function that is implemented as a method overload.
I used this for GIDSignInDelegate, but you can use the same method to figure out whether any function follows any delegate protocol.

Override var conforming to a protocol with a var conforming to a child of the overridden var protocol

This is my inheritance structure
Protocols
protocol BaseProtocol {
}
protocol ChildProtocol: BaseProtocol {
}
Classes
class BaseClass: NSObject {
var myVar: BaseProtocol!
}
class ChildClass: BaseClass {
override var myVar: ChildProtocol!
}
I'm receiving a compiler error:
Property 'myVar' with type 'ChildProtocol!' cannot override a property with type 'BaseProtocol!'
What is the best approach to achieve this?
UPDATE
I updated the question trying to implement the solution with generics but it does not work :( This is my code (now the real one, without examples)
Protocols
protocol TPLPileInteractorOutput {
}
protocol TPLAddInteractorOutput: TPLPileInteractorOutput {
func errorReceived(error: String)
}
Classes
class TPLPileInteractor<T: TPLPileInteractorOutput>: NSObject, TPLPileInteractorInput {
var output: T!
}
And my children
class TPLAddInteractor<T: TPLAddInteractorOutput>: TPLPileInteractor<TPLPileInteractorOutput>, TPLAddInteractorInput {
}
Well, inside my TPLAddInteractor I can't access self.output, it throws a compiler error, for example
'TPLPileInteractorOutput' does not have a member named 'errorReceived'
Besides that, when I create the instance of TPLAddInteractor
let addInteractor: TPLAddInteractor<TPLAddInteractorOutput> = TPLAddInteractor()
I receive this other error
Generic parameter 'T' cannot be bound to non-#objc protocol type 'TPLAddInteractorOutput'
Any thoughts?
#tskulbru is correct: it can't be done, and this has nothing to do with your protocols. Consider the example below, which also fails…this time with Cannot override with a stored property 'myVar':
class Foo {
}
class Goo: Foo {
}
class BaseClass: NSObject {
var myVar: Foo!
}
class ChildClass: BaseClass {
override var myVar: Foo!
}
To understand why, let's reexamine the docs:
Overriding Properties
You can override an inherited instance or class property to provide
your own custom getter and setter for that property, or to add
property observers to enable the overriding property to observe when
the underlying property value changes.
The implication is that if you are going to override a property, you must write your own getter/setter, or else you must add property observers. Simply replacing one variable type with another is not allowed.
Now for some rampant speculation: why is this the case? Well, consider on the one hand that Swift is intended to be optimized for speed. Having to do runtime type checks in order to determine whether your var is in fact a Foo or a Bar slows things down. Then consider that the language designers likely have a preference for composition over inheritance. If both of these are true, it's not surprising that you cannot override a property's type.
All that said, if you needed to get an equivalent behavior, #tskulbru's solution looks quite elegant, assuming you can get it to compile. :)
I don't think you can do that with protocols
The way i would solve the problem you are having is with the use of generics. This means that you essentially have the classes like this (Updated to a working example).
Protocols
protocol BaseProtocol {
func didSomething()
}
protocol ChildProtocol: BaseProtocol {
func didSomethingElse()
}
Classes
class BaseClass<T: BaseProtocol> {
var myProtocol: T?
func doCallBack() {
myProtocol?.didSomething()
}
}
class ChildClass<T: ChildProtocol> : BaseClass<T> {
override func doCallBack() {
super.doCallBack()
myProtocol?.didSomethingElse()
}
}
Implementation/Example use
class DoesSomethingClass : ChildProtocol {
func doSomething() {
var s = ChildClass<DoesSomethingClass>()
s.myProtocol = self
s.doCallBack()
}
func didSomething() {
println("doSomething()")
}
func didSomethingElse() {
println("doSomethingElse()")
}
}
let foo = DoesSomethingClass()
foo.doSomething()
Remember, you need a class which actually implements the protocol, and its THAT class you actually define as the generic type to the BaseClass/ChildClass. Since the code expects the type to be a type which conforms to the protocol.
There are two ways you can go with your code, depending what you want to achieve with your code (you didn't tell us).
The simple case: you just want to be able to assign an object that confirms to ChildProtocol to myVar.
Solution: don't override myVar. Just use it in ChildClass. You can do this by design of the language Swift. It is one of the basics of object oriented languages.
Second case: you not only want to enable assigning instances of ChildProtocol, you also want to disable to be able to assign instances of BaseProtocol.
If you want to do this, use the Generics solution, provided here in the answers section.
If you are unsure, the simple case is correct for you.
Gerd

Swift delegate & optional

I've declared this protocol
protocol ReactorDelegate {
func ReactorUpdateUI()
}
In my Model I have a delegate optional property and checking if isn't nill, unwrap it to call the protocol methode provided by the VC.
var delegate:ReactorDelegate?
if delegate {delegate?.ReactorUpdateUI()}
My VC follows the protocol and has the ReactorUpdateUI methode
class VC_Reactor: UIViewController, ReactorDelegate
I'm trying to create an instance of the Model in the VC but this fails
let reactorCore=Reactor()
ERROR: 'Reactor' is not constructible with '()' what let's me know that not all properties have an initial value.
I can work-around it by making my delegate in the VC an implicitly unwrapped optional
var reactorCore:Reactor!
and in the ViewDidLoad with a custom init: reactorCore=Reactor(delegate:self)
I don't understand why I need a custom init(delegate:ReactorDelegate) if I declare the delegate property optional.
You need to mark the method as optional in your delegate protocol:
#objc protocol ReactorDelegate {
optional func ReactorUpdateUI()
}
Then mark your class as #objc and use optional chaining on the method, too:
delegate?.ReactorUpdateUI?()
Note: When writing a protocol, it's easiest to keep everything required and stub out the methods in your class, then when everything works go back and make what you want optional be optional. The error messages you get are pretty opaque, so this way you're working with fewer issues at a time.
You have to declare your protocol like this:
protocol ReactorDelegate: class {
func ReactorUpdateUI()
}
And after, your delegate:
weak var delegate: ReactorDelegate
delegate?.ReactorUpdateUI()

Resources