Connect one view to another in seperate NIBs using Interface Builder - iphone

I have a custom UIWindow class that has an IBOutlet
#interface MyWindow
IBOutlet UIView * someView;
id <MyWindowDelegate> delegate;
// to inform a controller something happened to view
#end
#interface MyControllerThatContainsSomeView
IBOutlet UIWebView * theConcreteView;
#end
I have changed my Window in MainWindow.xib to MyWindow. Is there a way, through interface builder, in which I can reference someView from MyControllerThatContainsSomeView.xib
so, MainWindow.MyWindow.someView -> MyControllerThatContainsSomeView.theConcreteView

You can refer to it in a binding path but that's about it. Usually when you find that you need to refer from one view to another, it's time to rethink your design. Views should refer instead to model objects which provide data to the views.

Related

Cannot connect Segmented Control to its IBOutlet

I have created a segmented control in the interface builder.
In my ViewController.h:
#interface ViewController : UIViewController <MKMapViewDelegate>
#property IBOutlet UISegmentedControl *Segment;
- (IBAction)switchMode:(id)sender;
#end
What I could do was to connect the Segmented Control with the IBAction but I cannot connect it with the IBOutlet!
Add a segmented control to the nib/Storyboard
Add the following code into the .h
#property(nonatomic,retain) IBOutlet UISegmentedControl *Segment;
In your storyboard or xib make sure that the files owner has the same classname as that of the class in which you written the outlet
Right click on the segmantControl and a window with outlets and actions appears
click and drag on the referencing outlet and drop it on the filesowner a new pop appears which includes your outlet written in code select it .
Connection established
you have forgotten to write parameters of property, correct it like below code
#property(nonatomic,retain) IBOutlet UISegmentedControl *Segment;
after this synthesize this property in .m file like this
#Synthesize Segment;
It appears that with some xCode update you can no longer connect certain outlets to your .h. You should be fine connecting it in your .m though:
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UISegmentedControl *mySegmentedController;
#end
I will read some docs and see when this changed. Also there really is no reason to connect this property to your public interface (hence why it is no longer allowed). Only the View Controller of that class should have control over it.

Subclass UIViewController or create a custom NSObject when the view is not fullscreen

I need to create a class controller to manage the behavior of a custom view I created.
The standard approach is to subclass UIViewController, but in my case I instead decided to
subclass the NSObject essentially for three reasons:
my view needs to be added as small subview of the main view controller (it will not be displayed using something like presentModalViewController or pushViewController...) and it does not require any kind of toolbar or navigation control inside of it
Most probably my controller will not need to be notified for device orientation because its view will be always used in portrait format, so I'm not interested to receive the usual rotation messages willRotateToInterfaceOrientation etc...
I need to keep this class as lightweight as possible minimizing memory consumption. Not subclassing UIViewController have the advantage to obtain a lighter class without a bunch of methods that I will never need to use
The interface of my controller is pretty simple, example:
#interface MyScrollTabBarController : NSObject <MyTabBarViewDelegate> { }
/**
* The view is created internally by the controller and the client class
* can access to it in readonly mode
*/
#property (nonatomic, readonly) UIView *view;
/**
* A Property to change the view appearance
*/
#property (nonatomic, assign) MyScrollTabBarViewState viewState;
/**
* Others properties used to construct the view's subviews
*/
#property (nonatomic, retain) Location *rootLocation;
#property (nonatomic, readonly, retain) Place *place;
/**
* Designated initializer
*/
- (id)initWithPlace:(Place *)aPlace;
- (void)setRootLocation:(Location *)location animated:(BOOL)animated;
#end
To display its internal view from the parent view controller, I will use something like this:
tabBarController = [[MyScrollTabBarController alloc] initWithPlace:aPlace];
tabBarController.viewState = MyScrollTabBarViewStateXX;
tabBarController.view.frame = CGRectMake(...);
[self.view addSubview:tabBarController.view];
I'd like to know what do you think about my choice, if you think that there could be drawbacks in it and what do you usually do when you need to write a controller for a view which is not fullscreen like mine.
Thanks
Yes, this is the correct approach.
UIViewControllers are specifically for controlling full-screen views, not for sub-screens. In iOS5 there is a mechanism for composing sub-screen viewcontrollers in this way, but that's not available in iOS4 without lots of hackery.
In cases where the view and controller are inherently coupled, you could also consider making a custom view subclass that is its own controller, so for example you could have a self-contained table view subclass that managed its own data and could just be dropped into a page.
I think this is an acceptable solution.
Another solution would be creating a "fat" view that does its controlling itself (like, for instance, MKMapView, UITextView etc.). This might make things a little more manageable, and if the view is very specialized, and its controller is intended to only work with this one class of view, you don't really lose any reusability (because there isn't much).
what do you usually do when you need to write a controller for a view which is not fullscreen like mine
It is not important that your view is not displayed full screen. It is possible (and usual) to have views consisting of subviews which each have their own controller.
I need to keep this class as lightweight as possible minimizing memory consumption. Not subclassing UIViewController have the advantage to obtain a lighter class without a bunch of methods that I will never need to use
Subclassing UIViewController does not consume an unreasonable amount of memory, so this should not be part of the consideration.
[...] if you think that there could be drawbacks in it [...]
With your solution you loose flexibility. It is likely that you will reuse your solution in a context where you need to respond to UILifecyle-Messages or use other UIViewController features.
If your views shall be lightweight you could consider using a UIView subclass and use a delegate for the logic behind your view.
Hi You are subclassing NSObject and declaring a UIView inside it
#interface MyScrollTabBarController : NSObject <MyTabBarViewDelegate> { }
#property (nonatomic, readonly) UIView *view;
I Suggest you should subclass UIView, so you will not have to declare an additional view object.
so instead of self.view you can simply refer as self
tabBarController = [[MyScrollTabBarController alloc] initWithPlace:aPlace];
tabBarController.viewState = MyScrollTabBarViewStateXX;
tabBarController.frame = CGRectMake(...);
[self.view addSubview:tabBarController];

