Strange NSZombie occurring

2011-08-07 Thread Scott Steinman
I've got a zombie appearing in the weirdest place in my program.  Here is the 
relevant part of the code, using generic names for the methods:

-(void)setUp;
-(void)start;
-(void)changeWords:(NSTimer*)theTimer;
-(NSArray *)wordsInPhrase:(NSString *)thePhrase;

@property (nonatomic, assign) int numWords;
@property (nonatomic, assign) NSUInt wordChangeInterval;
@property (nonatomic, copy) NSString *phrase;
@property (nonatomic, copy) NSArray *words;
@property (nonatomic, copy) NSTimer *wordChangeTimer;

…

- (id)init
{
   self = [super init];
   if (self) {
   phrase = [[NSString stringWithString:@This is the phrase to display] 
retain]; 
   wordChangeInterval = 0.2;
   }
   return self;
}

-(void)setUp
{
   words = [[self wordsFromPhrase:phrase]] retain];
   [self start];
}

-(NSArray *)wordsInPhrase:(NSString *)thePhrase
{
   NSArray *wordArray;

   [wordArray arrayByAddingObjectsFromArray:[phrase 
componentsSeparatedByString:@ ]];
   numWords = [wordArray count];
   return wordArray;
}

- (void) start
{
   currentWordIndex = 0;
   wordChangeTimer = [[NSTimer 
scheduledTimerWithTimeInterval:wordChangeInterval 
   target:self 
 
selector:@selector(changeWords:) 
 userInfo:nil 
  repeats:YES] retain];
}

- (void)changeWords:(NSTimer*)theTimer
{
   currentWordIndex += 1;
   if (currentWordIndex  numWords)
   currentWordIndex = 0;
   messageLayer.string = [self.words objectAtIndex:currentWordIndex];
}

Now, the strangeness: words exists and is OK in setUpDisplay and startDisplay 
in that it contains the right words from the phrase.  But in changeWords:, 
somehow words is nil.  I'm at a loss to figure out how words could be released 
between start and changeWords:.  I'd appreciate some help.

Thanks.

Scott 
Dr. Scott Steinman
Brought to you by a grant from the Steinman Foundation (Thanks, Mom and Dad!)
Recommended by Major University Studies Over the Leading Brand
drsteinman at comcast dot net

I hope I die peacefully in my sleep like my grandfather. . .not screaming in 
terror like his passengers. -- Deep Thoughts, Jack Handy

___

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: Strange NSZombie occurring

2011-08-07 Thread Keary Suska
On Aug 7, 2011, at 7:10 AM, Scott Steinman wrote:

 I've got a zombie appearing in the weirdest place in my program.  Here is the 
 relevant part of the code, using generic names for the methods:
 

First off, this isn;t a zombie issue. Zombies are objects that haven't died 
though they should have. Also called leaks.

Anyway, have you stepped through the code to make sure your array is being 
constructed properly at all?

 -(NSArray *)wordsInPhrase:(NSString *)thePhrase
 {
   NSArray *wordArray;
 
   [wordArray arrayByAddingObjectsFromArray:[phrase 
 componentsSeparatedByString:@ ]];
   numWords = [wordArray count];
   return wordArray;
 }

 Now, the strangeness: words exists and is OK in setUpDisplay and startDisplay 
 in that it contains the right words from the phrase.  But in changeWords:, 
 somehow words is nil.  I'm at a loss to figure out how words could be 
 released between start and changeWords:.  I'd appreciate some help.

How do you know this? based on your code this statement cannot be the case. 
Debugger is your friend...

Keary Suska
Esoteritech, Inc.
Demystifying technology for your home or business

___

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: Strange NSZombie occurring

2011-08-07 Thread Andy Lee
On Aug 7, 2011, at 9:10 AM, Scott Steinman wrote:
 -(void)setUp
 {
   words = [[self wordsFromPhrase:phrase]] retain];
   [self start];
 }

Is this your exact code? You use wordsFromPhrase: here but the method below is 
wordsInPhrase:.

 -(NSArray *)wordsInPhrase:(NSString *)thePhrase
 {
   NSArray *wordArray;
 
   [wordArray arrayByAddingObjectsFromArray:[phrase 
 componentsSeparatedByString:@ ]];
   numWords = [wordArray count];
   return wordArray;
 }

Some problems with this method:

* You are sending arrayByAddingObjectsFromArray: to an uninitialized variable. 
The fact that you aren't crashing is pure luck.

* You are not assigning the result to anything.

* A design quibble: there's no real reason for the numWords instance variable. 
It's simpler to call [words count] when you need this number, and you don't 
have to worry about keeping two instance variables in sync.

 
 - (void) start
 {
   currentWordIndex = 0;
   wordChangeTimer = [[NSTimer 
 scheduledTimerWithTimeInterval:wordChangeInterval 
   target:self 
 
 selector:@selector(changeWords:) 
 userInfo:nil 
  repeats:YES] retain];
 }
 
 - (void)changeWords:(NSTimer*)theTimer
 {
   currentWordIndex += 1;
   if (currentWordIndex  numWords)
   currentWordIndex = 0;
   messageLayer.string = [self.words objectAtIndex:currentWordIndex];
 }

This should be

  if (currentWordIndex = numWords)

And again, there's no reason not to say:

  if (currentWordIndex  [words count])

 Now, the strangeness: words exists and is OK in setUpDisplay and startDisplay 
 in that it contains the right words from the phrase.  But in changeWords:, 
 somehow words is nil.

To echo Keary: how do you know? It helps to know how you are diagnosing the 
problem.

--Andy

___

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: Strange NSZombie occurring

2011-08-07 Thread Andy Lee

On Aug 7, 2011, at 10:25 AM, Andy Lee wrote:

 On Aug 7, 2011, at 9:10 AM, Scott Steinman wrote:
 -(void)setUp
 {
  words = [[self wordsFromPhrase:phrase]] retain];
  [self start];
 }
 
 Is this your exact code? You use wordsFromPhrase: here but the method below 
 is wordsInPhrase:.
 
 -(NSArray *)wordsInPhrase:(NSString *)thePhrase
 {
  NSArray *wordArray;
 
  [wordArray arrayByAddingObjectsFromArray:[phrase 
 componentsSeparatedByString:@ ]];
  numWords = [wordArray count];
  return wordArray;
 }
 
 Some problems with this method:

Another thing: you are ignoring the argument thePhrase.

--Andy

___

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: Strange NSZombie occurring

2011-08-07 Thread Fritz Anderson
Is this really your code? There are some oddities that make me wonder.

Also, your subject line talks about NSZombie (an instance of a class that gets 
substituted into an object when it is released, if you have NSZombieEnabled 
set), but your complaint is that a property is nil when you don't expect it. 
That has nothing to do with zombies.

Let me annotate your example, as I think the problem might be clearer if the 
code were cleaner:

On 7 Aug 2011, at 8:10 AM, Scott Steinman wrote:

 -(void)setUp;
 -(void)start;
 -(void)changeWords:(NSTimer*)theTimer;
 -(NSArray *)wordsInPhrase:(NSString *)thePhrase;
 @property (nonatomic, assign) int numWords;
 @property (nonatomic, assign) NSUInt wordChangeInterval;

Here's my first reason to believe you haven't provided your real code. There is 
no such thing as an NSUInt. I understand your desire to provide a compact 
example, but we can't help you if it hides your problem. And, getting the 
example to compile and run may point you to your bug.

 @property (nonatomic, copy) NSString *phrase;
 @property (nonatomic, copy) NSArray *words;

Properties: Tell us whether you've backed them explicitly with instance 
variables, or allowed @synthesize to generate instance variables; whether the 
backing ivars have the same name as the properties; and whether you're 
providing getters or setters for any of them.

Given that we're not seeing your actual code, I don't know whether you're 
assigning nil to -words or .words somewhere. Try overriding 

-(void) setWords: (NSArray *) newWords
{
if (newWords != words) {
[words release];
words = [newWords copy];
}
}

and setting a breakpoint at the beginning. Extra points for conditioning the 
breakpoint on newWords == nil. When the breakpoint hits, examine the backtrace. 
It won't catch your overuse of direct access to backing ivars (a major theme of 
this message), but it will be something.

 @property (nonatomic, copy) NSTimer *wordChangeTimer;

