I have a document-based Core Data app. My main Core Data entity has several string fields, most of which are bound to NSTextFields, but one is bound to an NSTextView.
I am using the technique for view switching (with multiple view controllers) as explained in the Hillegass book. All of my subviews are controlled by a ManagedViewController, my subclass of NSViewController that has a managedObjectContext field.
My subview exists in a separate nib file. For some reason, the bindings I have set up in that nib are not working--but if I set up the widgets and the bindings in the exact same way in the main nib file instead, they work fine.
See image:
Screenshot http://img180.imageshack.us/img180/3391/screenshot.gif
In the main nib file, I have a tree controller whose managedObjectContext is bound to File's Owner's mOC (File's Owner is MyDocument). The NSTextField's value (yes, value--it's not rich text) is bound to treeController.selection.content (where content is a string property of the entity.) No problem. This works fine.
In the second nib file, I have another tree controller whose managedObjectContext is bound to File's Owner's mOC (File's Owner is my ManagedViewController). The NSTextField's value is bound the same way as above.
In my code, I have tested to make sure that the two managedObjectContexts refer to the same object. They do, and it's not nil.
I don't get an error--it's just that the values never bind with NSTextViews in the subview. They're always nil.
Also, I have tried NSTextFields--same problem.
Any ideas on how to make Core Data bindings play nicely with subviews and multiple NIBs?
You have two tree controllers. Each has its own knowledge of the selection. Try binding selectionIndexPaths from both of the tree controllers to a property of your document (you'll need to provide a way to get there through the view controller).
Related
I'm very new to objective-c and it seems my question is so basic there's nothing concise on it around (I just end up more confused by reading things).
When you create a .xib file, you link it to a controller (usually, I think). At the same time, you can do things you can do in .xib by defining views in code. I thought I understood part of it when I realized most of the items you drag onto a .xib are view objects. I guessed from there that .xib were somehow just representing real code for views. Is that accurate? Or am I completely wrong? I really have no idea.
Xib files do not represent real code for views, only the structure of the view's data. Each xib (or a storyboard) has enough information to do all of the following:
Instantiate elements of the view
Set properties of individual elements of the view
Connect elements of the view in a hierarchy
Connect "outlets" of objects in the Nib to properties or variables of views in your code.
However, there is no "real code" there, only the metadata. Cocoa has enough smarts to build and connect the objects, but the actual code is always in your .m files.
A view controller manages a view which is made up of many subviews. While, every view can have only one superview at most. ( superview is nil for the top-most view). This is called the view hierarchy.
The top level view in a hierarchy can be defined using pure code, or with Interface Builder, which produces a xib.
Its useful also to explore the relationship of view controllers to each other. Within one application window, there can also be several view controllers, each managing their own top-level view. This is called view-controller containment. An example of this is a UINavigationController or tab-bar controller. . .in more complex apps it is common to set up your own root controller that manages this aspect of controller heirarchies. (Eg swipe to reveal a navigation controller, which is under the main content cotroller).
A XIB describes arbitrary objects that conform to NSCoding but is usually used to layout a view hierarchy. So it'll be mostly UIViews, usually with a UIViewController.
However they're purely data. No code is generated. The system reads the XIBs and creates the objects purely as a data-reading exercise.
Objective-C has a fully reflective runtime — you can lookup classes by name as a string and can call methods on them the same way, without even knowing whether the method really exists in advance. Interface builders that secretly write code, such as Microsoft's in Visual C++, tend to do so because there's no way they could establish whatever you've described purely by parsing data.
In my application I have a single nib file. The File's Owner is a NSViewController and insider there is just a vertical slider that I want to bind to a property in one of my classes. (I don't have any other nib files since it is a status bar application, so I don't have a window). The nib is loaded runtime to create a custom view for a NSMenuItem.
The problem is that I want to use an object controller to do the binding but I'm not sure what is the content of the object controller. How can I access from the nib to an arbitrary class in my project?
In the examples I have seen, usually the object controller uses the File's Owner to access the class (and the property for the binding) setting the Content Object binding to the File's Owner. But in my case from the File's Owner I do not have access to the class.
Any pointer?
Ok this works for me. It is enough subclassing NSViewController and sets the new subclass as the File's Owner. Now it is possible to use a Controller Object to bind through the File's Owner.
If you use XCode 4 you can Control-drag from the slider to the .h file (AppController.h?), and you will get the option to generate an outlet or an action. If you want to create an action, caused by sliding the slider, you should select action. The generated method will be called whenever the slider is changed. If you want the slider value to react to an event (or a changed instance variable in your program), set it to 'outlet'.
Hope that helps, let me know if you were really looking for something else :-)
The issue i am facing deals with multiple views, each needing to communicate with one another. I chose to use the File Owner for this, but can't seem to be able to access the already loaded instance of it from inside of views.
Each rectangle represents its own view
Activity will happen on "Some View", where user's event will cause Labels in top view to be updated
Event will not be triggers by a button click of anything like that. No outputs are set up to establish relationships between the views
No outlets are set up between the views
Outlets are setup however between top Views (with Labels) and File Owner (UIViewController).
Ultimately, i'd like to update label in view 1 from view 2.
Then the bar moves, I want labels to change
At this time, i believe a reasonable solution would be to ask the File Owner to make a change for Labels. From the "Some View", i'd like to call the File Owner and make a request.
From the stand point of the any view residing as part of the nib, how can i know who the "File Owner" of this nib is?
In the Interface Builder, File Owner maintains the IBOutlet to UILabels of the view.
You need to define a delegate (or whatever you like to call it) outlet in your Puzzle1 class and link this to File's owner in the nib. This will give you a pointer to the instance of the view controller that currently owns your view. If you set the type of the delegate to your viewcontroller subclass, then its methods and properties will be available to you from within the view.
This sounds potentially horrendously messy and is probably better solved by using NSNotifications.
But anyways, did you know there's a UINib class? Perhaps you could subclass that and keep track of the owners (which get passed in it's instantiateWithOwner: options: method) as things are loaded.
http://developer.apple.com/library/ios/#documentation/UIKit/Reference/UINib_Ref/Reference/Reference.html
I have a simple requirement.
On Click of a + button, I am trying to add a custom view to a SplitView.
I have created a class MyCustomView which is a subclass of NSView
In the applications nib file, I have a custom view which contains the buttons etc.
Now How to allocate a new MyCustomView every time ?
Is there an example to do this?
I am hoping something like
MyCustomView *v1 = [[MyCustomView alloc] init];
..
..
[splitView addSubView:v1];
[splitView addSubView:v2];
...
Please help
It's hard to tell exactly what you're describing based on your description but let's see if I understand you. You want to add a "copy" of your custom view assembly into a split view each time "+" is clicked, right?
The absolute best way to do this is to put the custom view assembly that will be copied (the "prototype") in its own xib. For each object you want to represent, you will instantiate a new copy from the xib and give it to some owner then add it to some parent view (a split view in your case ... odd for an unlimited number of views, but I don't have enough detail to say otherwise).
So. In the modern Cocoa world, such a view assembly should likely have its own view controller (NSViewController). This makes things easier for you since the xib's File's Owner will be an instance of your MyCustomViewController, whose -view is connected to the main container view in the xib (your custom view with all its subviews) and whose -representedObject is set to whatever model object your custom view represents. Your app will then maintain a list (an array or a dictionary, perhaps) of all the view controllers for the model objects. See this SO question/answer for a run-down of how to load from nibs/xibs.
This is basically how an NSCollectionView works (though the views must all be the same size - might not work for you). The collection view corresponds to your split view in this case; NSCollectionViewItem corresponds to your MyCustomViewController (and in fact on 10.5 and above NSCollectionViewItem is a subclass of NSViewController); your custom view is the collection view item's main -view. For each model object in its collection, it instantiates an NSCollectionViewItem and loads the view prototype from a xib (ideally, but this is optional), and uses this to set the item's view, then it sets the item's represented object (the model object).
I hope this clarifies things a bit. You've got some reading to do in order to understand enough of the nuts and bolts, but if you're still stuck, you might try editing your question to clarify or opening a new, more specific question.
I'm having an extremely difficult time trying to access information from an object (e.g. an NSTextField) that is located on a NIB other than my "MainMenu.nib".
My current setup:
I have a MainMenu.xib that contains only a toolbar at the top and an NSView. I have four other .xib files containing custom NSViews and each of their File Owner's are assigned to a NSViewController subclass which I have created for each. My MainMenu.xib contains an object that is set to my WindowController subclass that takes care of swapping the fours views into the NSView on my MainMenu.xib. All of this works fantastic.
Where I have a problem:
I have another class that acts as the brains to my application which sends and receives data from an online server, all of the methods I have created rely on inputs from the user that are located on the individual .xibs that swap into my MainMenu.xib's NSview. Unfortunately I have no idea on how to grab the information from the NSTextFields, textViews, etc. that are located on my individual .xib files.
What I've tried:
I have tried setting the File Owner's of the four individual .xibs to my "brains" class and connecting outlets defined in my "brains".h, but when I call [textField stringValue] I receive a NULL response. I'm thinking this is because I'm creating multiple instances of my "brains" class but not totally sure.
Any help on accessing information from textFields from other nibs would be a great benefit, thanks in advance.
each of their File Owner's are
assigned to a NSViewController
subclass which I have created for each
I think the easiest way (not the best way) is that your brain contains all 4 NSViewController subclass and you leak the information of the UITextField out using the property and then you can access them