How to Configure NSWindowController, NSViewController, and NSViews - nsview

To be honest, I don't even know where to start. I feel like I've been going around in circles for hours trying different things.
My issues are around how to configure NSWindowControllers, NSViewControllers, and NSViews in IB and then access each in a hierarchy to switch out the NSViewControllers using a single NSWindowController...
I started with this code from the Apple site and am trying to alter it to fit my situation:
https://developer.apple.com/library/mac/samplecode/ViewController/Listings/MyWindowController_m.html#//apple_ref/doc/uid/DTS10004233-MyWindowController_m-DontLinkElementID_12
I have a small app that has 2 views that need to be switched back and forth depending on user interaction. Let's call them drop_view and table_view.
Drop_view is the view that is loaded on launch.
Both of my views are configured in separate nib files:
RADropViewController.xib
RADropViewController.m
RADropViewController.h
RADropView.m
RADropView.h
RADropViewController.xib
RADropViewController.m
RADropViewController.h
RADropView.m
RADropView.h
Each nib has a File's Owner, First Responder, Application, View Icon, and Object.
The File's Owner is set to the controller class, the View Icon is set to the View class, and the Object icon is set to the View Controller class.
Then I have a window controller nib with a window controller.
RAWindowController.xib
RAWindowController.h
RAWindowController.m
The nib has File Owner set to RAWindowController, Window set to NSWindow, and an Object set to RAWindowContoller. I also have a Custom View in the window in this nib because there is an NSView outlet in the Apple example and I read on stackoverflow in all of my research that "there is usually a window controller with a host view and which is used to host the different NSWindowControllers).
The outlets are:
File's Owner
Outlets
myTargetView -> Custom View
Referencing Outlets
delegate -> Window - Window
Window - Window
Outlets
delegate -> File's Owner
Referencing Outlets
window -> Window Controller
Window Controller
Outlets
myTargetView -> Custom View
window -> Window - Window
Here is my RAWindowcontroller.h
#class RADropViewController, RATableViewController, RAWindowView;
#interface RAWindowController : NSWindowController
{
IBOutlet NSView *myTargetView;
}
#property (nonatomic, assign) NSViewController *myCurrentViewController;
#property (nonatomic, strong) RADropViewController *dropViewController;
#property (nonatomic, strong) RATableViewController *tableViewController;
-(void)changeViewController:(NSInteger)whichViewTag;
- (NSViewController *)viewController;
#property (strong) IBOutlet NSView *myTargetView;
#end
and my RAWindowController.m
#import "RAWindowController.h"
#import "RADropViewController.h"
#import "RATableViewController.h"
#interface RAWindowController ()
#end
#implementation RAWindowController
#synthesize myCurrentViewController, myTargetView;
enum // popup tag choices
{
kDropView = 0,
kTableView,
};
NSString *const kDropViewTitle = #"RADropViewController";
NSString *const kTableViewTitle = #"RATableViewController";
- (id)initWithWindow:(NSWindow *)window
{
self = [super initWithWindow:window];
if (self) {
}
return self;
}
-(void)awakeFromNib{
_dropViewController = [[RADropViewController alloc] initWithNibName:kDropViewTitle bundle:nil];
_tableViewController = [[RATableViewController alloc] initWithNibName:kTableViewTitle bundle:nil];
[self changeViewController:kDropView];
[myTargetView addSubview:[self.myCurrentViewController view]];
[self.window center];
[self.window setContentMaxSize:NSMakeSize(409.0, 295.0)];
[self.window setContentMinSize:NSMakeSize(409.0, 295.0)];
}
-(void)windowWillLoad{
[super windowWillLoad];
}
- (void)changeViewController:(NSInteger)whichViewTag
{
if ([self.myCurrentViewController view] != nil)
{
[[self.myCurrentViewController view] removeFromSuperview];
}
switch (whichViewTag)
{
case kDropView:
{
if (self.dropViewController == nil)
{
_dropViewController = [[RADropViewController alloc] initWithNibName:kDropViewTitle bundle:nil];
}
myCurrentViewController = self.dropViewController;
break;
}
case kTableView:
{
if (self.tableViewController == nil)
{
_tableViewController = [[RATableViewController alloc] initWithNibName:kTableViewTitle bundle:nil];
}
myCurrentViewController = self.tableViewController;
break;
}
}
[myTargetView addSubview:[self.myCurrentViewController view]];
}
- (NSViewController *)viewController
{
return self.myCurrentViewController;
}
Here is some sample code from my drop_view that I call when I want to switch to my table_view
-(void)showDifferentViewController: (NSViewController *) controller{
_windowController = [[RAWindowController alloc] initWithWindowNibName:#"RAWindowController"];
[_windowController changeViewController:1];
}
So everything works as I would expect on launch. The drop_view gets loaded and all looks good.
Things start to fall apart when I try to load the table_view.
This line of code:
[myTargetView addSubview:[self.myCurrentViewController view]];
is the issue, at least on the surface. myTargetView is nil. It's not nil on launch but is nil when I try to load a new view. So no new view gets loaded. My drop_view just stays there as nothing happened. myTargetView represents my host view (as I understand it). It's the custom view on my window in my nib file. You can see the outlet to it set up in my RAWindowController.h file and that connection looks OK to me. It seems like the reference is being lost maybe due to the host view being unloaded?
I thought maybe this post had saved me:
How exactly does an NSView, an NSViewController, and MainMenu.xib fit together?
[self.window.contentView addSubview:self.customViewController.view];
[self.customViewController.view setFrame:[self.window.contentView bounds]];
...but I realized my self.window object is nil (I'm assuming because my window object is set to
an NSWindowController in the .nib).
I have a feeling I'm failing to grasp something very basic about windows, controllers, how to configure them, and to access them programmatically.
I appreciate any insight you have.

Okay, so here's what I've picked up in the nine months since I asked the question you linked to. Anytime you're mixing and matching nibs, view controllers, and window controllers, things can get hairy. However, if you think positive thoughts, count to three, and knock on wood, sometimes things will fall into place.
This is how I mentally break down the various controllers:
NSWindowController (MyWindow.xib)
|
|-- NSViewController (MyFirstView.xib)
|
|-- NSView
|
|-- NSTextField
|-- NSButton
|-- NSImageView
|-- Etc.
|
|-- NSViewController (MySecondView.xib)
|
|-- NSView
|
|-- NSTableView
|-- NSButton
|-- Etc.
So in your situation, you'll want to do the following in RADropViewController.xib:
Select the "File's Owner" placeholder object.
Go to the Identity Inspector and make sure that RADropViewController is the class entered in the "Custom Class" field.
Select your top-most view object.
Again in the Identity Inspector, make sure that RADropView is the class entered in the "Custom Class" field.
Right-click and drag from the "File's Owner" object to custom view object and connect the view outlet.
You've now connected the view controller to its view. The same thing can be done in code by doing the following in RADropViewController.m:
- (void)awakeFromNib
{
self.view = [[RADropView alloc] initWithFrame:NSMakeRect(0, 0, 250, 250)];
}
Now repeat these steps in RATableViewController.xib (or RATableViewController.m if you decide to go the code route).
Just to be clear, you either connect the view in Interface Builder or in code, but not both. I used to accidentally override my views because I would set them in IB and then again in the -awakeFromNib method. Looking back, I see that I was basically redoing everything I did in Interface Builder, but until I really grasped the nib unarchiving process, it seemed like a logical thing to do. Anyway … back to the fun.
Now that your view controllers are all set up, hop over to RAWindowController.xib. Again, make sure the "File's Owner" object is pointing to your window controller class and connect the window to the window outlet.
In RAWindowController.h, make your view controllers outlets by adding the IBOutlet macro keyword to your view controller properties:
#property (nonatomic, strong) IBOutlet RADropViewController *dropViewController;
#property (nonatomic, strong) IBOutlet RATableViewController *tableViewController;
Now back in RAWindowController.xib, drag two view controller objects from the Object Browser to the sidebar. In the Identity Inspector, set the class for each to its respective view controller class and in the Attributes Inspector, set the Nib Name for each to the nibs you worked earlier. Now, connect the view controller objects to the properties you just created outlets for.
Finally, to switch the views, add something like this to RAWindowController.m:
- (void)changeViewController:(NSInteger)whichViewTag
{
NSView *contentView = self.window.contentView;
switch (whichViewTag)
{
case kDropView:
{
self.myCurrentViewController = self.dropViewController;
break;
}
case kTableView:
{
self.myCurrentViewController = self.tableViewController;
break;
}
}
if ( contentView.subviews.count > 0 )
{
[contentView replaceSubview:contentView.subviews[0]
with:self.myCurrentViewController.view];
} else {
[contentView addSubview:self.myCurrentViewController.view];
}
}
I'm pretty tired right now, so I may have missed something. I had to post, however, seeing as how I was struggling with this stuff not too long ago. I hope I've helped a little. If I was unclear about anything, please let me know, and I'll try to explain things better. I promise you this much, though: it will all make sense eventually. One day it'll just "click," and you'll laugh at this old Stack Overflow question. Anyway, good luck, and let me know if I can shed more light on anything you're unsure of. Take it easy.

Related

UIView setHidden not working

I am writing an app for the iphone and am attempting to create a view controller with two different views. So I have a subview created on top of the initial view in storyboard. I have created an outlet in the .h for the new view. I want to display the resultsView after the button is pressed so I have the view set to hidden in properties.
#interface ViewController : UIViewController
{
UIView *resultsView;
}
#property (nonatomic, retain) IBOutlet UIView *resultsView;
- (IBAction)buttonTapped:(id)sender;
In my .m I have the following code
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize resultsView;
- (IBAction)scanButtonTapped:(id)sender
{
[resultsView setHidden = NO];
}
I have also tried
resultsView.hidden = NO;
Neither of these worked and I tried NSLog to retrieve the BOOL of resultsView.hidden and it was still YES.
If resultsView is NULL or nil, then you did not assign it properly in interface builder, or in code. Make sure you drag the outlet connection in your storyboard/xib file, or assign it in code somewhere like viewWillAppear
If the function isn't getting called, then the action is not linked up to the button in interface builder. To make sure it is connected properly, you can ctrl+click (or right click) and drag from the button to the view controller, and select scanButtonTapped from the "Sent actions" list that appears
Another option - check that you run your [? setHidden:] code in UIThread
The most likely explanation is that resultsView id nil when you try and set the hidden property.
Please, review your code to initialize resultsView and if you need more help, post some relevant part of it.
In the case where you are designing a #IBDesignable UIView and you are using swift, somehow view.hidden = isHidden just does not work.
The work around is the following.
view.setValue(isHidden, forKey: "hidden")
I hope this helps someone out there.

how to access previous view elements in UINavigationController

I have a UINavigationController in which I am loading different view controllers. I want to know how can i access the elements (like labels etc) of my previous view.
Here is an eg.
View A
myLabel.text = #"first view";
(User moves to view B)
View B
(user entered a message, that i need to display in View A)
something like ViewA.myLabel.text = #"user entered message"
I tried many things but was not able to find anything very useful. Please help..
I am using Xcode 4 without ARC and without storyboard.
Thanks
Sam
Edited:
I want to update the property declared in viewController of View A and not the labels directly. My labels get updated using that property. Like while pushing the viewController we can pass the values as below.
ViewA *myView = [[ViewA alloc] init];
myView.title = #"View B" ;
myView.tableView.tag = 3;
myView.myTextView.text = #"Some Text";
[self.navigationController pushViewController:myView animated:YES];
[myView release];
Is there any way to pass these values to properties of ViewController of ViewA while popping ViewB and returning back to ViewA ?
The actual scenario is as follows: the user gets and option to write a message in textView or he can use the predefined templates. If he clicks on the templates button he is taken to a list of predefined templates where he can select any of the predefined message. Now I want that when the user click on any of the predefined message the view containing the list of predefined message gets popped of and the message he selected gets automatically populated in the textView of main view. what is the best approach to achieve this ?
TIA
Sam
You should set your AViewController as the delegate of your BViewController so you can message it back after a particular event. Using a delegate will also allow better decoupling of your ViewControllers.
In your BViewController, define a protocol like this :
BViewController.h :
#protocol BViewControllerDelegate <NSObject>
- (void)viewB:(UIViewController *)didEnterMessage:(NSString *)message;
#end
and add a delegate property :
#property (nonatomic, weak) id <BViewControllerDelegate> delegate;
When the user enter the message in your BViewController and hit the button that pops the BViewController to show to AViewController do this :
- (IBAction)messageEntered {
if ([self.delegate respondsToSelector:#selector(viewB:didEnterMessage:)]) {
[self.delegate viewB:self didEnterMessage:self.yourTextField.text];
}
}
Your AViewController should implement the BViewControllerDelegate protocol like this :
AViewController.h :
#interface AViewController <BViewControllerDelegate>
When your AViewController creates the BViewController, it should set itself as its delegate before presenting it. Might look like this :
BViewController *bvc = [[BViewController alloc] init…];
bvc.delegate = self;
And finally, your AViewController should implement the viewB:didEnterMessage: method :
- (void)viewB:(UIViewController *)didEnterMessage:(NSString *)message {
self.myLabel.text = message;
}
That's the cleanest way to do that, IMHO.
You can get the navigation controller's viewControllers property and use it, perhaps like this:
UILabel *label = ((SomeViewController *)[self.navigationController.viewControllers objectAtIndex:1]).myLabel;
However, that is not reliable. Since the “previous” view is off the screen, the system can unload it to free up memory. Then label will be nil.
You could force that other view controller to reload its view (if it has been unloaded) by accessing the view controller's view property.
But really this smells like bad design. You should almost never try to access the views of a view controller when that view controller's view is not on screen. Remember how the system can unload a view controller's view if the view is off-screen? If some UILabel under that view contained the only copy of important data, that data is now gone!
Any important data needs to be stored somewhere other than a view - perhaps in a property of the view controller, or in a model object. You should ask the view controller for the data, or for the model object that contains the data. A view controller's view objects should almost always be considered a private implementation detail of the view controller, not exposed to other classes.
EDIT
Your question is puzzling because you talk about popping ViewB and returning to ViewA, but your code only creates and pushes a ViewA. ViewB is not mentioned in the code.
I will assume that your ViewA creates and pushes a ViewB. So you should give ViewB a property of type ViewA, like this:
#class ViewA; // forward declaration to avoid circular imports
#interface ViewB
#property (weak, nonatomic) ViewA *aView;
Then, when your ViewA creates a ViewB instance, you set the aView property:
#implementation ViewA
- (void)pushViewB {
ViewB *bView = [[ViewB alloc] init];
bView.aView = self;
[self.navigationController pushViewController:bView animated:YES];
}
Now your ViewB has access to the ViewA that created it, and can set the properties of that ViewA.
If you want to write a good code you should follow the Model-View-Controller pattern. Here's rather good tutrial http://www.cocoalab.com/?q=node/24 In a couple of words it means that you should not store data in View (and also a view should not act as controller). I suggest you to write a custom class that will do this management(store data and pass it from one view to another).
If it's just a test app then you can use viewControllers property of UINavigationController to access the controllers which are in navigation stack or just create a variable to store this data for example, in View B
- (void)textFieldDidEndEditing:(UITextField *)textField {
stringToDisplayInFirstController = textField.text;
NSArray * arrayOfControllers = self.navigationController.viewControllers;
UIViewController * viewControllerA = [arrayOfControllers objectAtIndex:[arrayOfControllers count]-1];
viewControllerA.label.text = stringToDisplayInFirstController;
}

UIPopover and UITableView data exchange

I have a UITableView in a UINavigationController. On the navigation bar I have a button called add. When this button is pressed it presents a UIPopoverController, where user can input data to be added as a new row/cell in the UITableView. My issue is how can I add a new cell to the UITableView from the UIPopover? Do I pass in the array data to the UIPopOver root controller?
There are two solutions to this that I'm aware of. One would be to send a notification from the popover to the root controller and apply the necessary code to update the tableView in the handleNotification method.
The other, one that I personally use, is to set up a delegate protocol for the popover. You'll have to set it up something like this:
#protocol PopoverDelegate
- (void)addNewCell; // you can add any information you need to pass onto this if necessary such as addNewCellWithName:(NSString *)name, etc.
#end
#interface MyPopoverViewController..... {
id <PopoverDelegate> delegate;
// the rest of your interface code;
}
#property (nonatomic, retain) id delegate;
// any other methods or properties;
#end
Then in your root view controller header file, you need to add the delegate
#interface RootViewController .... <PopoverDelegate> {
Then in your root view controller implementation file, assign the popover delegate when you instantiate it. For example:
MyPopoverViewController *vc = [[MyViewController alloc] init];
vc.delegate = self; // this is where you set your protocol delegate
myPopover = [[UIPopoverController alloc] initWithContentViewController:vc];
myPopover.delegate = self;
[vc release];
Finally, you'll add your protocol method somewhere in the code
- (void)addNewCell {
// do what you want with the tableView from here
}
Sorry that's a bit long. I just wanted to make sure I was thorough. Hope it helps

Initialization for ViewController under NavController in TabBarController

I have the relatively common setup of a TabBarController whose tabs contain NavigationControllers which have TableViewControllers as their roots. I'm trying to perform some logic on initialization of one of these TableViewControllers but can't seem to find what init function gets called.
My goal is to add a listener in the TableViewController (that I have subclassed) which can respond to events by updating the navigationController.tabBarItem.badgeVluew property.
I've tried putting code into initWithStyle: as well as init but neither of them end up getting called. I've also tried putting it in viewDidLoad, but that only gets called once the controller actually appears (I need to have it happen as soon as the controller is loaded / as soon as the tab bar item shows up).
Does anyone know where I would put this code for it to happen on initialization of the controller?
Also, this is all set up through interface builder / NIBs. I'm not adding the nav controller or tableviewcontroller manually, which is why it's not clear what init function I need to override.
If you select one of your UITabBarItems in IB, you will see 'View loaded from "YourView"'. Click into this "gray" View. In the Inspector window you will see in the Attributes Tab (the tab on the left) the title and the NIB name which will be loaded (lets call it "YourNibName").
Now select the right tab of the inspector (Identity) and change the Classname (Combo next to Class) to your "YourViewController" class, which you must create in xcode. Don't use the standard ViewController, which is already selected. The InterfaceBuilder loads your nib and attaches it to your ViewController.
Open YourNibName and change FilesOwner's Class (Inspector, right Tab) to "YourViewController", too.
Your TabBar's NIB contains a FilesOwner, too. Create a ViewController for this FilesOwner and set its Class to this Controller (i.e. TabBarController)
In "TabBarController" you can find out which Tab was selected by using this code:
- (void)tabBarController:(UITabBarController *)tabBarController didSelectViewController:(UIViewController *)viewController{
if ([viewController.nibName isEqualToString:#"NIBName1"]){
// Do something here, if you like. (i.e. Save the state in a string or int)
}
if ([viewController.nibName isEqualToString:#"NIBNAme2"]){
// Do something here, if you like. (i.e. Save the state in a string or int)
}
...
}
Here you can do something "global" or preinitialize something. This is ONE thing you can do.
INIT OF YOUR VIEWS:
If you select a Tab and the view (which is handled by YourViewController) will be shown for the first time, "viewDidLoad" will be called in "YourViewController"
- (void)viewDidLoad {
// Here you can add views programatically
[self.view addSubview:myNavigationController.view];
[self.view bringSubviewToFront:myNavigationController.view];
// And if you like, do some INIT here
[super viewDidLoad];
}
I hope this is what your question was about.
Now something about the badge. It's a hack, but works fine for me.
Header file:
Add an outlet to your controller, which is representing your TabBarController:
#interface yourController : UIViewController <UITabBarControllerDelegate> {
UITabBarController *tabBarController;
}
#property (nonatomic, retain) IBOutlet UITabBarController *tabBarController;
#end
Connect this outlet in IB with your TabBar.
Implementation:
In your TabBarControllerClass you can overwrite 'initWithNibName':
#synthesize tabBarController;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
// Do some init here
// select your desired item (it will be loaded)
// then you can assign the badge
tabBarController.selectedIndex = 1;
tabBarController.selectedViewController.tabBarItem.badgeValue = #"222";
// and select the item you will start with
tabBarController.selectedIndex = 0;
// if you like you can add a notification, which you can activate from anywhere else
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(itemBadgeChanged:)
name:#"itemBadgeChangedNotification"
object:nil];
}
return self;
}
if you don't use nib, use '- (void)loadView { ... }' instead.
You are using a subclass of the TabBar controller, maybe you can use 'self.selectedIndex = 1;' instead of 'tabBarController.selectedIndex = 1;', and so on. Just try this out
Hope this helps!

