Label Issue

Discussion in 'Mac Programming' started by Blakeasd, Aug 6, 2011.

  1. Blakeasd macrumors 6502a

    Joined:
    Dec 29, 2009
    #1
    I am having a problem setting a label's value. I am detecting the number of moves in a game to in the class of my game piece I use mouseUp: to detect when a move occurs.
    I use this code to calculate a move set a label equal to the move count, but it doesn't work:
    Code:
    -(void)mouseUp:(NSEvent *)theEvent{
    
        movesCount++;
        NSString *movesCountString = [NSString stringWithFormat:@"%i",movesCount];
        [movesLabel setStringValue:movesCountString];
    
    
    }
    
    movesCount is an int
    movesLabel is a NSTextField connected to a label in Interface Builder.
    I tested to see if the int is adding one each time and it is (I used an NSLog to confirm this.)
    Why doesn't my label change to the value of movesCount?
    I get no errors, but the label stays empty.
    Thanks
     
  2. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #2
    Is movesLabel nil?

    BTW NSTextField inherits setIntValue: from NSControl. That might make your code a little simpler.
     
  3. Blakeasd thread starter macrumors 6502a

    Joined:
    Dec 29, 2009
    #3
    I used this to see if it's nil:
    Code:
     NSString *isNill = [NSString stringWithFormat:@"%@",movesLabel];
        NSLog(isNill);
    
    
    I get this:

    (null)

    I know the label is connected in Interface Builder though.
    Thanks
     
  4. jiminaus, Aug 6, 2011
    Last edited: Aug 6, 2011

    jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #4
    The first parameter of NSLog is a format string just like stringWithFormat: so you can do things like:
    Code:
    NSLog(@"%@", movesLabel);
    How exactly have you rigged this up in Interface Builder? I'm particularly wanting to know if the object to which mouseUp: is being sent is that same object as Interface Builder is setting movesLabel.
     
  5. Blakeasd thread starter macrumors 6502a

    Joined:
    Dec 29, 2009
    #5
    I'm not sure what you mean. Here is the .h and .m files I am using.
    .h:
    Code:
    
    
    #import <AppKit/AppKit.h>
    #import <AudioToolbox/AudioToolbox.h>
    
    @interface NormalBlock : NSImageView {
        int movesCount;
        NSPoint lastDragLocation;
        IBOutlet NSTextField *movesLabel;
        SystemSoundID sounds[10];
    
    }
    
    @end
    
    
    .m:
    Code:
    - (void)mouseDown:(NSEvent *)theEvent
    {
        lastDragLocation = [theEvent locationInWindow]; 
    }
    
    -(void)mouseDragged:(NSEvent *)theEvent{
        
        
        NSPoint newDragLocation = [theEvent locationInWindow];
        NSPoint origin = [self frame].origin;
        origin.x += (-lastDragLocation.x + newDragLocation.x);
            [self setFrameOrigin:origin];
        lastDragLocation = newDragLocation;
        
    }
    
    -(void)mouseUp:(NSEvent *)theEvent{
        
        movesCount++;
        NSString *movesCountString = [NSString stringWithFormat:@"%i",movesCount];
        [movesLabel setStringValue:movesCountString];
        NSLog(@"%@", movesLabel);
        
    }
    
    
    
     
  6. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #6
    Did you connect anything in the .xib file to movesLabel?
     
  7. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #7
    Try adding some logging so we can see what's happening during the lives of your NormalBlock objects.

    .h:
    Code:
    #import <AppKit/AppKit.h>
    #import <AudioToolbox/AudioToolbox.h>
    
    @interface NormalBlock : NSImageView {
        int movesCount;
        NSPoint lastDragLocation;
        [COLOR="Silver"][s]IBOutlet NSTextField *movesLabel;[/s][/COLOR]
        [COLOR="Green"]NSTextField *_movesLabel;[/COLOR]
        SystemSoundID sounds[10];
    }
    
    [COLOR="Green"]@property (assign, nonatomic) IBOutlet NSTextField *movesLabel;[/COLOR]
    
    @end
    .m:
    Code:
    [COLOR="Green"]-(id)initWithFrame:(NSRect)aFrameRect
    {
        NSLog(@"%s %p aFrameRect=%@", __PRETTY_FUNCTION__, self, NSStringFromRect(aFrameRect));
        self = [super initWithFrame:aFrameRect];
        if (self) {
        }
        return self;
    }[/COLOR]
    
    [COLOR="Green"]-(void)awakeFromNib
    {
        NSLog(@"%s %p", __PRETTY_FUNCTION__, self);
        [super awakeFromNib];
    }
    [/COLOR]
    
    [COLOR="Green"]-(NSTextField *)movesLabel
    {
        NSLog(@"%s %p", __PRETTY_FUNCTION__, self);
        return _movesLabel;
    }[/COLOR]
    
    [COLOR="Green"]-(void)setMovesLabel:(NSTextField *)aNewLabel
    {
        NSLog(@"%s %p aNewLabel=%@", __PRETTY_FUNCTION__, self, aNewLabel);
        _movesLabel = aNewLabel;
    }[/COLOR]
    
    - (void)mouseDown:(NSEvent *)theEvent
    {
        [COLOR="Green"]NSLog(@"%s %p", __PRETTY_FUNCTION__, self);[/COLOR]
        lastDragLocation = [theEvent locationInWindow]; 
    }
    
    -(void)mouseDragged:(NSEvent *)theEvent{
        [COLOR="Green"]NSLog(@"%s %p", __PRETTY_FUNCTION__, self);[/COLOR]
        NSPoint newDragLocation = [theEvent locationInWindow];
        NSPoint origin = [self frame].origin;
        origin.x += (-lastDragLocation.x + newDragLocation.x);
            [self setFrameOrigin:origin];
        lastDragLocation = newDragLocation;
        
    }
    
    -(void)mouseUp:(NSEvent *)theEvent{
        [COLOR="Green"]NSLog(@"%s %p", __PRETTY_FUNCTION__, self);[/COLOR]
        movesCount++;
        NSString *movesCountString = [NSString stringWithFormat:@"%i",movesCount];
        [[COLOR="Green"]self.[/COLOR]movesLabel setStringValue:movesCountString];
        NSLog(@"%@", [COLOR="Green"]self.[/COLOR]movesLabel);    
    }
    
    Disconnect and re-connect the connection to moveLabel in Interface Builder.

    The aim here is to find out when the initialiser, awakeFromNib, and setMovesLabel are being called and on what instances they are being called.

    These NSLog's will print out the method name and the address of the NormalBlock object. So you should be able to see if your mouse event methods are being called on the same instance as is the Nib setting movesLabel. You should also be able to confirm the movesLabel is in fact being set.

    I know you didn't post the whole code of this class, but you get this idea.
    If you get compiler errors about movesLabel being undefined, don't change it to _movesLabel, this would defeat the purpose of adding the logging accessors, change it to self.movesLabel.
     
  8. Blakeasd thread starter macrumors 6502a

    Joined:
    Dec 29, 2009
    #8
    Here is the output:
    Code:
    2011-08-07 18:09:53.682 Block Escape![4876:707] -[NormalBlock initWithFrame:] 0x1001579c0 aFrameRect={{0, 0}, {0, 0}}
    2011-08-07 18:09:53.689 Block Escape![4876:707] -[NormalBlock setMovesLabel:] 0x1001579c0 aNewLabel=<NSTextField: 0x10014d6f0>
    2011-08-07 18:09:53.702 Block Escape![4876:707] -[NormalBlock awakeFromNib] 0x1001579c0
    2011-08-07 18:09:53.703 Block Escape![4876:707] -[NormalBlock awakeFromNib] 0x10014b660
    2011-08-07 18:09:59.228 Block Escape![4876:707] -[NormalBlock mouseDown:] 0x10014b660
    2011-08-07 18:09:59.417 Block Escape![4876:707] -[NormalBlock mouseDragged:] 0x10014b660
    2011-08-07 18:09:59.433 Block Escape![4876:707] -[NormalBlock mouseDragged:] 0x10014b660
    2011-08-07 18:09:59.450 Block Escape![4876:707] -[NormalBlock mouseDragged:] 0x10014b660
    2011-08-07 18:09:59.467 Block Escape![4876:707] -[NormalBlock mouseDragged:] 0x10014b660
    2011-08-07 18:09:59.483 Block Escape![4876:707] -[NormalBlock mouseDragged:] 0x10014b660
    2011-08-07 18:09:59.499 Block Escape![4876:707] -[NormalBlock mouseDragged:] 0x10014b660
    2011-08-07 18:09:59.516 Block Escape![4876:707] -[NormalBlock mouseDragged:] 0x10014b660
    2011-08-07 18:09:59.549 Block Escape![4876:707] -[NormalBlock mouseUp:] 0x10014b660
    2011-08-07 18:09:59.550 Block Escape![4876:707] -[NormalBlock movesLabel] 0x10014b660
    2011-08-07 18:09:59.565 Block Escape![4876:707] -[NormalBlock movesLabel] 0x10014b660
    2011-08-07 18:09:59.566 Block Escape![4876:707] (null)
    
    
    
    
     
  9. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #9
    Do you notice there are 2 NormalBlock objects here?

    The first instance (0x1001579c0) is being inited, awoken and having moveLabel set.

    Then a second instance (0x10014b660) becomes apparent and it's to this second instance that your mouse events are being sent.
     
  10. Blakeasd thread starter macrumors 6502a

    Joined:
    Dec 29, 2009
  11. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #11
    Because the seconds instance's movedLabel hasn't been set and is nil/null. It's not the instance from the xib that has movedLabel set. It's some other instance.

    Where/why are you seemingly unexpectedly creating a second instance?
     
  12. Blakeasd thread starter macrumors 6502a

    Joined:
    Dec 29, 2009
    #12
    I am not sure what you're talking about. I just what the label to change to the appropriate value.
     
  13. jiminaus, Aug 7, 2011
    Last edited: Aug 7, 2011

    jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #13
    I know you do. But you're going to have to try to figure out where this second instance is coming from. I can't help you from my side of your screen.

    EDIT: Follow up thoughts. Do you have this object in multiple XIB files?
     
  14. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #14
    Computer doesn't care what you what or what you want. You have to do it right. You have two "NormalBlock" objects, one connected to a movelabel, one that isn't. There shouldn't be two of them, and they are there because you do something wrong. Fix that; it will never work if you don't fix that.

    You are trying to fix the systems. You have to find the root cause of your problem and fix that. And jiminaus told you what the root cause is. Your NSLog statement told you what the root cause is.
     
  15. Blakeasd thread starter macrumors 6502a

    Joined:
    Dec 29, 2009
    #15
    Is it possible for it to be a glitch in Xcode? I am looking at Interface Builder right now and I only see one NormalBlock object. I don't see where I created two.
     
  16. TheWatchfulOne macrumors 6502

    TheWatchfulOne

    Joined:
    Jun 19, 2009
    #16
    I'm still pretty inexperienced at this myself, but mind if I take a stab at this? I could be wrong and if I am then I'd like to know why.

    First observations:

    You have an instance variable called "_movesLabel" and a property called "movesLabel" which is just fine.

    However, In the code you showed us, I don't see where you make the property point at the instance variable. (Is that the correct way to say that?)

    Should you maybe have a @synthasize statement like this?

    Code:
    @synthesize(assign, nonatomic) IBOutlet NSTextField *movesLabel = _movesLabel;
    As I said I'm pretty new at this myself (been reading books and studying sample code for over a year and a half, and development of my first app has barely started.)

    Of course it is quite possible there are bugs in Xcode. (I've heard experienced developers mention them.) None-the-less I would trust the skills of Apple's developers more than I trust my own skills.:cool:
     
  17. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #17
    @synthesize isn't necessary because we manually provided the movesLabel and setMovesLabel: methods.



    Occam's razor. It's much more likely to be something wrong with how your XIBs are rigged up or something wrong in your code.

    If we can find which initialiser is being used to initialise this second instance, we might be able to find out why/where/how it's being created. Do you notice that we don't have an initialiser logged for the second instance? That mens it's not being initialised via the NSTextField's designated initialiser (initWithFrame:).

    So let's go through NSTextField's inheritance hierarchy to find all the possible initialisers that could be used. It looks simple, because other than NSTextField's designated initialiser (inherited from NSControl), the only other initialiser is init inherited from NSObject.

    Add this code.
    Code:
    -(id)init
    {
      [NSException raise:"@MYDeliberateException" format:@""];
    }
    
    If this works you should see a log about an unhandled exception together with a stack trace starting at this init method. Post that stack trace.
     
  18. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #18
    FWIW, View Programming Guide : Creating a Custom View
    Initializing View Instances Created in Interface Builder

    View instances that are created in Interface Builder don't call initWithFrame: when their nib files are loaded, which often causes confusion. Remember that Interface Builder archives an object when it saves a nib file, so the view instance will already have been created and initWithFrame: will already have been called.
    suggesting that the logged initWithFrame: is from something not in a nib.

    Here's another question:
    For a custom view instance in a nib, are its IBOutlet objects assigned a value? If so, from what? If not, consider why not... Possibly because a view object inside a nib is not the owner-object, which is presumably the normal target for IBOutlet setting. Why would an IBOutlet of a view inside a nib ever be set?
     
  19. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #19
    Well now I'm utterly confused because if that's the case then the first instance isn't from a nib and the second is, yet it's the first one that's having it's movesLabel set.

     
  20. chown33 macrumors 604

    Joined:
    Aug 9, 2009
    #20
    Yeah. The first one isn't being tracked for mouse events, either. Maybe it's being created programmatically. Or maybe it's not actually on-screen to receive mouse events. Or if it is on-screen, it's not being clicked on.

    The awakeFromNib: timestamps are only 1 ms apart, which suggests a correlation, but it's unclear what the relationship is, either between the objects, or between the objects and the nib.

    If it were my code, I'd throw an exception in initWithFrame: or setMovesLabel: and see what the stack trace shows.
     
  21. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #21
    @Blakeasd PM me your project. You've interested me enough to want to see what the hell you've done here.
     
  22. gnasher729 macrumors P6

    gnasher729

    Joined:
    Nov 25, 2005
    #22
    You don't see it, but the NSLog statements prove that there are two. Have you ever used the debugger? If two NormalBlock objects are created, where would you set a breakpoint to find out? Which method is guaranteed to be called when a NormalBlock object is created?

    You are still acting completely against the first rule of debugging: If it goes wrong, it is your fault. Get that in your mind. The problem is _always_ something you are doing. You are still looking for faults elsewhere; that is just wasting time.

    After reading other posts: Setting a breakpoint in initWithFrame and examining the call stack should solve the riddle.
     
  23. Blakeasd thread starter macrumors 6502a

    Joined:
    Dec 29, 2009
    #23
    I went ahead and uploaded the project here:
    http://cl.ly/2M102f0M3F120q1n3O1a
    if you want to download it and look at it. Hopefully someone can figure out! I have no idea how I created two objects.
    Anyway, Thanks Everyone!
    ;)
     
  24. jiminaus macrumors 65816

    jiminaus

    Joined:
    Dec 16, 2010
    Location:
    Sydney
    #24
    You do in fact have 2 NormalBlock objects in MainMenu.xib.

    The first one in the one added as a subview (highlighted in grey below). It's the one on the window.

    The second one is the one added as a top-level custom object (highlight in red below).
     

    Attached Files:

  25. PatrickCocoa macrumors 6502a

    Joined:
    Dec 2, 2008
    #25
    Facinating

    I've avoided chiming in so far, because it seemed to me after reading the first post that OP had created an extra object in IB but was not at a skill level to find it. Since I didn't have the .xib in front of me, I was unable to contribute.

    But that raises an issue - how to communicate with other developers about objects in .xib? It's straightforward to cut and paste code:
    Code:
    /* here's my beautiful code
    NSString *myBeautifulString;
    But how to show someone else what's in the .xib and how it's hooked up?
     

Share This Page