steps to add tabbarcontroller to AppDelegate using Interface Builder in XCode 4.2 Empty Application template

while I'm stuck at this question I cannot find the right steps to add a UITabBarController to the AppDelegate (not programatically) but by using interface builder for the "Empty Application" template, I tried to add a new empty xib file, then dropped uitabbarcontroller into it, but there is no way to link it (from IB) to AppDelegate !! i.e. when I move the blue line from tabbarcontroller object (in document outline) to File's Owner, interface builder shows only the "Delegate" option in the shown list so there is no IBOutlet option in there.
so, what are the exact steps for adding a tabbarcontroller and connect it to appDelegate using the interface builder way (for the Empty Application template, using XCode 4.2 and IOS 5 SDK) ?
step1: create new Empty Application template project.
... waiting for the next steps...
thanks so much in advance.
Step 1: create new Empty Application template project.
Step 2: add
#property (nonatomic, strong) IBOutlet UITabBarController *tabBarController;
#property (nonatomic, strong) IBOutlet UIWindow *window;
in your app delegate. (dont forget to synthesize these)
Step 3: change this line in your app delegate:
#interface AppDelegate : NSObject <UIApplicationDelegate, UITabBarControllerDelegate>
Step 4: modify this method
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[self.window addSubview:[self.tabBarController view]];
[self.window makeKeyAndVisible];
return YES;
}
Step 5: create a new empty xib. Drag a tab bar controller on to it as well as an empty object.
Set the empty object's class to AppDelegate. Set Files Owner to UIApplication.
Step 6: drag the 'delegate' property from your files owner on to your appdelegate class and drag the tab bar outlet from you appdelegate class to your tabbarcontroller
Step 7: Add a window and drag the 'window' connection from your appdelegate to the window.
Step 8: Dont forget to go into the project settings and set the main-base nib file to the new xib you created.
Thats it. Hope I didn't miss anything.
I don't understand what is the need to add a UITabBarController through the main window. With Xcode 4.2, Apple has made some changes in the default templates. It does not provide a MainWindow.xib in the Empty Application. That is why, if you open up the AppDelegate.h, you will see:
#property (strong, nonatomic) UIWindow *window;
It does not have an IBOutlet for the window as we used to see in previous Xcode versions.
What you want to achieve is a UITabBarController with Core Data support. You could add the tabBarController programatically, and still add CoreData support.
Here's what I had to do.
From your storyboard's Objects list (Controllers & Objects) in the Utilities panel, drag over a generic "Object" (yellow cube) to your Tab Bar Controller Scene page (I place the object under the "Exit" object).
Set the class of the object to your appDelegate. Now you should be able to link your Tab Bar Controller's delegate to your appDelegate object. You can also link the appDelegate to the Tab Bar Controller if you've created a property such as
#property (weak, nonatomic, readwrite) IBOutlet UITabBarController *tabs

iPhone Subclassing view controller and IBOutlet UITableView

