Alright, in my rootViewController, I am able to push another viewController that I defined myself onto the screen. However, when I make any connections between that viewController and its own .h file, the program just hangs and crashes, giving me this error:
2010-06-04 15:36:13.944 pooldocfinal[11971:20b] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key label1.'
That happens when i don't connect anything besides that one UILabel. Here is the code I use to declare/push the view (named balanceViewController):
- (IBAction) pushedBalanceButton
{
balanceViewController *controller = [[balanceViewController alloc] initWithNibName:#"balanceViewController" bundle:nil];
[self.navigationController pushViewController:controller animated:YES];
[controller release];
}
And here is the .h file of the view that I am pushing, it has only one thing in it:
#import <UIKit/UIKit.h>
#interface balanceViewController : UIViewController {
IBOutlet UILabel *label1;
}
#end
And like I said, everything works unless I actually make a connection in Interface Builder between anything in balanceViewController.xib and balanceViewController.h (in this case, it is the one UILabel object).
You should alloc a balanceViewController, not a UIViewController.
I believe if you have an IBOutlet, you need to define getters/setters. That's what Key Value coding compliant means. You can do this via #property statements and #synthesize statements, or manually if you so choose.
#interface balanceViewController : UIViewController {
IBOutlet UILabel *label1;
}
#property (nonatomic, retain) IBOutlet UILabel *label1;
#end
Then add
#synthesize label1;
to your implementation
EDIT - PS, don't forget to [label1 release] in your dealloc method
Related
I'm hoping someone can shed some light on my question below.
I'm getting a property delegate not found on object of type viewcontroller error on when I declare the delegate in the parent view:
Here's the relevant code in the parent .h file:
#protocol ModalViewDelegate
- (void)didReceiveFrequencyMessage:(NSString *)message;
#end
#interface jhsManageRemindersViewController : UIViewController<UIAlertViewDelegate, UINavigationControllerDelegate, ModalViewDelegate>
and here's where I call the child view:
jhsScheduleViewController *jhsScheduleController = [[jhsScheduleViewController alloc]
initWithNibName:#"jhsScheduleViewControllerr" bundle:nil];
jhsScheduleController.delegate = self;
// Create the navigation controller and present it modally.
UINavigationController *navigationController = [[UINavigationController alloc]
initWithRootViewController:jhsScheduleController];
navigationController.modalTransitionStyle = UIModalTransitionStyleCrossDissolve;
[self presentModalViewController:navigationController animated:YES];
and here's part of my child .h file
#protocol ModalViewDelegate ;
#interface jhsScheduleViewController : UIViewController {
//id<ModalViewDelegate> delegate;
// __unsafe_unretained id <ModalViewDelegate> _delegate;
__weak id <ModalViewDelegate> delegate;
NSMutableString *message;
}
#property ( weak) id<ModalViewDelegate> delegate;
//#property (nonatomic, weak) id<ModalViewDelegate> delegate;
#property (nonatomic, retain) NSMutableString *message;
and finally, here's my .m usage
#synthesize delegate;
//#synthesize delegate = _delegate;
I've viewed and tried various solutions based upon Stackoverflow questions and this recommended blogpost. I've included some of my attempted solutions in commented out code, just as an FYI.
I started with the code I had in an iOS4 app but that generates the error. As a footnote, this is an app with a TabBarController and a NavigationController
Can someone tell me how to fix this so the delegate error can be resolved?
Thank you for your help!
Well, I'm not sure what the problem was. But as a last resort, I saved every file, then tried to build it, with Xcode still reporting the error, which worked.
Actually, there was an error in the initWithNibName but it ran fine until it got to that point, and correcting the typo fixed that. Again, I'm not sure what the problem was but I seem to be on my way.
I have my ViewController.h/m and another class Keyboard.h/m.
In my ViewController.h I have an UILabel:
#interface ViewController : UIViewController{
UILabel *label;
}
#property (nonatomic, retain) IBOutlet UILabel *label;
and my ViewController.m looks so
#import "ViewController.h"
#synthesize label;
...
Now I want to change the label from Keyboard.m.
I have tried something like this:
#import "ViewController.h"
...
ViewController *vc;
vc.label.text = #"text";
it compiles without any errors but the label doesn't change
It's very error prone that you're doing here.
ViewController *vc;
declares a pointer, but this won't be initialized; so when you're accessing its property vc.label.text, objc_messageSend() will be passed a bogus pointer, so it can potentially crash! (you're lucky if id didn't do so.)
Anyways: if you have done it well, like ViewController *vc = [[ViewController alloc] init]; creating a new instance wouldn't have affected the other instance. You have to store the pointer to your instance somewhere, e. g. set a #property (retain) ViewContrller *vc; to your application's app delegate object, and access it through that property like this:
[(MyAppDelegate *)[[UIApplication sharedApplication] delegate] vc].label.text = #"new text";
that way it should work.
Hope it helps.
How are you initiating your vc variable? I am guessing that is where the error is coming from. Try doing:
vc = [[ViewController alloc] initWithNibName:# ViewController"];
If you are already doing that, make sure your IBOutlet is hooked up correctly. You are setting the variable correctly so the error must be coming from somewhere else.
my code broke somewhere along the way, and crashes when using the navigation bar buttons.
Error message:
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIView newMemoViewController:didAddMemo:]: unrecognized selector sent to instance 0x5b55a60'
When debugging, the program does run the cancel method, and throws an exception at the #synthesize line. However, I cannot see anything wrong with it.
The symptoms are identical, so I am including the relevant code only for the Cancel button:
NewMemoViewController.h
#import <UIKit/UIKit.h>
#protocol NewMemoDelegate;
#class AKVoiceMemo;
#interface NewMemoViewController : UIViewController {
#private
AKVoiceMemo *voiceMemo;
id <NewMemoDelegate> delegate;
}
#property (nonatomic, retain) AKVoiceMemo *voiceMemo;
#property (nonatomic, assign) id <NewMemoDelegate> delegate;
#end
#protocol NewMemoDelegate <NSObject>
- (void)newMemoViewController:(NewMemoViewController *)newMemoViewController didAddMemo:(AKVoiceMemo *)voiceMemo;
#end
NewMemoViewController.m
#import "NewMemoViewController.h"
#synthesize delegate;
- (void)viewDidLoad {
UIBarButtonItem *cancelButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Cancel" style:UIBarButtonItemStyleBordered target:self action:#selector(cancel)];
self.navigationItem.leftBarButtonItem = cancelButtonItem;
[cancelButtonItem release];
}
- (void)cancel {
[self.delegate newMemoViewController:self didAddMemo:nil];
}
Your help would be appreciated.
Edit: the delegate is the RootViewController:
- (void)newMemoViewController:(NewMemoViewController *)newMemoViewController didAddMemo:(AKVoiceMemo *)voiceMemo {
if (voiceMemo){
// Show the note in a new view controller
// TODO: Implement this
}
[self dismissModalViewControllerAnimated:YES];
}
You're probably setting the delegate of NewMemoViewController to a UIView object instead of an object that implements the NewMemoDelegate protocol.
The error message is telling you that a newMemoViewController:didAddMemo: message was sent to a UIView object and the UIView object didn't know what to do with it. Since your cancel method calls newMemoViewController:didAddMemo: on the delegate, it is the delegate which is the UIView object that doesn't recognize the newMemoViewController:didAddMemo: message. In other words, your delegate is a UIView and it doesn't implement the NewMemoDelegate protocol.
If you are correctly setting the delegate, then #jtbandes makes a great point: The delegate is probably being released and a UIView object is taking over the same memory location, thus "becoming" the delegate by accident. You're doing the right thing by using the assign attribute for your delegate; that's fairly standard Cocoa practice. However, you do need to make sure that the delegate is retained by another object, and that object needs to make sure that the delegate sticks around as long as NewMemoViewController needs it to.
I'm guessing you've over-released the delegate. I notice you have #property (assign) ... delegate;. This means that whenever you set the delegate, that object must be retained by something else as well.
The other possibility is the delegate is actually a UIView, but I'm guessing it's the other case.
Im new to iphone development and after lots of reading on it im still trying to figure out how UIViews operate properly. I have been playing about with it and i this is where i am at so far:
I have created a new xcode project using the view-based application. I have my MMAppViewController classes and i created a new UIViewController subclass called "Level1View".
There is a button titled "Level 1" that takes me to the "Level1View" viewController. In this viewController there is there is a "next" button, a "main menu" button (that returns to MMAppViewController) and there is a label, currently titled "Level 1".
My problem is that the code i have used to change the title of label does not work! Does anyone know why this is? Here is my code:
#class MMAppViewController;
#interface MMAppAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
MMAppViewController *viewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet MMAppViewController *viewController;
#end
and
#implementation MMAppViewController
-(IBAction)pushLevel1{
Level1View *level1View = [[Level1View alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:level1View animated:YES];
}
...
and
#import <UIKit/UIKit.h>
#interface Level1View : UIViewController {
IBOutlet UILabel *labelTitle;
}
-(IBAction)pushBack;
-(IBAction)pushNext;
#end
and
#import "Level1View.h"
#import "MMAppViewController.h"
#implementation Level1View
-(IBAction)pushBack{
MMAppViewController *MainView = [[MMAppViewController alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:MainView animated:YES];
}
-(IBAction)pushNext{
[labelTitle setText:(#"Thanks for playing :)")];
}
- (void)didReceiveMemoryWarning {
...
Currently the app runs but the label wont change when i hit the "next" button. Can anyone help?
are you sure a UINavigationController isn't a better tool for the job you want to do? That will make it easy for you to manage a stack of UIView objects.
That said, have you tried adding logging to make sure your pushNext method is getting called? where is labelTitle declared? Did you use a XIB or not?
Did you bind the Label in Interface Builder to the labelTitle outlet in your Level1View?
If you forget that step, the outlets won't work. Even after several years, I still forget this step sometimes.
--Mike
are you sure you connected the label in IB?
and if you set a property "#property (nonatomic, retain) IBOutlet UILabel *labelTitle;" in Level1View.h you can access it from Main View:
Level1View *level1View = [[Level1View alloc] initWithNibName:nil bundle:nil];
[self presentModalViewController:level1View animated:YES];
level1View.labelTitle.text = #"something";
[level1View release];
The other thing you shouldn't present the Main View Controller again instead dismiss the Level1View with:
#implementation Level1View
-(IBAction)pushBack{
[self dismissModalViewControllerAnimated:YES];
}
//
and maybe the problem is [[Level1View alloc] initWithNibName:nil bundle:nil] you have to specify the nib you want to load e.g. [[Level1View alloc] initWithNibName:#"Level1View" bundle:nil]
Declare labelTitle as a property in your header file, and synthesize labelTitle in your .m - as long as labelTitle is hooked up through interface builder the rest of your code is fine.
.h
#property (nonatomic, retain) IBOutlet UILabel *labelTitle;
.m
#synthesize labelTitle;
Then your setter call will work. (also, dot-notation works for synthesized properties so you may as well use it)
change
[labelTitle setText:(#"Thanks for playing :)")];
to
labelTitle.text = #"Thanks for playing :)";
Synthesizing a property will create setter and getter methods at runtime. Read: The Objective-C Programming Language
Here is what I do:
1) Create New UIViewController subclass , tick with NIB for interface builder
2) In the header:
#interface QuizMainViewController : UIViewController
{
UILabel* aLabel;
}
#property (nonatomic, retain) IBOutlet UILabel* aLabel;
#end
3) In the .m
#import "QuizMainViewController.h"
#implementation QuizMainViewController
#synthesize aLabel;
- (void)dealloc
{
[aLabel release];
[super dealloc];
}
#end
4) Open the NIB In interface builder, drag a new UILabel into the view.
I test the program here and it runs fine.
5) right click on file's owner, connect 'aLabel' from the Outlets to the UILabel.
I run here and it crashes. Message from log:
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key aLabel.'
I have fixed the problem!
The view was being loaded from a tab bar controller, I had set the nib name to be "QuizMainViewController" but I didn't set the Class identity of the view to be "QuizMainViewController" it was stuck at the default value of "UIViewController".
When the view was loaded it thought it was an instance of UIViewController, therefore it didnt know about the aLabel property.
MORAL OF THE STORY: When using tab bar controller, set the nib name AND the class idenity for nibs that have their own view controller.
Try:
#interface QuizMainViewController : UIViewController
{
IBOutlet UILabel* aLabel;
}
Supposedly, you no longer have to do this in Objective-C 2.0 but I've run into problems on the iPhone leaving it out.
Edit:
You could try changing
#property (nonatomic, retain) IBOutlet UILabel* aLabel;
to
#property (nonatomic, retain) IBOutlet UILabel *aLabel;
Don't think that should matter however. The compiler can usually puzzle that out.
Edit01:
In IB, make sure that he class of the view controller is set to QuizManViewController and not just UIView.