Simple math app terminated in Xcode- Why? - ios

Alright, so I'm trying to do something very, very simple: Multiplying the user input from one textfield by another textfield and feeding out the answer through a label. There are no error messages, but when I try to run the app, the simulator screen goes black and Xcode says this:
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key outputlabel.'
I have no idea why it is doing this. Any suggestions? Please be extremely specific as I am new to programming.
My code:
//
// ViewController.h
// Cramer
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
// Objects are given addresses:
#property (weak, nonatomic) IBOutlet UITextField *box_a;
#property (weak, nonatomic) IBOutlet UITextField *box_b;
#property (weak, nonatomic) IBOutlet UILabel *hiLabel;
#property (weak, nonatomic) IBOutlet UIButton *clickButton;
#end
AND
//
// ViewController.m
// Cramer
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
// Math takes place:
- (IBAction)clickButton:(id)sender {
NSInteger number1 = [self.box_a.text integerValue];
NSInteger number2 = [self.box_b.text integerValue];
NSInteger prod = number1 * number2;
self.hiLabel.text = [NSString stringWithFormat:#"%#", #(prod)];
}
#end

It seems like in your view controller XIB file, created using the Interface Builder or Storyboard graphic editor, you have some view (probably a UILabel) connected to a "outputlabel" property of the File Owner (that is your ViewController class) which doesn't exist.
Typically this happens when you initially connect an object from the XIB to a new outlet in the code, then you rename the outlet in the code but you forget to reconnect the object in the XIB to the new reanmed outlet. It could be, in your case, that you initially connected the output label to a IBOutlet property called "outputlabel", then you renamed it to "hiLabel" but you forgot to reconnect the label in the XIB to the new "hiLabel" IBOutlet.
To verify this you can look at all your objects in the view controller graphical interface, right-click on each of them and see their outlet connections and check that they point to properties effectively defined in the class.

your label on your storyboard is hooked up to a UILabel in your view controller named "outputlabel". However in your view controller you have it named "hiLabel". If, in interface builder, you click on your label then go to view -> utilities -> connection inspector you'll see the connections on the right hand side and should be able to verify what it's connected to. Either delete the connection and start over or change the name of your label in your view controller.

In the last line [NSString stringWithFormat:#"%#", #(prod)];, why are you using %#? NSInteger is a primitive type, not an object. It seems to me you should use a %d so that the line would read [NSString stringWithFormat:#"%d", prod];.
ETA: Use %ld instead of %d.

Related

Need to connect a UISlider created with Interface Builder to non-event code

I have a ViewController that populates a couple of sliders as so:
// ViewController.h
#interface ViewController : UIViewController
#property (weak, nonatomic) IBOutlet UISlider *aSlider;
#property (weak, nonatomic) IBOutlet UISlider *anotherSlider;
#end
// ViewController.m
#interface ViewController ()
#end
#implementation ViewController
-(void)resetSliders
{
NSLog(#"Resetting sliders sl1: %# sl2: %#", self.aSlider, self.anotherSlider);
[self.aSlider setValue:0.5f animated:NO];
[self.anotherSlider setValue:0.5f animated:NO];
}
- (IBAction)setOneSlider:(UISlider *)sender {
NSLog(#"Setting aSlider to %f", sender.value);
self.sl1Val = sender.value;
[self doAThing];
}
- (IBAction)setTwoSlider:(UISlider *)sender {
NSLog(#"Setting anotherSlider to %f", sender.value);
self.sl2Val = sender.value;
[self doBThing];
}
#end
The calls to setOneSlider and setTwoSlider are wired to the value changed events of the two sliders. That works perfectly well. Unfortunately, I have not connected the sliders to their programmatic handles, because the call to resetSliders yields no change in the UI, even with a call added to setNeedsDisplay on the two slider elements.
When resetSliders is called, the log shows:
2015-04-28 12:22:19.608 myApp[4489:681127] Resetting sliders sl1: (null) sl2: (null)
Can anyone indicate to me how to set the self.aSlider and self.anotherSlider with the correct object handles?
To add some color: I have dragged the UI representation of the sliders to their respective #property declarations, and I can see that they have filled-in grey circles in the margin, indicating that they've been wired. The Connections Inspector shows both a "Value Changed" event trigger and a Referencing Outlet connecting myApp to the slider(s).
I'm extremely new to IOS programming and am reaching the limits of learning-by-failing.
The properties should be defined inside the #interface blocks. Yours are currently outside. Additionally, they should probably be weak instead of retain, and no need for the #synthesize statements or the ivars.
Lastly, when you reference them in code, you should do so as self.aSlider, not just aSlider.
It sounds like you still need to connect these outlets in Interface Builder:
#property (retain, nonatomic) IBOutlet UISlider *aSlider;
#property (retain, nonatomic) IBOutlet UISlider *anotherSlider;
Also you don't need to declare properties and ivars for the same sliders. Just declare and use the properties you already have.
#interface ViewController : UIViewController
and
-(void)resetSliders
{
// note the addition of 'self.' below
NSLog(#"Resetting sliders sl1: %# sl2: %#", self.aSlider, self.anotherSlider);
[self.aSlider setTo:0.5f animated:NO];
[self.anotherSlider setTo:0.5f animated:NO];
}

iOS custom UIView access properties in code

So I've created a custom UIView subclass and have it assigned to a UIView in my main storyboard. When the view loads everything is displayed properly.
The issue I'm having is that I need to be able to access properties of said custom UIView since the view is data driven.
JSON_table.h:
#import <UIKit/UIKit.h>
#interface JSON_table : UIView
#property (strong, nonatomic) IBOutlet UIView *view;
#property (weak, nonatomic) IBOutlet UISearchBar *searchbar;
#property (weak, nonatomic) IBOutlet UITableView *table_view;
#property (weak, nonatomic) NSString *data_header;
#property (weak, nonatomic) NSString *data_list;
#end
JSON_table.m:
#import "JSON_table.h"
#implementation JSON_table
- (id) initWithCoder:(NSCoder *)aDecoder{
self = [super initWithCoder:aDecoder];
if (self) {
[[NSBundle mainBundle] loadNibNamed:#"JSON_table" owner:self options:nil];
[self addSubview:self.view];
}
return self;
}
#end
(I know I'm missing delegates for tableview, ill be adding these later)
The issue I'm having is when I right click on my UIView on my storyboard I get:
The problem is when I try to connect "view" to my header file "
ViewController.h" it doesn't let me create a IBOutlet, so I cannot reference my view and its properties in code.
This is what I am trying to accomplish:
"Table" is of type UIView
Idea:
Would this have anything to do with the UIView being on the second view in my storyboard? I noticed that I don't seem to have any problem attaching to anything on the first page, but the second one I can't.
You can only connect the outlets of a view to it's class object. You are trying to connect outlets of JSON_table object to UIViewController object.
If you need to access those properties in UIViewController object. You need to import
JSON_table.h
in your view controller. And create and instantiate a object of it.
JSON_table * customView = [[JSON_table alloc]init];
Now you can access all the properties of it as:
customView.searchbar, customView.view etc.
Added by theshadow124:
Thanks to everyone who attempted to help me solve my problem. Due to being fairly new to coding for iOS I didn't realize I had to assign a custom class to every UIViewController in my storyboard(I thought they they would inherit from the base if I didn't specify). simply creating a new subclass of UIViewController and assigning it under the Identity inspector fixed my problem and now I can properly assign outlets.
Im going to accept this answer because it was one of the issues I ran into after fixing the subclass on the storyboard issue.
Please make sure that in assistant editor your are opening the same class that your custom class is contained in .

How to bind the control on the form with variable

I am just start studying iOS developing watching Stanford iOS course, but it looks like I have already missing something.
I have a form with UILabel and UIButton. When an user press the button the title of the button must be added to the text of label.
Here is my current CalculatorViewController.h:
#import <UIKit/UIKit.h>
#interface CalculatorViewController : UIViewController
#property (weak, nonatomic) IBOutlet UILabel *display;
#end
and here is a CalculatorViewController.m:
#import "CalculatorViewController.h"
#implementation CalculatorViewController
#synthesize display = _display;
- (IBAction)digitPressed:(UIButton *)sender {
NSString *digit = [sender currentTitle];
UILabel *myDisplay = self.display;
myDisplay.text = [myDisplay.text stringByAppendingString:digit];
}
#end
The problem is that self.display (and myDisplay) variables have a nil value. Looks like I need to do something to link my variable with control on the form. What ?
Thanks in advance.
You need to link the control, the UILabel in Interface Builder to the variable in your CalculatorViewController class.
It is very likely that the file's owner (talking about the Xib file) is your CalculatorViewController, so you need to Control+drag the file's owner (or the object representing your VC) to the control and you will be shown a menu with the possible IBOutlet variables declared in your class, so you select the one you want to represent the control.
You can check if this link is properly set in two ways: (1) Select the UILabel in Interface Builder and see if there's a connection to the variable in the Connections Inspector, or (2) In your code you'll see a bullet near the IBOutlet declaration, if the bullet is hollow the connections is not set, if the bullet is filled the connection is set.
There is no need of this line
UILabel *myDisplay = self.display;
You have already declared your label in your interface file
- (IBAction)digitPressed:(UIButton *)sender
{
NSMutableString *string = [myDisplay.text stringByAppendingString:sender.titleLabel.text];
myDisplay.text = string;
}

How can I manipulate objects in a subView?

Got away from XCode programming for a while, now I'm starting back and feel like I'm starting ALL over. I have a simple example that's driving me crazy.
I have created a sub class of UIView called Word1View and added it to my storyboard.
I declared it as a property in the main view controller and attached it as an IBOutlet to the main view. I can draw on this view using Core Graphics with no problems (rectangles, lines, etc). Here's the code in the ".h" file. The property is synthesized correctly in the ".m"
#import <UIKit/UIKit.h>
#import "Word1View.h"
#interface Board3ViewController : UIViewController
{
Word1View *word1View;
}
#property (nonatomic, strong) IBOutlet Word1View *word1View;
#end
Now, here's the problem. I have added a UILabel (I will be adding UIImageFiles later)
in Word1View.h it appears as so:
#import <UIKit/UIKit.h>
#interface Word1View : UIView
{
UILabel *testLabel;
}
#property (nonatomic, retain) UILabel *testLabel;
#end
This property is also synthesized correctly. The UILabel was added to the view in the main storyboard. I tried to make this an IBOutlet, but could not hook it up as long as it was part of the subview. I tried to access the UILabel in my main view controller as so:
[super viewDidLoad];
[self.view addSubview:word1View];
NSLog(#"Label text is: %#", word1View.testLabel.text);
I don't have any access to that label as evidenced by the output to NSLog which is:
Board3[14520:c07] Label text is: (null)
I would like to be able to access the label (change its text, properties etc) from my main View Controller.
Any help is greatly appreciated. Thank you.
You need to instantiate your UILabel and give it some text.
wordView1 = [[UILabel alloc] init];
wordView.text = #"Some Text";

getting signal SIGABRT in first IOS project, Xcode 4

I am trying to create my first test app in IOs and everything I do gets me that error. I am using xcode 4.4.
The app is very simple. It has a button, and When I press it, a label and an imageview must appear.
My whole code is this:
ViewController.h
//
// ViewController.h
// helloWorld_04
//
//
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController{
IBOutlet UILabel *label;
IBOutlet UIImageView *Kant;
}
#property (nonatomic, retain) IBOutlet UILabel *label;
#property (nonatomic, retain) IBOutlet UIImageView *Kant;
- (IBAction)buttonGuess:(id)sender;
#end
and my implementation file:
#import "ViewController.h"
#interface ViewController ()
#end
#implementation ViewController
#synthesize label,Kant;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (void)dealloc {
[label release];
[Kant release];
[super dealloc];
}
- (IBAction)buttonGuess:(id)sender {
label.text=#"Hello World i am back!";
UIImage *imageSource=[UIImage imageNamed:#"kantStair.png"];
Kant.image=imageSource;
}
#end
My error log is this:
2012-08-23 13:38:50.030 helloWorld_04[537:c07] *** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<ViewController 0x6a5e1f0> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key image.'
*** First throw call stack:
(0x14b2022 0xeb2cd6 0x14b1ee1 0x9c3022 0x934f6b 0x934edb 0x94fd50 0x23771a 0x14b3dea 0x141d7f1 0x23626e 0xdc1fc 0xdc779 0xdc99b 0x3b401 0x3b670 0x3b836 0x4272a 0x2d1b 0x13386 0x14274 0x23183 0x23c38 0x17634 0x139cef5 0x1486195 0x13eaff2 0x13e98da 0x13e8d84 0x13e8c9b 0x13c65 0x15626 0x2a22 0x2995)
terminate called throwing an exception(lldb)
and it gets me that signal in that line:
//
// main.m
// helloWorld_04
//
//
#import <UIKit/UIKit.h>
#import "AppDelegate.h"
int main(int argc, char *argv[])
{
#autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
I have read several answers here but not found sollution to my problem, that why I made it a new question. I thought that it may be a problem with the connection so what I did on my own was to "darg and drop" my label and my image to "file's owner" but still getting the error.
Looking at your error message, it looks like you have something defined as image in Interface Builder, but doesn't exist. E.g., maybe you have something like:
But you don't have a image property. Did you have one once upon a time, perhaps having renamed it to Kant? If you have something like this defined in Interface Builder, delete it (by tapping on the "x" next to the outlet that I've highlighted) and then link it up again to your new control.
Update:
You should definitely fix your bug above, and hopefully the above observation helps you find it. There is not a bug in your code, but rather the problem undoubtedly rests with your Interface Builder linkages.
But, having said that, if you're a new programmer, I hope you don't mind some unsolicited stylistic observations. Clearly, given that it is a matter of style, these can be debated, but I think these all represent either established or emerging iOS coding standards. Anyway, I might suggest that in the future:
Like David H suggested, you should use lower case variable names.
You probably should have #synthesize statements that either say #synthesize label = _label, or, if you're using Xcode 4.4 or later, just omit the #synthesize statement altogether. (I know that Interface Builder can generate a simple #synthesize statement for you, but it really is best practice to #synthesize with a unique instance variable name so you don't accidentally confuse instance variables with properties.)
You should reference your instance variables in init and dealloc methods (i.e. the variable name with the leading underscore) and elsewhere use the property (with the leading self.), as noted by Born Survivor.
You probably should omit the instance variables and let the #synthesize statement do these for you (so that if you make a typo, you don't accidentally end up with two instance variables).
Thus your code would then become:
// ViewController.h
#import <UIKit/UIKit.h>
#interface ViewController : UIViewController
// note, no braces with instance variables defined
// once upon a time that was recommended by Apple, but no longer
// just let the following #property statements and the subsequent
// #synthesize statement generate the instance variables for you.
#property (retain, nonatomic) IBOutlet UIImageView *kant; // note the lower case "k"
#property (retain, nonatomic) IBOutlet UILabel *label;
- (IBAction)buttonGuess:(id)sender;
#end
and
// ViewController.m
#import "ViewController.h"
#implementation ViewController
#synthesize label = _label; // note the #synthesize statement let's us define what the instance variable name should be, _label in this case
#synthesize kant = _kant;
- (void)viewDidUnload
{
[self setKant:nil];
[self setLabel:nil];
[super viewDidUnload];
// Release any retained subviews of the main view.
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
- (void)dealloc {
[_kant release]; // note I'm now using the instance variables that begin with the underscore
[_label release];
[super dealloc];
}
- (IBAction)buttonGuess:(id)sender
{
self.label.text = #"Hello World i am back!"; // note, I'm using the properties with the preceding "self."
UIImage *imageSource = [UIImage imageNamed:#"kantStair.png"];
self.kant.image = imageSource;
}
#end
Its important in ObjectiveC to always name your variables with a lower case letter - because when you synthesize a variable like "foo" you get "-(id)foo;// the getter" and "-(void)setFoo:(id)val;//the setter". See how the setter uses a capital letter. So first thing you should do is rename 'Kant' to 'kant'. [by convention only Classes have initial capital letters, so you help others like me read your code by following the conventions.]
So first thing you do is change 'Kant' to 'kant', and then go back to the Interface builder view and re-wire the newly named variable to the UIImageView.
If that does not fix the problem, you have iswired 'kant' or there is some other oddity going on - add this line of code right before you set the image:
NSLog(#"kant has class %#", NSStringFromClass([kant class]) );
and lets see what it really is.

Resources