DrainOpener
DrainOpener

Reputation: 196

Why protocol type never gets a value?

I am trying to understand more protocols. I could not figure out myProtocolFunction never call and print or passing the variable as below.

I think my problem is about initialization. When I try with two viewcontroller everything is okay but MyStruct protocol instance is nil. Thanks for your help.

class ViewController: UIViewController, MyProtocol {
    var myProtocolValue: String = ""
    
    var globalInstance = "a"

    override func viewDidLoad() {
        super.viewDidLoad()
                
    }
    
    
    @IBAction func click(_ sender: Any) {
        
        var myStruct = MyStruct()
        myStruct.myProtocol = self        
    }
    

    func myProtocolFunction(passing: String) {
        globalInstance = passing
        print("never print")
    }
}

protocol MyProtocol {
    func myProtocolFunction(passing: String)
}


struct MyStruct {

    var myProtocol: MyProtocol?
    
    init() {
        makeSomething()
    }
    
    func makeSomething() {
        myProtocol?.myProtocolFunction(passing: "abc")
        
    }
}

Upvotes: 0

Views: 41

Answers (3)

Shehata Gamal
Shehata Gamal

Reputation: 100533

1- You need to make

var myStruct = MyStruct() // an instance variable 

@IBAction func click(_ sender: Any) {
    
    myStruct.myProtocol = self        
}

2- Also you call init before even you set myProtocol as its called when you do var myStruct = MyStruct() and at that time myProtocol is nil as its not yet set

init() {
    makeSomething()
}

Check full working edit

class ViewController: UIViewController, MyProtocol {

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        
    }
    
    func myProtocolFunction(passing: String) {
        print(passing)
    }
     
    @IBAction func click(_ sender: Any) {
          
        var myStruct = MyStruct(self)
        
    }
     
}

protocol MyProtocol {
    func myProtocolFunction(passing: String)
}

struct MyStruct {

    var myProtocol: MyProtocol?
    
    init(_ mine:MyProtocol) {
        myProtocol = mine
        makeSomething()
    }
    
    func makeSomething() {
        myProtocol?.myProtocolFunction(passing: "abc")
        
    }
}

Upvotes: 1

Raja Kishan
Raja Kishan

Reputation: 18994

You need to create MyStruct() object out of the click action else when the scope is over your object is deinitialize.

Also, You have to call .makeSomething() function on the button click as the time of object creation delegate is nil.

var myStruct = MyStruct() // Create an instance here

@IBAction func click(_ sender: Any) {
    myStruct.myProtocol = self        
// Add your action
    myStruct.makeSomething()
}

Upvotes: 0

Mohmmad S
Mohmmad S

Reputation: 5088

Think about protocols as a type, in your struct you are basically saying that this struct have a variable of this type ( your protocol ) and on init you are trying to call its function.

What you're missing is setting an instance of type ( your protocol ) so it can get called.

for instance :

MyStruct = MyStruct(myProtocol: ViewController())

Now your nullable protocol have a value and can call it's function in another word, protocols can't have implementation directly into them they're more like a signature contract

Read more about protocols here.

Upvotes: 1

Related Questions