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

Discussion in 'Mac Programming' started by bahlquist, Oct 14, 2010.

  1. macrumors member

    Joined:
    Oct 6, 2010
    #1
    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:

    Code:
    #import <Cocoa/Cocoa.h>
    
    @interface BATester : NSObject {
    NSNumber* numb;
    }
    - (IBAction)theButton:(id)sender;
    - (IBAction)theField:(id)sender;
    @end
    BATester.m:

    Code:
    #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.
     
  2. macrumors 68020

    Joined:
    Jul 4, 2002
    Location:
    Muncie, Indiana
    #2
    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.
     
  3. macrumors 6502a

    Joined:
    Feb 18, 2008
    #3
    Edit: never mind. Misread the post.

    How are you putting a value into numb? What is the error message when it crashes?
     
  4. thread starter macrumors member

    Joined:
    Oct 6, 2010
    #4
    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.
     
  5. macrumors 68000

    Sydde

    Joined:
    Aug 17, 2009
    #5
    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.
     
  6. macrumors member

    Joined:
    Jul 18, 2009
    #6
    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.

    Code:
    #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:
    Code:
    #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
     
  7. thread starter macrumors member

    Joined:
    Oct 6, 2010
    #7
    Thanks! I fixed the problem by changing the line:

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

    Code:
    numb = [[NSNumber numberWithFloat:[sender floatValue]] retain];
     
  8. macrumors 603

    Joined:
    Aug 9, 2009
    #8
    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.
     
  9. thread starter macrumors member

    Joined:
    Oct 6, 2010
    #9
    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. :)
     
  10. macrumors member

    Joined:
    Jul 18, 2009
    #10
    The os shuts down your app and releases it.
     

Share This Page