Passing object between NSViewController

Hi, I have a P1 protocol, whose methods and properties are implemented by the C1 class. In NSViewController VC1, object OBJ1 of class C1 is instantiated. VC1 loads a new NSViewController VC2 through the segue, which needs access to the OBJ1 object. What is the best method to make VC2 see the object OBJ1, being able to modify it and return it to VC1? Thanks.

Accepted Reply

If it is not executed, that means that connection between code and IB is damaged or that the segue if fired in another way than through the performSegue in IBAction.

May be you have defined both an IBAction and a segue in IB from the button to its destination ? In such a case, the IBAction is not executed but the segue is fired.

If so,

  • remove the segue in Interface Builder from Button to destination
  • recreate the segue (same identifier) but form the VC to the desination (control drag from the left icon at top of VC in IB to the destination).
  • select the type of segue you want (show for instance)

Otherwise, if that's not the case:

  • Remove the connection (the black dot should disappear)
  • Reconnect the button to its IBAction
  • Do a Clean Build Folder

That should work now.

Replies

A very good way is to use delegation.

See example here in this old thread:https://developer.apple.com/forums/thread/112517?answerId=345249022#345249022

Hi,

This thread uses the protocol implementation performed by NSViewController, which was the previous situation I posted (already resolved). Now the implementation of the protocol is done in a class, as described below.

This is just a study to understand how to pass an instantiated object of a class between two NSViewControllers.

Here is the Protocol.

Here is the definition of the class that implements the protocol.

Here is the definition of the first NSViewController .

Here is the definition of the second NSViewController.

In the first viewcontroller, on line 22, the class object is declared and instantiated, with default parameters. In the button's code on line 71, the object is instantiated with the values to be passed to the second viewcontroller, called on line 85, with the object's delegate. However, the values that arrive at the second viewcontroller are those declared on line 22.

Thanks.

when you post code, please post code, not screen shots.

In the IBAction (line 71), you redeclare objClasseCampos. That creates a NEW instance, which scope is only the IBAction and which is never used (except in the print).

@IBAction func btnCampos( sender: NSButton) f
  var objClasseCampos = ClasseCampos.init (_campoInt: 200, _campoDouble: 5.3, _campoData: DateO, _campoString: "Agostinho")
  print("Enviado\(objClasseCampos._campoString)")
  performSegue(withIdentifier:"segueVCCampos",sender:nil)
}

That does not update the var you declare line 22.

In prepare, you use the var you have declare at line 22, not the one of line 71.

Solution: remove var line 71:

@IBAction func btnCampos( sender: NSButton) f
  objClasseCampos = ClasseCampos.init (_campoInt: 200, _campoDouble: 5.3, _campoData: DateO, _campoString: "Agostinho") // <<-- CHANGE HERE
  print("Enviado\(objClasseCampos._campoString)")
  performSegue(withIdentifier:"segueVCCampos",sender:nil)
}

Note: take core of a typo here that may be source of errors in the future.

var campoDoouble

The solution of removing line 71 makes the application a single record! The application must be able to send different information to the second viewcontroller. There will be a field for each of the variables, allowing the user to fill in each of the variables in the class with whatever values they want. That is, it must be able to generate instances of the class with information that will be on the screen.

You did not read what I told you and probably you did not even test it !

I did not tell you to remove line 71 but to remove var on line 71, as shown in code:

@IBAction func btnCampos( sender: NSButton) f
  objClasseCampos = ClasseCampos.init (_campoInt: 200, _campoDouble: 5.3, _campoData: DateO, _campoString: "Agostinho") // <<-- CHANGE HERE: No var before objClasseCampos
  print("Enviado\(objClasseCampos._campoString)")
  performSegue(withIdentifier:"segueVCCampos",sender:nil)
}

As I explained: In the IBAction (line 71), you redeclare objClasseCampos. That creates a NEW instance, which scope is only the IBAction and which is never used (except in the print). What you want to do is to update the var declared line 22, because it is the one you use in prepare. And you can change the content of the var as often you want.

So, try it. If it does not give expected result, explain the problem (what you expect and what you get). If it works, don't forget to close the thread on the correct answer.

I forgot to say, but I had already done the test of removing the var from line 71, the result is always the same: it only shows the values declared in the instance created on line 22.

Replace line 71 as follows (don't recreate an instance but set the properties):

objClasseCampos._campoInt = 200
objClasseCampos._campoDouble = 5.3
objClasseCampos._campoData = DateO
objClasseCampos._campoString = "Agostinho"

You could also set directly the properties.

objClasseCampos.campoInt = 200
objClasseCampos.campoDouble = 5.3
objClasseCampos.campoData = DateO
objClasseCampos.campoString = "Agostinho"

And tell what you get from the print statement:

 print("Enviado\(objClasseCampos._campoString)")

Note: I don't understand why you declare those var:

var _campoInt: Int {
}

Hi Claude31, The code behavior is completely strange. I did the debbug, and the code inside the button's Action is simply not executed, that's why it doesn't show the changed values assigned to the properties, although VCCampos is called. So when loading VCCampos it takes the original creation of objClasseCampos

If it is not executed, that means that connection between code and IB is damaged or that the segue if fired in another way than through the performSegue in IBAction.

May be you have defined both an IBAction and a segue in IB from the button to its destination ? In such a case, the IBAction is not executed but the segue is fired.

If so,

  • remove the segue in Interface Builder from Button to destination
  • recreate the segue (same identifier) but form the VC to the desination (control drag from the left icon at top of VC in IB to the destination).
  • select the type of segue you want (show for instance)

Otherwise, if that's not the case:

  • Remove the connection (the black dot should disappear)
  • Reconnect the button to its IBAction
  • Do a Clean Build Folder

That should work now.

Hi Claude32, Sorted out. Both segues were pointed at the buttons as the first one I made was working like that. So I made the second one the same way. Now I switched the direct connection to the VC of the two buttons and everything works as I need. Thanks.

  • Wish you good continuation.

Add a Comment