icekomo
icekomo

Reputation: 9466

trying to understand protocols and delegates in swift

I'm trying to wrap my head around protocols and delegates, but seems to be having some issues. I have 2 ViewControllers that I'm trying to pass data from. ViewController A has a text field that I want to be optionally populated from ViewController B. So there is a button on ViewController A that segues you over to ViewController B This is how I have B set up.

 protocol AddPlayersViewControllerDelegate{
    var playersName:String? { set get }
}

class B-Controller: UIViewController, UITableViewDelegate, UITableViewDataSource{

    var addPlayerDelegate:AddPlayersViewControllerDelegate?

    override func viewDidLoad() {
            super.viewDidLoad()
    ..etc

    }

I'm using this code in my viewControllers B class to dismiss the currentView when a cell is selected

   func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {


        println("did select")
        let cell = playerTableView.cellForRowAtIndexPath(indexPath)

        addPlayerDelegate?.playersName? = "New Name"

        if let navController = self.navigationController {
            navController.popViewControllerAnimated(true)
        }
    }

It's not allowing me to set the players Name property inside the protocol here. It keeps returning me Nil when I check it from ViewController A.

View Controller A looks like this:

    class A-ViewController: UIViewController, UITextFieldDelegate, AddPlayersViewControllerDelegate{

var addPlayerDelegate:AddPlayersViewControllerDelegate?
}

//then I'm just trying to print out the new name the was set in ViewController B

override func viewWillAppear(animated: Bool) {

println("this is the selected players name \(addPlayerDelegate?.playersName)") - returns nil

}

I'm sure I'm not fully understanding something, but I feel that I just keep reading and trying out examples only to end back up here where I started from.

//************************* UPDATE *************************//

I'm going to try and simplify my set up. I have 2 View Controllers, VC-A, and VC-B.

VC-A has a text field and a button. VC-B has a tableview. I want the option to have the textField to be populated from the cell.text from CB-B, but only if the user taps the button to view VC-B. So the first time that VC-A loads, it should being back nil from my playersName string from the protocol, because VC-B has never been called as of yet. But once the user taps the button inside VC-A to view VB-B and then selected a cell, which would dismiss VC-B and populate the playersName string inside the protocol on the VC-B class, then I'm using the viewWillAppear method to check to see if playersName has been set and if so use it. Here is my updated code from the help you have given me.

VC-A

class FirstViewController: AddPlayersViewControllerDelegate{

    var playersName:String?

    let svc = LookUpViewController()

    override func viewDidLoad() {
        super.viewDidLoad()

        svc.addPlayerDelegate = self
    }
}

VC-B

protocol AddPlayersViewControllerDelegate{
    var playersName:String? { set get }
}


class LookUpViewController: UIViewController, UITableViewDelegate, UITableViewDataSource{

    var addPlayerDelegate: AddPlayersViewControllerDelegate?  
    override func viewDidLoad() {
        super.viewDidLoad()
    }
}


    func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {

        let cell = playerTableView.cellForRowAtIndexPath(indexPath)

        addPlayerDelegate?.playersName = "Ziggy"


        println("the name to be pass is \(addPlayerDelegate?.playersName)")

        if let navController = self.navigationController {
            navController.popViewControllerAnimated(true)
        }
    }

It seems that I'm still getting nil even when I got back to VC-A from VC-B. All I want is to be able to get some data (string) from VC-B and use it in VC-A, but only after the user uses the VC-B class. Does that make sense?

Upvotes: 0

Views: 719

Answers (1)

matt
matt

Reputation: 534950

You have shown that in the BController you have a property addPlayerDelegate:

var addPlayerDelegate:AddPlayersViewControllerDelegate?

And you have shown that in the BController you talk to that property:

addPlayerDelegate?.playersName? = "New Name"

But you have not shown that at any point in the lifetime of this controller, its addPlayerDelegate property is ever set to anything. For example I would want to see code like this:

someBController.addPlayerDelegate = someAController

If that doesn't happen, then that property remains at its initial value of nil.


Another problem with your code is that this line makes no sense:

class A-ViewController : // {
    var addPlayerDelegate:AddPlayersViewControllerDelegate?
}

The AController doesn't need this property. They don't both need delegates! What the AController needs is a playersName property. Without it, it doesn't conform to the AddPlayersViewControllerDelegate protocol. In fact, I'm surprised that without that property your code even compiles. Are you sure you are reporting it correctly?

Upvotes: 4

Related Questions