Re: Drawing A Mutable String
Well, I feel dumb. Your (Andy's) mention of setNeedsDisplay: caught my eye, and I realized soon after that the button whose method causes invalidStack to be YES never tells the view the redraw. I still don't entirely understand why the text didn't get drawn when the view was subsequently redrawn (because of tabbing through controls, resizing, etc.), but at least it works as intended now. Any insight is still appreciated. Michael S Craig (908) 328 8030 On Mon, Jan 11, 2010 at 4:15 PM, Andy Lee ag...@mac.com wrote: Bizarre. I love bugs like this that it's easy to prove can't possibly be happening. :) The only desperate, farfetched suggestion I have is that somehow you've accidentally created two instances of your GameView, only one of which is visible, and for some reason when invalidStack is true, the correct drawing *is* happening but in the wrong view. I would think this would be obvious if it were the case, but still, what if you add the following line? NSLog(@%@ -- %p, [self className], self); Do you always see the same pointer value printed? As I said, farfetched, but I see that like me, you like to test the most basic assumptions. Also, I assume you aren't calling drawRect: directly, right? Or setNeedsDisplay:NO, or any other dirty rect manipulation? I'd be willing to look at the code, with complete respect for confidentiality, if you're trusting enough to send it to me and at liberty to do so. --Andy On Monday, January 11, 2010, at 12:25PM, Michael Craig mks...@gmail.com wrote: Andy: There's nothing drawing over it. I can move that chunk of code to the end of drawRect: with the same result. Quincy: rightAligned is a paragraph style object that's defined elsewhere in drawRect and used in a few different places. Fritz: All four things you mention are apparently true when I run it through the debugger, so the if statement must be working. What's more, I can see that it's working by inserting a printf inside (or after) the if and seeing the fully appended string there. How is it possible that I can append the value of infoStr, see that new value at the console with printf, then draw it and get the old value? Also, I can appended another string to infoStr after the invalidStack if statement and it gets drawn (always, since it's not in an if), but the string appended in the invalidStack if statement still doesn't get drawn. They both show up in the console when I printf infoStr, but the invalidStack piece in the middle of the string is left out when infoStr is drawn. Gah! Michael S Craig (908) 328 8030 On Thu, Jan 7, 2010 at 4:18 PM, Fritz Anderson fri...@manoverboard.org wrote: On 7 Jan 2010, at 2:29 PM, Michael Craig wrote: if ([theDeck.cardPile count] == 0) { [infoStr appendString: @\n\nThe deck is empty.]; // *2* } if (gameCon.invalidStack) { [infoStr appendString: @\n\nThat's an invalid stack.]; // *1* } [infoStr drawInRect: infoRect withAttributes: infoAtts]; ... If I move the line marked *1* to come after the line marked *2*, then both messages are drawn when the deck is empty, as one would expect. If I move the line marked *1* one line down (so it's outside of the invalidStack if statement and the if is empty), then invalidStack message is drawn at all times, as one would expect. So what is keeping it from drawing the appended text when it happens inside the invalidStack if statement? Like I said above, the if statement itself works fine. I don't understand why you say the if statement works fine. You say it doesn't execute its body when you think its condition is true. That means it doesn't work fine, doesn't it? When you execute this code line-by-line in the debugger, do you see with your own eyes: • gameCon (assuming it is an object pointer) is not nil? • gameCon.invalidStack is non-zero? • Control ever reaches line 1? • infoStr changes content? — F ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/aglee%40mac.com This email sent to ag...@mac.com ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Drawing A Mutable String
Andy: There's nothing drawing over it. I can move that chunk of code to the end of drawRect: with the same result. Quincy: rightAligned is a paragraph style object that's defined elsewhere in drawRect and used in a few different places. Fritz: All four things you mention are apparently true when I run it through the debugger, so the if statement must be working. What's more, I can see that it's working by inserting a printf inside (or after) the if and seeing the fully appended string there. How is it possible that I can append the value of infoStr, see that new value at the console with printf, then draw it and get the old value? Also, I can appended another string to infoStr after the invalidStack if statement and it gets drawn (always, since it's not in an if), but the string appended in the invalidStack if statement still doesn't get drawn. They both show up in the console when I printf infoStr, but the invalidStack piece in the middle of the string is left out when infoStr is drawn. Gah! Michael S Craig (908) 328 8030 On Thu, Jan 7, 2010 at 4:18 PM, Fritz Anderson fri...@manoverboard.orgwrote: On 7 Jan 2010, at 2:29 PM, Michael Craig wrote: if ([theDeck.cardPile count] == 0) { [infoStr appendString: @\n\nThe deck is empty.]; // *2* } if (gameCon.invalidStack) { [infoStr appendString: @\n\nThat's an invalid stack.];// *1* } [infoStr drawInRect: infoRect withAttributes: infoAtts]; ... If I move the line marked *1* to come after the line marked *2*, then both messages are drawn when the deck is empty, as one would expect. If I move the line marked *1* one line down (so it's outside of the invalidStack if statement and the if is empty), then invalidStack message is drawn at all times, as one would expect. So what is keeping it from drawing the appended text when it happens inside the invalidStack if statement? Like I said above, the if statement itself works fine. I don't understand why you say the if statement works fine. You say it doesn't execute its body when you think its condition is true. That means it doesn't work fine, doesn't it? When you execute this code line-by-line in the debugger, do you see with your own eyes: • gameCon (assuming it is an object pointer) is not nil? • gameCon.invalidStack is non-zero? • Control ever reaches line 1? • infoStr changes content? — F ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Drawing A Mutable String
Hi all, This has me completely boggled. I've got a GameController with some BOOL instance variables that it uses to make certain gamestate information available to other objects. I've also got a GameView that looks at those BOOLs and conditionally appends an NSMutableString before it gets drawn. The relevant chunk of drawRect: looks like this: NSRect infoRect = NSMakeRect(hBuff, vBuff, cardSize.width, [self frame].size.height - vBuff * 4); NSDictionary *infoAtts = [NSDictionary dictionaryWithObjectsAndKeys: [NSFont labelFontOfSize: infoFontSize], NSFontAttributeName, rightAligned, NSParagraphStyleAttributeName, nil]; NSNumber *cardsInDeck = [NSNumber numberWithUnsignedInteger: [theDeck.cardPile count]]; NSMutableString *infoStr = [NSMutableString stringWithString: @Cards in deck: ]; [infoStr appendString: [cardsInDeck stringValue]]; if ([theDeck.cardPile count] == 0) { [infoStr appendString: @\n\nThe deck is empty.]; // *2* } if (gameCon.invalidStack) { [infoStr appendString: @\n\nThat's an invalid stack.];// *1* } [infoStr drawInRect: infoRect withAttributes: infoAtts]; The number of cards in the deck is always displayed, and additional text should be drawn if the deck is empty or if gameCon.invalidStack is YES. The empty deck text is drawn as intended, but the invalidStack text is never drawn. However, it IS being appended to infoStr at all the right times (tested by printf'ing the contents of infoStr after the above chunk). If I move the line marked *1* to come after the line marked *2*, then both messages are drawn when the deck is empty, as one would expect. If I move the line marked *1* one line down (so it's outside of the invalidStack if statement and the if is empty), then invalidStack message is drawn at all times, as one would expect. So what is keeping it from drawing the appended text when it happens inside the invalidStack if statement? Like I said above, the if statement itself works fine. Thanks, Mike ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
NSArray as a class variable
Hi folks, I'm building a class Card that represents a playing card in a simulation. I want instances of Card to be initialized with two integers that represent the suit and value. When an instance of Card is queried for its suit or value, it returns an NSString (@Club, @Spade, @4, @King, etc.). So I'd like to have class variables that are NSArrays of NSStrings for suits and values. I declare them in Card.h as follows (I'll just show the suits array, for brevity): #import Cocoa/Cocoa.h static NSArray *suitArray; @interface Card : NSObject { ... They're initialized in Card.m as follows: @implementation Card +(void) initialize { suitArray = [NSArray arrayWithObjects: @Club, @Diamond, @Spade, @Heart, nil]; } ... However, when I try to access suitArray from another of Card's methods, I get an EXC_BAD_ACCESS error in the console. Here's a simplified version of the method (that I've tested and which produces that error): -(void) testIt: (id) sender { NSString *str = [NSString stringWithString: [suitArray objectAtIndex: 2]]; NSLog(@%@, str); } If I declare str as a class variable and set it inside initialize, then I get the desired output from the NSLog call in testIt:. If I declare it as a class variable and set it inside testIt:, as shown above, I still get the error. What's going on here? NSArray's elements have ref. count 1, right? Is this related? Thanks, Michael S Craig ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: NSArray as a class variable
Ah, that makes perfect sense. Thank you! Michael S Craig On Sat, Dec 26, 2009 at 12:12 AM, Dave Keck davek...@gmail.com wrote: Presumably you're not using garbage collection. If that's the case, suitArray is being deallocated because you didn't retain it. Probably time to check out the memory management guidelines: http://developer.apple.com/mac/library/documentation/cocoa/Conceptual/MemoryMgmt/Articles/mmObjectOwnership.html Particularly the bit under Obtaining Objects Using Convenience Methods ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Re: Releasing Objects
Thanks! I've got a better grip on memory management now. By the way, I'm working with GC turned off, for the sake of learning this stuff. My bad for not including that. Michael S Craig ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/mkscrg%40gmail.com This email sent to mks...@gmail.com ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com
Releasing Objects
Hi folks, I'm new to Cocoa but I think I have a passable understanding of Obj-C. I'm learning Cocoa for a part of an undergraduate comp-sci independent project. I'm working through the Cocoa Application Tutorial, found here: http://developer.apple.com/mac/library/documentation/Cocoa/Conceptual/ObjCTutorial/01Introduction/01Introduction.html At the point where the tutorial discusses garbage collection (end of ch. 5), I decided to implement the deallocation of the Converter objects created by ConverterController's convert: method. I want the deallocation to happen inside convert:. To test it, I'm using [converter retainCount], thinking that after the object is deallocated, that call will cause an error. First I tried [converter release], which didn't work. My code for convert: looks like this: -(IBAction) convert: (id) sender { float amount; converter = [[Converter alloc] init]; [converter setSourceCurrencyAmount: [dollarField floatValue]]; [converter setRate: [rateField floatValue]]; amount = [converter convertCurrency]; [rateField selectText: self]; // autorelease ineff. if b4 this line. hmmm. [amountField setFloatValue: amount]; NSLog(@Reference count: %lx, (unsigned long) [converter retainCount]); [converter release]; NSLog(@Reference count: %lx, (unsigned long) [converter retainCount]); } Everything else is the same as is given in the tutorial. The console shows that the reference count of converter is 1 both before and after the release. Why? Next I tried using an autorelease pool inside the convert method. My code for convert: looks like this: -(IBAction) convert: (id) sender { NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; float amount; converter = [[Converter alloc] init]; [converter setSourceCurrencyAmount: [dollarField floatValue]]; [converter setRate: [rateField floatValue]]; amount = [converter convertCurrency]; [amountField setFloatValue: amount]; [rateField selectText: self]; [converter autorelease]; NSLog(@Reference count: %lx, (unsigned long) [converter retainCount]); [pool drain]; NSLog(@Reference count: %lx, (unsigned long) [converter retainCount]); } Once again, everything else is the same. Now it works: and the console shows that the ref count is 1 before the pool drain and then there's an error (EXC_BAD_ACCESS). HOWEVER: If the [converter autorelease] call is moved up so it happens anywhere prior to the [rateField selectText: self] call, it doesn't work. The console now shows a ref count of 1 both before and after the pool drain. Once again, why? If I'm missing some key concept here, just point me in the right direction and I'll go learn it. If it's something more specific, fill me in! Thanks, Michael S Craig ___ Cocoa-dev mailing list (Cocoa-dev@lists.apple.com) Please do not post admin requests or moderator comments to the list. Contact the moderators at cocoa-dev-admins(at)lists.apple.com Help/Unsubscribe/Update your Subscription: http://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com This email sent to arch...@mail-archive.com