PDA

View Full Version : Xcode: Problem outputting the value in a field by pressing a button




bahlquist
Oct 14, 2010, 09:52 PM
Hi,
In Interface Builder I dragged a push button (NSButton) and a text field (NSTextField) to the window. My aim is to enter a number into the field and print this out to the console by way of NSLog when I push the button. I have an object (not sure if this is the right word) BATester that will control this. The button is connected to BATester as an IBAction called "theButton", and the field as "theField". However my program crashes if I push the button after entering into the field. Can you tell me what is going on? Here are my files:

BATester.h:

#import <Cocoa/Cocoa.h>

@interface BATester : NSObject {
NSNumber* numb;
}
- (IBAction)theButton:(id)sender;
- (IBAction)theField:(id)sender;
@end

BATester.m:

#import "BATester.h"

@implementation BATester
- (IBAction)theButton:(id)sender{
NSLog(@"The button says: %f",[numb floatValue]);
}
- (IBAction)theField:(id)sender{
numb = [NSNumber numberWithFloat:[sender floatValue]];
NSLog(@"The field says: %f",[numb floatValue]);
}
@end

If I push the button first I get an output of [. . .] 0.00000. If I change the field value the output is [. . .] [whatever number I entered]. My program tries to make use of a variable which is part of my object BATester. If there is another way to do this please let me know, but also please tell me what is wrong with the above.



cubist
Oct 14, 2010, 10:32 PM
Don't you need an @property for the numb variable?
e.g. @property (nonatomic, retain) NSNumber *numb;

My guess would be that, as long as it's nil, cocoa displays 0, but once it's non-nil, it's getting sent the floatValue message and crashing because it's not properly declared.

knightlie
Oct 15, 2010, 07:15 AM
Edit: never mind. Misread the post.

How are you putting a value into numb? What is the error message when it crashes?

bahlquist
Oct 15, 2010, 11:11 AM
Edit: never mind. Misread the post.

How are you putting a value into numb? What is the error message when it crashes?

You see all the code. I enter numbers into the field (integers or decimals) and it returns the number just fine, but as soon as I press the button, it crashes. What it shows after it crashes is some junk about GNU (?!?). If I assign a value to numb while inside the "theButton" method, then the program does ok. The problem is when I try to use the value I get from the field when I press the button.

Sydde
Oct 15, 2010, 11:14 AM
Don't you need an @property for the numb variable?
e.g. @property (nonatomic, retain) NSNumber *numb;

No, typically you either use @property or do an instance variable declaration like the one in bahlquist's code (usually not both). If you do the latter, are instance variables have nil, zero or false values when the object is created.

The problem with the code is in the -theField: method. The NSNumber is created with a convenience method, meaning it is autoreleased. By the time the button is pressed, numb is no longer a valid object because the autorelease pool has been drained.

Toreddo
Oct 15, 2010, 01:00 PM
This is not the right way to do it, are you sure your applications works when you type in to your textfield? Does it log?

Your currently trying to trigger an action with your textfield but that won't happen if you just connect it to the sender. The better way to do this is to connect your textfield to an property which just contains the NSTextField and read out the value when you press the button.

#import <Cocoa/Cocoa.h>

@interface BATester : NSObject {
NSNumber* numb;
NSTextField *textField;
}
- (IBAction)theButton:(id)sender;
@property (nonatomic, retain) IBOutlet NSTextField *textField;
@end

Synthesize it in your .m:
#import "BATester.h"

@implementation BATester
@synthesize textField;

- (IBAction)theButton:(id)sender{
NSLog(@"The button says: %f",[textField floatValue]);
}
@end

Don't forget to connect to textfield to the IBOutlet

bahlquist
Oct 15, 2010, 03:39 PM
No, typically you either use @property or do an instance variable declaration like the one in bahlquist's code (usually not both). If you do the latter, are instance variables have nil, zero or false values when the object is created.

The problem with the code is in the -theField: method. The NSNumber is created with a convenience method, meaning it is autoreleased. By the time the button is pressed, numb is no longer a valid object because the autorelease pool has been drained.

Thanks! I fixed the problem by changing the line:

numb = [NSNumber numberWithFloat:[sender floatValue]];

to:

numb = [[NSNumber numberWithFloat:[sender floatValue]] retain];

chown33
Oct 15, 2010, 03:50 PM
Thanks! I fixed the problem by changing the line:

numb = [NSNumber numberWithFloat:[sender floatValue]];

to:

numb = [[NSNumber numberWithFloat:[sender floatValue]] retain];

That fixes the crashing problem, but it causes a memory leak. You need to release any existing numb, before assigning it another value. A property with the retain attribute, used as self.numb = ..., would do the retain and release.

And you probably want to review the Memory Management Guide, unless you've already done so recently:
http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html

Finally, if you're not following a gradual tutorial or a book, you probably should be, now that you've done a simple example. The reason is that there's a lot of fundamental stuff that you simply can't learn by brute force trial and error, because you'll never figure out what causes the error. A book will introduce and explain this stuff, and give relevant exercises.

bahlquist
Oct 15, 2010, 10:45 PM
That fixes the crashing problem, but it causes a memory leak. You need to release any existing numb, before assigning it another value. A property with the retain attribute, used as self.numb = ..., would do the retain and release.

And you probably want to review the Memory Management Guide, unless you've already done so recently:
http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html

Finally, if you're not following a gradual tutorial or a book, you probably should be, now that you've done a simple example. The reason is that there's a lot of fundamental stuff that you simply can't learn by brute force trial and error, because you'll never figure out what causes the error. A book will introduce and explain this stuff, and give relevant exercises.

Your right, I neglected to release the memory. Since we're on the topic, what are the consequences of a memory leak? Is that location in memory just tied up until I shut down my computer? Or does worse happen?

I am going through a book and have ordered another. :)

Toreddo
Oct 16, 2010, 05:10 AM
Your right, I neglected to release the memory. Since we're on the topic, what are the consequences of a memory leak? Is that location in memory just tied up until I shut down my computer? Or does worse happen?

I am going through a book and have ordered another. :)

The os shuts down your app and releases it.