IBOutlet will not instantiate - properties

Alright,
I have a weird one here. I have created a VERY simple UIViewController that has 1 big UITextView on it.
In my .h file I declare a property like this:
#property (nonatomic, strong) IBOutlet UITextView *displayTextView;
and then synthesize it like this:
#synthesize displayTextView;
Then I go to load it using:
ExampleViewController *eVC = [[ExampleViewController alloc] initWithNibName:#"ExampleView" bundle:nil];
[eVC.displayTextView setText:#"This is the string I want to show!!!"];
[self.navigationController pushViewController:eVC animated:YES];
For some stupid reason the text view is never instantiated and when I use breakpoints to go through it is NULL. I am using Xcode 4 with ARC, can ANYONE please explain why this extremely simple code that would have worked in Xcode 3 refuses to in Xcode 4?
Before you ask, YES I have triple checked my IB connection from the outlet to the text view.
GRRR, this is so frustrating! Please help!

Related

How can i make a UITabbar like this?

I would like to create a UITabbar like below but i don't know what is the logic to do that.
Here is the large answer:
First of all, you will need to create a UIView subclass to get a view that looks like the bar that you want. It can be composed by a background UIImageView and three buttons.
Then, the best thing would be to create a subclass of the UITabBarController and in its viewDidLoad or at any point where the flow will go through just once, you instantiate one view of type specified at first point. You should place the frame of this view in order to hide the original tabbar of the controller.
This would be the custom bar header file:
#interface CustomBar : UIView
{
}
#property (nonatomic, retain) UIImageView *backgroundView;
#property (nonatomic, retain) NSArray *buttons;
#end
You can easily complete the implementation. You can try to look for how to instantiate it with a nib file to make it easier to design it. In order to test, you can first just set the background color to green or something visible.
Then, this would be the subclass of the UITabBarController class:
#interface CustomTabBarController : UITabBarController
#property (nonatomic, retain) CustomBar *customBar;
#end
#implementation CustomTabBarController
- (void)viewDidLoad
{
[super viewDidLoad];
self.customBar = [[[CustomBar alloc] initWithFrame:[self.tabBar frame]] autorelease];
[self.view addSubview:self.customBar];
}
#end
Please, remember to implement the dealloc if you are not using ARC.
The thing I am not sorting out here is how to create the communication between the buttons from the custombar and the tabbarcontroller. This should be solved by delegates. If you need help with that, I will complete that too.
Good luck!

Trouble creating UINavigationController to push just one VC

I'm having trouble on such as trivial but fundamental concept in XCode.
I just want to be able to create an app from scratch and be presented with my root view controller and push and pop some VC for practice.
Believe me, I looked at tons of posts and none of them seem to do the trick.
So my steps were, I created a new xcode project, and created an empty application. I figure hell, lets learn here, instead of creating a single view app.
I went to new file then added a obj-c class and created the XIB with it. I called it RootViewController.
So here's my app delegate h file.
#import <UIKit/UIKit.h>
#import "RootViewController.h"
UINavigationController *navVC;
#interface VCTestAppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (retain, nonatomic) UINavigationController *navVC;
#property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
#property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
#property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;
#end
Notice I'm creating my own UINavigationController called, navVC.
Then here's the beginning and relevant section of my appledelegate m file...
#import "VCTestAppDelegate.h"
#implementation VCTestAppDelegate
#synthesize managedObjectContext = _managedObjectContext;
#synthesize managedObjectModel = _managedObjectModel;
#synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
#synthesize navVC;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
UIViewController *VC1 = [[UIViewController alloc]initWithNibName:#"RootViewController" bundle:nil];
navVC = [[UINavigationController alloc]initWithRootViewController:VC1];
[[self window] setRootViewController:navVC];
[self.window makeKeyAndVisible];
return YES;
}
And I just created a label on that root VC to verify its showing. Well, nope. No syntax errors and no crashing, the simulator just shows a black screen. What on earth and I doing? Then once I figure this out, I want practice to push and pop view controllers.
I can't believe I can't figure this out. I recently published my own app, but using storyboards. I want to move on to another project now but I want more solid fundamentals without using storyboards. I don't want to limit users of just iOS 5 and higher.
And by the way, I even tried by starting a single view application and adding a VC and when I click my button, it "should"; push the 2nd VC. I know the syntax for that, but when I tested the other app I was messing with, it would go into the IBAction block for the button but it would not push that VC....
I tried [self navigationController] pushview... I even tried just [navVC pushview...] nothing works.
I don't understand what I'm missing and how people made apps manually (programmatically before storyboards).
Any help would be super appreciated. Thanks!
You need to create the window. If you look at the default code for an Empty Application, it will have this line:
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
If you're creating a simple application for practice, what are you doing with the core data stuff?
The only I can think of is that the UIWindow *window that your app needs is currently nil.
You said you made a XIB: try associating the "window" and "NavigationController" outlets to the correct controllers in the XIB.
Control+click from the controller to the window view. It should give you an option to click on "window". This should associate the window with the controller. Try doing the same with the UINavigationController's controller and view.

Setting a property from another property's setter from segue Objective-C

For reference, I'm trying to learn Objective-C through the Stanford iTunes-U course. I wanted to update one property from the setter of another (they are inherently connected. Also, is that bad style?). The property I am trying to update is a UILabel, but it doesn't work like I thought.
This code is in one of my view controllers:
-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
[segue.destinationViewController setProgram:self.brain.program];
}
Naturally, this code calls the setter for the Program property of the incoming viewController. Here's that setter code:
-(void)setProgram:(id)program {
_program = program;
self.title = [CalculatorBrain descriptionOfProgram:program];
[self.graphview setNeedsDisplay];
self.testLabel.text = #"Trying to update your text!";
}
and the header file:
#import <UIKit/UIKit.h>
#interface GraphViewController : UIViewController
#property (nonatomic, strong) id program;
#property (weak, nonatomic) IBOutlet UILabel *testLabel;
#end
Now, when this code is run, as the segue happens, the new view DOES have its title changed (the self.title line works). However, the UILabel DOES NOT get updated. Furthermore, if I call the setter again say in viewDidLoad, it does change the UILabel. Is this because of self being updated? What's going on here?
In one of the lectures, the professor explains that outlets aren't set yet in prepareForSegue. This means testLabel is nil, and you're sending a message to nil (which is allowed and doesn't crash your app). To solve your problem, set the textLabel's text in viewDidLoad or viewWillAppear.
I believe this is "fixed" in iOS 6, but it won't be backwards compatible, so if you want to support iOS 5 still, you'll have to use viewDidLoad or viewWillAppear to update outlets (which I think is better to do anyway).

Setting the initial value of a UILABEL

I'm trying to create a simple Quiz app (I'm a beginner), when I launch the app I want a UILabel to show the first question (of an array of questions). I'm having some trouble with setting the initial value.
I've done a couple of attempts, whiteout success. I my QuizAppDelegate.h file I declare my UILabel like this:
IBOutlet UILabel * questionField;
In my main .m file I have tried the following:
- (id)init {
[super init];
questions = [[NSMutableArray alloc] init];
// Not working
questionField = [[UILabel alloc] init];
[questionField setText:#"Hello"];
// Working
NSLog(#"Hello");
[self defaultQuestions];
// [self showQuestion];
return self;
}
Another thing I have tried is the following in QuizAppDelegate:
#property (nonatomic, retain) IBOutlet UILabel *questionField;
- (void)changeTitle:(NSString *)toName;
And in the .m file:
#synthesize questionField;
- (id)init {
[super init];
questions = [[NSMutableArray alloc] init];
// Not working
[self changeTitle:#"Hello"];
// Working
NSLog(#"Hello");
[self defaultQuestions];
// [self showQuestion];
return self;
}
-(void)changeTitle:(NSString *)toName {
[questionField setText:toName];
}
Any tips on how to solve this would be great!
// Anders
Hopefully you're not actually putting code into main.m. On iOS, you rarely modify that file.
Since you're doing everything in the AppDelegate, let's keep it there (as opposed to creating a new UIViewController). Let's start with the basics.
Adding the Label as an instance variable
You're doing this correctly—inside the curly braces of the .h file, put the line
IBOutlet UILabel * questionField;
Then, declare the corresponding property, and make sure to synthesize it in the .m file.
#property (nonatomic, retain) IBOutlet UILabel *questionField;
#synthesize questionField // in the .m file
Adding the UILabel in Interface Builder
Open up MainWindow.xib. Drag a UILabel from the Library to the Window that represents your app's window. Then Control-Drag from the AppDelegate object (the third icon on the left in Xcode 4; it'll be labelled in the Document window in IB 3). You'll see a little black window come up—select the option called questionField to make the connection.
See this link for screenshots and how to make connections in IB. The same applies in Xcode 4.
Changing the text
You don't need a separate method to change the text—just modify the label's text property.
Pick a method that'll be called when the app launches (applicationDidFinishLaunching:WithOptions: is a good place to do it in), and put the following code:
questionField.text = #"Hello";
And that's it!
Code
QuizAppDelegate.h
#import <UIKit/UIKit.h>
#interface QuizAppDelegate : NSObject <UIApplicationDelegate> {
IBOutlet UILabel *questionField;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UILabel *questionField;
#end
QuizAppDelegate.m
#import "QuizAppDelegate.h"
#implementation QuizAppDelegate
#synthesize window=_window;
#synthesize questionField;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
// Add the tab bar controller's current view as a subview of the window
[self.window addSubview:self.questionField];
[self.window makeKeyAndVisible];
self.questionField.text = #"Hello";
return YES;
}
- (void)dealloc
{
[_window release];
[questionField release];
[super dealloc];
}
#end
If you're creating the label programmatically, then you have to add the label to the view:
[self.view addSubview:questionField];
This assumes that you have a ViewController. If not, and you're doing this directly in the AppDelegate (a very bad idea, by the way), then do
[self.window addSubview:questionField];
If you're creating it in the IB, make sure you set up the connections.
You should not both add the UILabel in the IB and instantiate it programmatically. Only call alloc if you are creating it programmatically. Otherwise, if using the IB, skip that part. You created it already with the xib.
I suspect that you have either not created your Interface Builder layout properly - either you have missed the control out all together or more likely you have not connected that control to the questionField outlet in yout header file.
You need to drag a UILabel view into the main view and then connect it to the correct line in your header file.
You shouldn't be using your main.m like that at all. In fact, you should almost certainly never do anything with it. Try creating a UIViewController subclass and practicing your quiz with that. (Add the UILabel to the IB file and then connect the outlet.) Perhaps use the View-Based Application template while you are practicing.
This is a good answer:
"You're doing this correctly—inside the curly braces of the .h file, put the line
IBOutlet UILabel * questionField;"
I was trying to change the value of mylabel.text and the screen didn't update the label with this.value. I included the {IBOutlet UILabel * mylabel} and it works like a charm!
So this answer is valid to change the text of a label programmatically!
Thanks

When to alloc/init an ivar, and when not to

All,
In Apple's sample code "DateCell"
http://developer.apple.com/library/ios/#samplecode/DateCell/Introduction/Intro.html
the ivar "pickerView" is declared in MyTableViewController.h like this:
#interface MyTableViewController : UITableViewController
{
#private
UIDatePicker *pickerView;
UIBarButtonItem *doneButton; // this button appears only when the date picker is open
NSArray *dataArray;
NSDateFormatter *dateFormatter;
}
#property (nonatomic, retain) IBOutlet UIDatePicker *pickerView;
...
It is synthesized in the class file MyTableViewController.m like this:
#implementation MyTableViewController
#synthesize pickerView, doneButton, dataArray, dateFormatter;
...
When this app runs, I can insert NSLog(#"%#",pickerView) into ViewDidLoad and see that, sure enough, the ivar pickerView is real and has a value. Nowhere, though, does this class alloc/init pickerView. And that's the root of the question: how's it getting done if it's not being done explicitly?
Well, I naively copied this stuff to my code into my RootViewController.h and .m files figuring I could do the same, but pickerView stubbornly remains uninitialized (and my NSLog calls return "(nil)" as its value) no matter what I try short of explicitly alloc/initing it. Certainly RootViewController is being instantiated, or the RootView wouldn't be showing up, right? So shouldn't my pickerView be coming along for the ride just as it does for Apple?
So... do I have to manually alloc/init the pickerView instance variable? If so, where's Apple doing it? Or how are they doing it somehow otherwise?
I think I'm missing something very basic here, but I have no idea what it is. I can't see anything in Interface Builder or XCode that looks different between mine and theirs, but I've got tunnel vision at this point and can't see anything clearly anymore.
Thanks,
Bill
The IBOutlet modifier on this line is the key...
#property (nonatomic, retain) IBOutlet UIDatePicker *pickerView;
IBOutlet is a decorator that indicates that the object will be hooked up/connected/initialised when the corresponding xib (Interface Builder) file is loaded. The sample application you're looking up will contain a UITableViewController is a xib which has a connection to a UIPickerView.
You can either go the route of creating your own custom xib file and wire to an instance of UIPickerView or you can manually initialise the picker yourself.
Interface Builder (nib or xib) treats automatically IBOutlet ivar with connection of components.
IBOutlet is a special keyword that is
used only to tell Interface Builder to
treat an instance variable or property
as an outlet. It’s actually defined as
nothing so it has no effect at compile
time.
Your First iOS Application - The
View Controller Interface
Declaration, Making Connections
Interface Builder User Guide -
Defining Outlets and Actions in
Xcode