NSTimer doesn't implement NSCopying, as copying an NSTimer doesn't make 
sense. If you had actually used the property, the runtime would have caught 
this for you.

 - (id)init
 {
   self = [super init];
   if (self) {
   phrase = [[NSString stringWithString:@This is the phrase to display] 
 retain];

phrase = @This is the phrase to display;//  stringWithString: is almost 
never what you intend.

[@This is the phrase to display copy] is the prudent thing to do, but not 
idiomatic or necessary.

   wordChangeInterval = 0.2;

This was declared as NSUInt, I assume is some sort of integer. The ivar will 
be set to zero.

   }
   return self;
 }
 
 -(void)setUp
 {
   words = [[self wordsFromPhrase:phrase]] retain];

Your brackets are unbalanced.

self.words = [self wordsFromPhrase: self.phrase];

1. You've got a property. Use it.

2. You're simulating* the retain attribute, when your property declaration said 
you want copy. This suggests to me that you don't mean it.

* (Simulating in that you're leaking the previous occupant of -words. The 
synthesized accessor would have taken care of that.)

   [self start];

Do you ever want to change .words without doing [self start]? If not, make the 
call to -start inside setWords:. Then self.words = [self wordsFromPhrase: 
self.phrase] can completely replace -setUp. But see:

 }
 
 -(NSArray *)wordsInPhrase:(NSString *)thePhrase
 {

Perchance, do you call this method with any phrase other than self.phrase? If 
not, then you can implement -(NSArray *) words to return [self wordsFromPhrase: 
self.phrase], the property can become readonly, and your worry about self.words 
being nil goes away.

   NSArray *wordArray;
 
   [wordArray arrayByAddingObjectsFromArray:[phrase 
 componentsSeparatedByString:@ ]];

This sentence no verb. wordArray has no initial value, so sending 
arrayByAddingObjectsFromArray: to it should crash most of the time (another 
reason I don't believe you're showing your code). 
arrayByAddingObjectsFromArray: returns an NSArray*, but you're throwing away 
the returned value, and the method itself has no side effects.

And thePhrase isn't used anywhere in the method.

   numWords = [wordArray count];

self.numWords = wordArray.count;// Use the property.

   return wordArray;
 }

I _think_ you mean:

- (NSArray *) wordsInPhrase: (NSString *) thePhrase
{
NSArray *   wordArray = [thePhrase componentsSeparatedByString: @ 
];
self.numWords = wordArray.count;
return wordArray;
}

But I'm _guessing_ you mean:

- (NSArray *) wordsInPhrase
{
NSArray *   wordArray = [self.phrase componentsSeparatedByString: 
@ ];
self.numWords = wordArray.count;
return wordArray;
}

and that you _really_ mean:

@property(nonatomic, readonly) NSUInteger numWords;
@property(nonatomic, readonly) NSArray *words;
@property(nonatomic, retain) NSArray * backingWordsArray;
...
@synthesize backingWordsArray;

