I am experimenting creating views that contain View based TableViews, ie: NSOutlineView and would like to better understand the correct connections that are made within IB.
At the moment, I have created a MainWindow that has the AppDelegate assigned to it.
On top of this, I have introduced a NSOutlineView which ultimately have an array as its data source.
I would like to have a separate Controller to look after this and its sub-views.
The NSOutlineView is made up of:
NSTableColumn
NSTableViewCell
NSTextField
With my NSTableCellView I have added two NSTextFields, the top one will be used as a Title and the second is a mini and will be used for displaying descriptions.
The issue I am facing is what controls need to have an IBOutlet connected to it.
My logic is; the only controls that will exhibit a change are the NSTableView as there needs to be a separate TableView within the TableColumn which will be a result of the item.count in the array.
Secondly, I am assuming that an IBOutlet will need to point to each of the TextField’s in the TableViewCell which will allow them to display the correct information for each item.count in the array.
So, all I need to do is design a Controller that has three IBOutlets.
Have I got my basics right….. or am I way off track?
I don't get everything you are asking for but first of all you don't set outlet to your NSTableView you need to use a NSArrayController, KVC and bindings.
1) in your AppDelegate.h create an IBOutlet to your NSArrayController:
#interface AppDelegate : NSObject <NSApplicationDelegate>
{
IBOutlet NSArrayController *yourArrayController;
}
2) in AppDelegate.m put your input or whatever in the NSArrayController:
yourItem *newItem = [[yourItem alloc] init];
[newItem setValue:[_inputVar stringValue] forKey:#"name"]; //use Key Value Coding
...
[yourArrayController addObject:newItem];
3) now go to your .xib and draw a NSArrayController object (green bubble with 3 blue cubes) in the dock (the area left to the .xib).
4) in your tableview click three times at each row and open the Bindings inspector
5) go to "Value" and activate "Bind to", select yourArrayController
6) set Controller Key to "arrangedObjects"
7) write the appropriate key in Model Key Path
Do that for each tableview column and you should be fine basically. No IBOutlet from the controller to you NSTableView!
The NSArrayController is taking care about user input back an forth to and from your tableview which is pretty convenient. I know not to answer all your questions but it might help you to get started. Good luck!
Related
I got an app with one main view and 5 other table views. Selecting row in each table changes some Labels in main view. Is it making main view as delegate of 5 table views right way to choose or there are other more elegant ways? Please, I need just ideas, no code lines. Thanks
it will be better if 5 tables will be present in other class. This will separate your code and code complexity will be less.
For labels, just declare one string in app delegate as
//in appdelegate.h
#property (nonatomic, strong) NSString *lblName;
//in appdelegate.m
#synthesize lblName;
Then,
In the class where tables are you can acess the label as
AppDelegate *app = (AppDelegate*)[[UIApplication sharedApplication] delegate];
then label text will be set as, app.lblName=#"Something";
You can access lblName in any class. Just you have to create share instance of app delegate using which you have to access lblName and other strings which you want to access.
Finaly when you come on the main view you can set the label text as
Your_label.text=app.lblName;
i am new into ObjC, unfortunately..
I have created a list and Tool bar at the bottom, with two buttons.
The first button does the list refresh,
the second one should be 'enabled' when you tap on a list item and when clicked it will perform additional work. This requires me to disable this button on start, but enable on didSelectRowAtIndexPath.
I want to grab a pointer to the second button on viewDidLoad method for later purposes.
Something like that would be great:
UIBarButtonItem* m_pButtonA = (UIBarButtonItem*) some_magic_function_to_call;
UIBarButtonItem* m_pButtonB = (UIBarButtonItem*) some_magic_function_to_call;
So i can later call the control method when required.
[m_pButtonRefresh method...]
Is this possible ? Thanks for any input.
In your custom view controller class, create an IBOutlet property, like this:
#property (nonatomic, weak) IBOutlet UIBarButtonItem* m_pButtonA;
#property (nonatomic, weak) IBOutlet UIBarButtonItem* m_pButtonB;
(I'd suggest using more descriptive names)
Then, in Interface Builder you can set those properties to be the Reference Outlet for each of those views (drag from the little (+) to the view control in the left sidebar in IB, and select the appropriate property).
You'll then be able to access those items using code along the lines of self.m_pButtonA. You don't need to manually create the reference to them, as the code will automatically generate them.
This is somewhat similar to the approach you would use when connecting GUI events to methods in the view controller (those would use methods labeled with type IBAction), that are triggered automatically when those events are raised. Both IBOutlet and IBAction are just little hints for Interface Builder (IBAction is actually just another name for void).
Sounds like you're coming from an Android background? You should read about outlets, the equivalent to what you're looking for.
See Apple's cheat sheet, Cocoa Application Competencies for iOS, which links to more thorough documentation if you need it.
Ok, i have found the answer here
Get UIButton reference from viewDidLoad
Long story short:
Just give tag to your button and access your button with tag value.
UIButton *btn = (UIButton*)[self.view viewWithTag:1];
[btn setHidden:YES];
I'm building a Core Data document based application. In the app there's a main view (NSTableView) and an inspector view. Both views are separate nib files. The content of the inspector view should depend on the selected row in the main view. I have three controller files:
DocumentWindowController (master controller)
ItemsViewController (main view)
SchedulesViewController (part of the inspector)
Every controller owns a nib file. How is it possible to change the content of the inspector when the user selects another row in the main view's table?
I tried to make it work as follows:
Every controller has it's own NSArrayController, which is set up in the DocumentWindowController. The DocumentWindowController gets its managedObjectContext from [[self document] managedObjectContext]
When a user clicks a row in the ItemsViewController's tableView, an NSNotification is posted, with [NSTableView selectedRow] as a parameter. Then a fetch request is being made.
My intuition says I have to do this with Cocoa bindings.
I searched on Stackoverflow and google but I just can't make it work. If everything is in one nib file is very easy to accomplish. What is the best/most used way to achieve this?
Thanks in advance!
You could follow the same paradigm as the table view and create a data source for your inspector view.
#protocol InspectorDataSource <NSObject>
- (void) inspectorView:(InspectorView*)inspectorView managedObjectSelected:(NSManagedObject*)managedObject;
#end
Your inspector view controller would then have the data source as a property.
#interface InspectorViewController : UIViewController{
#public
id<InspectorDataSource> dataSource;
}
#property (nonatomic, assign) id<InspectorDataSource> dataSource;
Can anyone describe how it is possible to have a TableViewController with its xib file having a at its root and the uitableview as a subview?
I believe the TVController somehow assumes that UITableView will fill the entire area.
Why is that?
I have a really specific need to build a kind of side and bottom tabbed interface with a UITableView as its main area. Pressing tabs changes the predicate for the fetchedresultscontroller etc etc.
The reason I want this is because of the breadth and depth of the data categories in the data model. I rally need to flatten the menu structure a lot...other wise with a table and navbar controller structure, user experience will be akin to sinking to ever deeper depths of a cavern!
My idea is tried and true in other paradigms...in iOS it almost looks like it's Apple's way or the highway. I am OK with APPLE of course no gripe.
But I really would like to create this.
I tried adding a new tableviewcontroller complete with xib and then removing the UITableView in IB and replacing with a UIView and a UITableView as a subview, hooking up (I believe) the delegate to the file's owner.
I created an IV tableView for when I want to reference it and again used IB to hook it up in IB
Try to run it and it whines that...
[UITableViewController loadView] loaded the "TabbedTableController" nib but didn't get a UITableView.'
Really can't seem to get my head around what the issue is here.
There doesn't appear to be anymore I can do to hook the UITableView up!
Any help would be terrific. I'll send you a Christmas card in desperation :^)
Also...why should it be so and how strict is this UITableView fullscreen thing?
Enlighten me if you can. The docs I have read don't want to.
Regards
Keith
A UITableViewController does assume that the root view (i.e. the controller's view property) will be a UITableView, thus the table view fills the screen. When you need a view that combines UITableView with other top level views, you will need to do a little more work but it's not hard:
Your view controller will not subclass UITableView. Instead, do this:
#interface MyViewController : UIViewController
<UITableViewDelegate, UITableViewDataSource>
#property (nonatomic, weak) IBOutlet UITableView* tableView;
In Interface Builder, drop in a UITableView and whatever other controls you need. The table view can be any size and in any location in the view hierarchy. Also in Interface Builder, ctrl-drag from the table view to your VC and set the delegate and dataSource outlets, and ctrl-drag from your VC to the table view to set the tableView outlet.
Your view controller implementation should be the typical table view controller implementation: cellForRowAtIndexPath, etc.
A UITableViewController is more or less just all of the above work packaged up into a single unit for you.
I've created a ChildViewController class, and then a nib that uses that class.
Then I created a BaseView, that includes some buttons, and some text that I'll be changing programmatically.
Then I created two more views (Boy and Girl), that I want to be able to lay behind the baseview so that the background color is different along with some graphics in an ImageView. I've named the views that I created in IB 'Boy' and 'Girl'...
But when I go back to my code where I'm calling ChildViewController, I'm not sure how to access the views I created so I can call insertSubView. Do I need to instantiate them in code? (in ViewDidLoad perhaps?) Does the nib create the instances when it loads?
I'm confused about how to handle multiple views for a single ViewController
edit =================
#Pablo Santa Cruz
Your answer assumes that i have two nibs and two view controllers (one for each view). I want to know if I can use one nib and one controller, and load in UIViews. It seems silly to create another nib and controller, when all want to do is change the background color and some graphics. Can't I programatically load in UIViews into a UIViewController?
Add IBOutlets in your App Controller class in Xcode then link them in IB (ctrl-click or right-click) from the connections tab in the Inspector to the object.
Then you will be able to send method calls to the objects.
The code in Xcode should look like this:
#interface AppController : NSObject
{
IBOutlet Girl girlIvarName1;
IBOutlet Boy boyIvarName2;
}
#end
You can access a UIView programatically by assigning a value to its tag property, which can be set in IB on the first tab of the inspector (Command 1)
The tag value defaults to zero, so if you want to access it specifically, make it non zero and unique. e.g. 100, which I will use in the example code below
Once the tag is set you can access the view using the following code in your UIViewController that was initWithNibName for the NIB containing the tagged view
UIView *aView = [self.view viewWithTag:100];
You can get instances for your IBuilder views with this piece of code:
boyViewController = [[BoyViewController alloc] initWithNibName:#"BoyViewController" bundle:nil];
girlViewController = [[GirlViewController alloc] initWithNibName:#"GirlViewController" bundle:nil];
Assuming your NIB file names are BoyViewController and GirlViewController. With those instances, you can do whatever you need to. I.E., adding them to a parent view (with addSubView message on the parent).