 |
 |
How do I pass two references into a NIB?
|
 |
|
 |
|
Mac Enthusiast
Join Date: Dec 2001
Status:
Offline
|
|
Though I've been dabbling in it off and on for a few months, I still feel like I'm new to Cocoa. I'm writing a simple app as a learning project and while I know I could push through and get it done by brute force, I'd really like to understand the Cocoa way of architecting the app.
Here's my problem. In my app, the user can create and edit data objects. There is a main window, which displays the objects in an NSTableView, and then there is a editor window that can be opened for any object so that it can be edited. I've created a special nib file with the editor window, so that I can open up multiple editors for multiple simultaneous objects.
The problem I have is that each editor window needs associated with it a data object, a controller object, and a callback object (so the table can be updated when editing is done). I can put the controller instance in the nib, but then I need a way to pass in the data object and the callback object. I understand the "file's owner" is a way to pass in a single object, but is there a way to pass more than one? Do I need to create a special method in "file's owner" just to pass in these items? This seems kind of lame to me.
|
|
|
| |
|
|
|
 |
|
 |
|
Mac Elite
Join Date: Sep 2000
Location: Norfolk, Va
Status:
Offline
|
|
I think that file's owner is representative of an entire class, so your new controller object can query those needed variables from this one object.
In other words, instead of passing in the data and callback objects, just make sure that File's owner has access to those variables so that your editorController can retreive them from File's owner.
Also, if I'm not mistaken, File's owner is or can be set to be the callbacl object you want anyway.
I would do it this way:
The controller is in the nib.
When the nib is created by your Application, send controller an init method you create such as initWithData:.
Set File's Owner to be the callback object.
Corect me here, guys. This should be the gist of it though.
|
|
you are not your signature
|
| |
|
|
|
 |
|
 |
|
Mac Enthusiast
Join Date: Dec 2001
Status:
Offline
|
|
So, that's another question. When you load a nib, using NSBundle+loadNibNamed:owner you have no way of getting a reference out of the nib either. If you can't get a reference out, how can you call an init method on any object in the nib?
Instead, it seems the only thing you can do is load the nib, passing in an owner/callback object). Then, have the nib objects call back to you and pass the references you need and request the references needed for objects in the nib.
I can deal with this, but I find this kind of ugly, because there are three sections of code that are involved: - The method where the nib is loaded
- the callback method needed to send references to objects loaded from the nib
- The awakefromnib method that calls back to get the references
I'd rather have all this code specified in a single place, the section of code where the nib is loaded.
|
|
|
| |
|
|
|
 |
|
 |
|
Fresh-Faced Recruit
Join Date: Apr 2001
Status:
Offline
|
|
Originally posted by nickm:
So, that's another question. When you load a nib, using NSBundle+loadNibNamed:owner you have no way of getting a reference out of the nib either. If you can't get a reference out, how can you call an init method on any object in the nib?
Instead, it seems the only thing you can do is load the nib, passing in an owner/callback object). Then, have the nib objects call back to you and pass the references you need and request the references needed for objects in the nib.
I can deal with this, but I find this kind of ugly, because there are three sections of code that are involved:- The method where the nib is loaded
- the callback method needed to send references to objects loaded from the nib
- The awakefromnib method that calls back to get the references
I'd rather have all this code specified in a single place, the section of code where the nib is loaded.
The nib sends the init message to all objects in the nib. The awakeFromNib method is then called, where you can set the values of the outlets. This method guarantees that all the outlet connections have been made and that the outlets are available in your controller (ie. not nil).
I am not sure what you are doing with the callback, but since all your updates should go through your controller(s), then after updating an object, you need to have the controller that owns the nib with the NSTableView send the [yourTableViewViewVariable reloadData] message. Then, yourTableViewVariable table will ask its datasource for the data necessary to load the visible portion of the table. Of course, the datasource would be pointing to the same object(s) that you just updated.
I do not usually think of sending messages to the nib or its objects. I tend to view it as I set my controller's outlets and my controller recieves messages from the objects in the nib.
If you are dealing with multiple controllers, then your main controller probably creates the other controllers and holds a reference to them. You can have the designated initialize of those other controllers have a reference to the creating controller if you want. It is often easier just to use a notification to let any other interested observers (such as you controller with the tableView) know when something has changed.
Were is your prior experience (ie. C++, assembler, Java, etc.)?
|
|
|
| |
|
|
|
 |
|
 |