I have the following problem. I've created a ViewController pretty much like the above
#interface MyViewController : UIViewController {
IBOutlet UITableView *myTableView;
}
#property (nonatomic, retain) IBOutlet UITableView *myTableView;
I've linked myTableView on the Interface Builder to the matching nib's UITableView. and I've subclassed MyViewController to create YourViewController as so:
#interface YourViewController : MyViewController {
}
And then I load from a TabBarController the YourViewController on a tab item. Although I can see that MyViewController is indeed invoked at the end, no table view is displayed on the emulator.
I've tried debugging the MyViewController and it appears the the IBOutlet is nil.
Why is that?
I have encountered major issues with inheritance and IBOutlets and IBAction. I advise you to avoid that, and create shared stuff in another way.
I was hit hard by bugs when getting memory warnings for instance. Outlets and actions didn't get reconnected properly when they were defined in base class vs derived class.
Probably MyViewController's nib file is not loaded at all. Are you using for YourViewController a specific nib file? and in which way are you creating YourViewController.
Can you also try to define an "awakeFromNib" method in YourViewController and then from it call [super awakeFromNib] ?
However to understand your issue you must clearly explain how you load objects and if and where you use Nibs?
If you add it dynamically using code then only it will work. Not using Nib.
the UITableView (ie. your myTableView) needs delegates for data source and and its control.
And your controller needs a link to the Table view in the xib.
declare table delegate protocols in the interface section of your controller.
using IB, link the TableView in your xib to owners file:delegates.
using IB, link the file owner myTableView to the tableView in the xib.
I hope it will help.
Assuming that you have your whole navigation stack in MainWindow.xib
Open MainWindow.xib
Select YourViewController (Or whatever your controller that is subclassing UITableViewController is called)
Select Attributes Inspector
Ensure that the 'NIB Name' property has your correct YourViewController (Or whatever the name) selected
I had this exact same issue, this solved it for me.

iPhone Views at Runtime?

I am new to the iPhone SDK and am trying to create 3 views and switch between them. Data will come from a server and I will basically be showing 1 view and caching the other two. So far I am just trying to create a view and display it at run-time. My code is listed below. It shows only a blank screen and I think I am missing a key concept. Any Help?
#import <UIKit/UIKit.h>
#import "ImageViewController.h"
#interface Test5ViewController : UIViewController
{
IBOutlet UIView *rootView;
ImageViewController *curImage;
ImageViewController *nextImage;
ImageViewController *prevImage;
}
#property(nonatomic,retain) IBOutlet UIView *rootView;
#property(nonatomic,retain) ImageViewController *curImage;
#property(nonatomic,retain) ImageViewController *nextImage;
#property(nonatomic,retain) ImageViewController *prevImage;
#end
and
- (void)loadView
{
self.curImage = [[ImageViewController alloc]initWithNibName:#"ImageView" bundle:[NSBundle mainBundle]];
UIImage *pic = [UIImage imageNamed:#"baby-gorilla.jpg"];
[self.curImage assignImage:pic];
self.rootView = self.curImage.view;
}
and
#import <UIKit/UIKit.h>
#interface ImageViewController : UIViewController
{
IBOutlet UIImageView *image;
}
-(void)assignImage:(UIImage *)screenShotToSet;
#property(nonatomic,retain) IBOutlet UIImageView *image;
#end
Welcome to the iPhone SDK!
In general, there are two ways to get any view displayed.
First, and most commonly, you use a NIB file created by the Interface Builder. This is usually the easiest way to get started and I would recommend it for what you're trying to do here. It's too lengthy to describe all the steps you need to do for what you have here, but basically start in xcode by creating a new file and selecting "user interfaces" and choose View XIB. This will create a basic NIB file (they're called NIBs rather than XIBs for historical reasons). The first step in interface builder is to change the class name of the "File's Owner" to your UIViewController subclass (Test5ViewController). You can then drop anything that IB will allow into the view window or even replace the pre-supplied view object with one of your own. And here's the trick: make sure the view outlet (supplied by the UIViewController superclass) is connected to a view. Once this is done, this view will be automatically loaded when your NIB is loaded. You can then just put your UIViewController subclass (Test5ViewController) in your MainWindow.xib NIB file to get it automatically loaded, and you're in business.
Now, the way you're doing it here is the second way. Some people like to code this way all the time and not user interface builder. And while it's definitely necessary sometimes and always more flexible, it makes you understand what is happening a bit better. There may be other things, but the main thing you're missing is that in your code above, you have nothing that is adding your view into the view hierarchy. You need to check first that you have an UIApplicationDelegate subclass and it needs to load your "root" UIViewController class. All initial project creation types in xcode do this (except Window-based application). It is code like:
[window addSubview:rootController.view];
Once this is done, if your view controller wasn't loaded by the NIB (described briefly above), your loadView method will be called, expecting you to build your own view hierarchy. Above, you created the view(s), but failed to put them in a hierarchy. You need something like:
[self.view addSubview:curImage.view];
No view will be rendered until added to the view hierarchy. Make sure to look up the UIView class in the documentation and understand the variety of ways to add and remove views to the view hierarchy.
A couple things I should warn you about:
* your code above is leaking. You need to review how objective-C properties work. There's lots on this site about it. More than I have time to write about here.
* don't create a rootView property in the case you have here. There already is one in the superclass (UIViewController). It's just 'view'. Use that for saving your root view.
I hope this helps you get started. It can be bewildering at first, but you'll soon get it going! I recommend building and rewriting and rebuilding a lot of sample code before you do your "real" application. The SDK has many great samples.