- (NSArray *) words
{
if (! 

Re: Strange NSZombie occurring

2011-08-07 Thread Dr. Scott Steinman
Ah. I see some of your points. Very dumb of me.  I'm new to Cocoa, but I did 
program in a number of other languages for 30 years. I apologize for not being 
clear enough.  Pain and nausea tend to mess up the clarity of my thinking.  
Unfortunately, I'm ill most of the time (don't ask about my health. It's too 
depressing).  This also makes it take an extremely long time to get any program 
done.  In the past, I got into the habit of not asking for help, and forcing 
myself to figure out the solution on my own. I don't like to bother other 
people with my problems (besides, learning from my mistakes was the way I 
learned before).  Maybe with Cocoa this is a bad idea.

 Is this your exact code? You use wordsFromPhrase: here but the method below 
 is wordsInPhrase:.

This is a typo.  The same method names are used in my code. I tried to pare 
down the source code to a manageable length for posting my question.  When I 
looked at it afterwards, I didn't notice my own typos.  I always the a long 
time to check for such typos when within Xcode.

To give you a little more background about the context of the code snippets in 
the full program, I'm trying to animate the individual words of the phrase in 
sequence with fading in and out, color changes, etc. I'm using Core Animation 
in conjunction with the NSTimer because I could not find an elegant way to 
create an NSKeyframeAnimation in which each individual word of my phrase 
(displayed  in a CATextLayer) could be swapped in sync with the other 
animatable properties.  Each individual word had to be set before the animation 
started.  My solution was to use the timer's changeWords: method to change the 
words and trigger a one-shot animation on each invocation, with the timer's 
duration slightly longer than the animation's duration.  Yes, I know this is a 
kludge, but it was the only way that I could come up with to solve this 
problem.  I ran it past a few other people and they thought it would work.  Any 
other approaches would be appreciated.

 Another thing: you are ignoring the argument thePhrase.


Right.  In paring down the code for my post, I passed an argument. In my 
working code, I simply use the phrase property within the method.  Sorry about 
making that mistake and confusing the issue.  And, yes, I am declaring ivars 
for all of the properties.

 phrase = @This is the phrase to display;//  stringWithString: is almost 
 never what you intend.

God, was that stupid!  Of course I should have done that!

 Do you ever want to change .words without doing [self start]? If not, make 
 the call to -start inside setWords:. Then self.words = [self wordsFromPhrase: 
 self.phrase] can completely replace -setUp.

Good point.  Within start: I call different methods for each type of animation 
to use, but I never change the words without calling [self start]. This would 
be a good place to move that call.  I had not refactored my code yet.

  NSArray *wordArray;
  [wordArray arrayByAddingObjectsFromArray:[phrase 
 componentsSeparatedByString:@ ]];

I did not notice that mistake.  That _should_ crash. Thanks.

 and that you _really_ mean:
 @property(nonatomic, readonly) NSUInteger numWords;
 @property(nonatomic, readonly) NSArray *words;
 @property(nonatomic, retain) NSArray * backingWordsArray;

I thought that properties such as NSString and NSArray needed to be retained or 
copied.  Am I wrong?

  wordChangeTimer = [[NSTimer scheduledTimerWithTimeInterval:wordChangeInterval
 [My customary objection to accessing an ivar directly.]

I tried both wordChangeTimer and self.wordChangeTimer when I was testing the 
program. Both worked, so I left it as is.

 self.wordChangeTimer = [NSTimer ... repeats: YES];
 If you let the property manage your memory, you won't have to do it yourself. 
 And if you have a setter method, you can invalidate the old timer.

Would invalidating within the setter as the NSTimer is assign in the code above 
for the first time cause a problem?
  
 What are setUpDisplay and startDisplay? Are they the same as setUp and start?

Yeah. Another typo. You know, when I took a mandatory typing class in junior 
high school, I was the worst typist in the class.  That's probably why I was 
also a terrible piano player. 

I ran everything through the debugger, and stepped though it.  That's how I 
knew that words had a non-nil value in start and not have it in changeWords:.  
As for Instruments, I find Apple's documentation very unclear.  I've only used 
Instruments on one project before this, and managed to remove a leak.  When I 
ran Instruments on this project, I did not notice a leak. However, since I'm so 
new to Instruments, it's entirely possible that I forgot how to use it properly 
again on this project. ;-)  Is there a good tutorial on using Instruments?  All 
I've seen on-line are descriptions of the tools within Instruments, but not 
clear instructions on how to use them.

 I will take your advice and correct my code. I appreciate your 

Re: Strange NSZombie occurring

2011-08-07 Thread Scott Ribe
On Aug 7, 2011, at 10:51 AM, Dr. Scott Steinman wrote:

 I don't like to bother other people with my problems (besides, learning from 
 my mistakes was the way I learned before).  Maybe with Cocoa this is a bad 
 idea.

Have you seen Hillegass's book on Cocoa. It's an excellent start for Cocoa 
newbies.

 Yes, I know this is a kludge...

I'm not so sure about that; sounds reasonable to me.

-- 
Scott Ribe
scott_r...@elevated-dev.com
http://www.elevated-dev.com/
(303) 722-0567 voice




___

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: Strange NSZombie occurring

2011-08-07 Thread Dr. Scott Steinman
 Have you seen Hillegass's book on Cocoa. It's an excellent start for Cocoa 
 newbies.

I took Aaron's course about 10 years ago, but didn't have a chance to use Cocoa 
since then due to job requirements.  I lost a lot of my books recently in a 
disaster (aren't you all getting tired of knowing how crappy my life is?).  My 
wife insisted on avoiding dead tree books since then, so I only have it in 
eBook form, but it's too difficult to search.  I intend to read both Aaron's 
and Matt Neuberg's iOS books when I'm ready to try an iPad app.

 Yes, I know this is a kludge...
 
 I'm not so sure about that; sounds reasonable to me.

Thanks.  That feedback is reassuring.

Scott
Sent from my iPad





___

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