How to access data from one view to another view?

I have an UITabBarController with two tabs:
UINavigationController
OptionsViewController : UIViewController
How can I reach data (ie. UILabel.text) set in OptionsViewController, in a new added modal View which has been invoked from UINavigationController?
Edit1:
Scenario: After launching app I select the second tab bar called "Options" where I fill up a textField. The label is set to value from textField. Next I select first tab bar called "Main" where I have a button. I click the button and new modal View appears. In this new modal View I'd like to show the value from textField
I love MVC, but I'm not an absolute purist to the point of hurting yourself to accomplish a fairly trivial task, so the answers you've gotten here are good and useful. However, by creating an ivar to refer back to a specific type such as a label or other view controller, you are coupling things together that aren't necessary to couple. What you could do instead is make your first tab view controller a delegate of your second tab view controller. So do something like this in your app delegate.
OptionsViewController *optionsViewController = // ... get this from the tab view
FirsTabViewController *firstTabViewController = // ... same here
[optionsViewController setDelegate:firsTabViewController];
Which means that you need an ivar in your OptionsViewController:
#property (assign) id delegate;
Then, when whatever event you want to trigger the change occurs in your options view controller, see if the delegate can respond to a selector you've named. For example:
- (void)someEventHappenedLikeTyping:(id)sender;
{
if ([delegate respondsToSelector:#selector(setOptionsString:)]
[delegate performSelector:#selector(setOptionsString:) withObject:[label text]];
}
Notice you never specified any specific object types. You just check to see if the delegate (which was declared as id) can respond to that selector. If it can, it does what it's told and just is silent otherwise.
For this to work, you need an ivar for the optionsString in your FirstTabViewController and so it would be declared in the header as:
#property (copy) NSString *optionsString;
and then #synthesize it in the .m. This causes -setOptionsString to become a valid selector that will get called in the -someEventHappenedLikeTyping method.
Anyhow, now, if you ever need to to change which view controller references which, you don't have to go into the header and change the type of ivar referenced. You simply need to implement the selector (this is known as an informal protocol, by the way) in the view controller that is a delegate of your options view controller.
Just some food for thought there. Hope that helps. There is further de-coupling that could be done in the code I've added, but again it may be overkill for such a simple task. Let me know if you need clarification or want to understand what I mean by further decoupling.
Best regards,
p.s. Sometimes needing to share data between two tab bar view controllers, means you have a design flaw. If you are wanting to store preferences from your options view, you should just call
[[NSUserDefaults standardUserDefaults] setObject:[label text] forKey:#"option1"];
[[NSUserDefaults standardUserDefaults] synchronize];
Then you can pull from the NSUserDefaults back in your main tab with;
NSString *option1 = [[NSUserDefaults standardUserDefaults] objectForKey:#"option1"];
// Do something with option1
In your OptionsViewController, create a property:
#property (nonatomic, retain) UILabel *mylabel;
then after creating your OptionsViewController, but before displaying it, set the mylabel property. (Or perhaps you just want the text, so you can use an NSString* property.)
Edit:
So you probably want to do something like this:
OptionsViewController *vc = [[OptionsViewController alloc] init];
vc.mylabel = mySomethingLabel;
[self presentModalViewController:vc animated:YES];
So after creating the object, you set the property, and then you display the view controller.
I usually set IBOutlets in each of my viewcontrollers which point to the other controller.
So if I had view controllers A and B. A has an IBOutlet to B and B to A. Then whenever I want to access anything in B from A i just use a dot operator on B.
In your example UINavigationController would #include "OptionsViewController.h" and have an ivar IBOutlet OptionsViewController * ovc (which is set in IB) and then any instance variable from your options view controller can be referenced as ovc.UILabel.text from the navigation controller. This process can be reversed to access values from your navigation controller in your options view controller.
Example Navigation Controller (.h):
#include "OptionsViewController.h"
#interface UINavigationController // (whatever the name of this class is)
{
OptionsViewController * ovc;
}
#property (nonatomic, retain) IBOutlet OptionsViewController * ovc;
#end
Example OptionsViewController.h:
#interface OptionsViewController
{
UILabel * label;
}
#property (nonatomic, retain) IBOutlet UILabel * label;
#end
Then from UINavigationController (.m) you can just write ovc.label.text to access the text.
I have an easy way to access data between views. Let's try. You have two views named view1 and view2, you can define a View *vc1 property in view2.h, set the vc1 point to view1, when pop the view2, like this:
view1.m
//here pop out view1 code
View2 *view2 = [[View2 alloc] initWithNibName:#"View2" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:view2 animated:YES];
view2.vc1 = self; //transfer view1 instance to view2,use vc1 you may handle view1 in view2 directly
[view2 release];
view2.h
#import "view1.h"
#property (nonatomic, retain) IBOutlet View1 *vc1; //here you could name it as view1 as well :)
view2.m
vc1.lblTable.text = #"ok"; //you'll see "ok" in view1
[self.navigationController popViewControllerAnimated:YES]; //navigate to view1
//dont forget release vc1