|
Mac Enthusiast
Join Date: Dec 2001
Status:
Offline
|
|
The nib sends the init message to all objects in the nib. The awakeFromNib method is then called, where you can set the values of the outlets.
I'm down with awakeFromNib, but I hadn't heard of init. Does this mean that each instance archived in the nib potentially gets two messages? An init upon first being "awaken" and an awakeFromNib after all the outlets are connected?
since all your updates should go through your controller(s), then after updating an object, you need to have the controller that owns the nib with the NSTableView send the [yourTableViewViewVariable reloadData] message.
Right, but the only object that knows whether the data has changed is the editor window's controller. So, it either has to have a reference to the NSTableView or it's controller in order to get it to update. That doesn't change the fact that I still have to pass in two references to the editor window's controller, (1) the data object to be edited and (2) a NSTableView or it's controller.
I do not usually think of sending messages to the nib or its objects. I tend to view it as I set my controller's outlets and my controller recieves messages from the objects in the nib.
So, you don't put an instance of the controller in the nib? That is another thing that confuses me. The controller potentially needs to have all kinds of connections to the interface objects in the nib, so it seems easier to put it in the nib and make those connections in IB. But, the controller also needs to have connections with objects outside the nib, but that argues for creating an instance of the controller outside the nib. Is there a "correct" way to do this?
It is often easier just to use a notification to let any other interested observers (such as you controller with the tableView) know when something has changed.
Yes, but that still requires passing the reference somehow. There are a lot of ways to do it, but any way I do that I still have the basic problem of passing multiple references to the objects in the nib. I suppose I could use the convention of sending a refresh method to the shared application's delegate or something like that any time the data changed. But there are still problems with that solution, because the table's controller needs to know which object was updated, etc.
Were is your prior experience (ie. C++, assembler, Java, etc.)?
In order of decreasing experience: Java, Matlab, C, Python, Scheme, Objective-C. Truth be told, this is actually a Cocoa java project, but I don't think that is relevant to the discussion.
|
|
|
| |
|
|
|
 |
|
 |
|
Fresh-Faced Recruit
Join Date: Apr 2001
Status:
Offline
|
|
Each instance gets one init message. The awakeFromNib guarantees that all the outlets have been instantiated.
Unfortunately, I have not seen a simple example using multiple controllers that talk to each other. Perhaps one will appear, or if I have time, I will come up with one.
But, if you use notifications you can do something along the lines of:
[[NSNotificationCenter defaultCenter] postNotificationName:@"YourNotificationName" object:yourObjectYourAreModifying];
Your table controller would register for the notification, ie:
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(tellMyTableToUpdate: )
name:@"YourNotificationName" object:nil];
If you passed a reference to the object you modified, then you just need to tell the table to reload (ie. [yourTable reload]). Also, if you passed a reference to the actual object you are modifying, then your posting of the notification could pass nil as the object: arguement. If you passed a copy of the object, then the tellMyTableToUpdate: method would should first update your model object with the new values from the copied object that you passed in the notification.
If you are updating something like a TextField, then you will need to probably pass the updated object as an arguement in the posting of the notification.
Actually, I usually put an instance of my controller in the nib, but not always. I was just trying to explain how I view the process. For me, the instance of the controller in the nib is simply for "wiring" the actions and outlets. As for instances outside the nib, I would suggest taking a look at Apple's documentation on the Document Architecture if you have not yet had the opportunity. There are also some good Cocoa books that explain this also along with the the some design philosophy. Once again, this goes back to the lack of a good, "simple", example IMO for what you are doing. One thing you can also do is set a subclass of NSWindowController to be the File Owner and handle the process that way.
I am still confused what objects in the nib you are passing references to. Am I correct in assuming it is the objects represented in the TableView? If not, please correct me.
I have not done Java with Cocoa, so I do not know if that makes a difference, I assume not. My Java experience is on the server side, so I do not really know how Java handles UI issues.
I hope my rambling is not to confusing since it was done as a stream of conciousness. I like to use notifications since they are easy and you do not have to keep track of a bunch of references. However, in large apps you need to watch out for notification storms.
|
|
|
| |
|
|
|
 |
|
 |
|
Mac Enthusiast
Join Date: Dec 2001
Status:
Offline
|
|
But, if you use notifications...
I think this is a clean approach to what I want to do. I can pass in the data object as the file's owner when I modify the nib (if it is nil, that means that the user wants to modify a new data object). When the object is done being edited, I can post a notification on it, and all the listeners of the object can be informed. It seems pretty clean to me, and doesn't require passing in multiple references to the nib.
I am still confused what objects in the nib you are passing references to.
I didn't want to get to bogged down in the specifics, but you can think of my app as being like iTunes. I have a list of tracks in a table, and then I have an interface for editing track metadata in a nib. The user can either edit an existing track or create a new one.
So, when the nib awakens the first thing the window controller needs to do is discover whether it is editing a new object or an existing one (that's the first reference).
Second, when the user is done editing the track, the controller needs to know who to tell about it. I think the NSNotificationCenter can be used for this purpose.
Thanks for the response, by the way. I think this will work out well.
|
|
|
| |
|
|
|
 |
 |
|
 |
|
|
|
|
|

|
|
 |
Forum Rules
|
 |
 |
|
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts
|
HTML code is Off
|
|
|
|
|
|
 |
 |
 |
 |
|
 |
|