Fast Enumeration skips on first run


#1

So this is a weird error I’ve seen a couple times now. When using fast enumeration to print items in array with NSLog, the first time I tell XCode to run my program, it skips everything after the first two items in the array. I’ve included screenshots so hopefully we can verify I am actually not using XCode wrong. I’m using Command-R to run the program, and all I need to do to resolve the error is hit Command-R a second time… I’m not touching the mouse or anything between runs.

First run:

Second run:


#2

It is hard to tell from the screen shots, but I am guessing that you have a nil in your array before the terminating nil.

Take a look at the following code fragment and the output it emits:

[code] NSLog (@“Small primes:”);
NSArray *primes = [NSArray arrayWithObjects:@“2”, @“3”, @“5”, @“7”, @“11”, @“13”, @“17”, @“19”, nil];
for (NSString *prime in primes)
{
NSLog (@“Prime = %@”, prime);
}

NSLog (@"Small primes again (there is a nil after 7):");
primes = [NSArray arrayWithObjects:@"2", @"3", @"5", @"7", nil, @"11", @"13", @"17", @"19", nil];
for (NSString *prime in primes)
{
    NSLog (@"Prime = %@", prime);
}

2012-05-07 15:15:30.820 TripleJ[15657:707] Small primes:
2012-05-07 15:15:30.821 TripleJ[15657:707] Prime = 2
2012-05-07 15:15:30.821 TripleJ[15657:707] Prime = 3
2012-05-07 15:15:30.821 TripleJ[15657:707] Prime = 5
2012-05-07 15:15:30.822 TripleJ[15657:707] Prime = 7
2012-05-07 15:15:30.822 TripleJ[15657:707] Prime = 11
2012-05-07 15:15:30.822 TripleJ[15657:707] Prime = 13
2012-05-07 15:15:30.823 TripleJ[15657:707] Prime = 17
2012-05-07 15:15:30.824 TripleJ[15657:707] Prime = 19
2012-05-07 15:15:30.824 TripleJ[15657:707] Small primes again (there is a nil after 7):
2012-05-07 15:15:30.824 TripleJ[15657:707] Prime = 2
2012-05-07 15:15:30.825 TripleJ[15657:707] Prime = 3
2012-05-07 15:15:30.825 TripleJ[15657:707] Prime = 5
2012-05-07 15:15:30.826 TripleJ[15657:707] Prime = 7
[/code]


#3

Well, I know I didn’t post the code that caused this problem, but the thing is, this only happened the first time I ran the program, not every time. That’s what my screenshots are meant to illustrate. No code was changed, but the program ran differently the second time and every time thereafter. Here is the code from main.m for clarity:

[code]#import <Foundation/Foundation.h>
#import “StockHolding.h”
#import “ForeignStockHolding.h”

int main(int argc, const char * argv[])
{

@autoreleasepool {
    
    // Create StockHolding objects and set instance variables
    StockHolding *firstStock = [[StockHolding alloc] init];
    [firstStock setPurchaseSharePrice:8.0];
    [firstStock setNumberofShares:17];
    [firstStock setCurrentSharePrice:600.0];
    
    StockHolding *secondStock = [[StockHolding alloc] init];
    [secondStock setPurchaseSharePrice:75.0];
    [secondStock setNumberofShares:17];
    [secondStock setCurrentSharePrice:600.0];
    
    StockHolding *thirdStock = [[StockHolding alloc] init];
    [thirdStock setPurchaseSharePrice:110.0];
    [thirdStock setNumberofShares:500];
    [thirdStock setCurrentSharePrice:600.0];
    
    // Create ForeignStockHolding objects and set instance variables
    ForeignStockHolding *firstForeignStock = [[ForeignStockHolding alloc] init];
    [firstForeignStock setPurchaseSharePrice:110.0];
    [firstForeignStock setNumberofShares:500];
    [firstForeignStock setCurrentSharePrice:600.0];
    [firstForeignStock setConversionRate:0.1];
    
    ForeignStockHolding *secondForeignStock = [[ForeignStockHolding alloc] init];
    [secondForeignStock setPurchaseSharePrice:110.0];
    [secondForeignStock setNumberofShares:500];
    [secondForeignStock setCurrentSharePrice:600.0];
    [secondForeignStock setConversionRate:1.1];
    
    // Create an array and store StockHoldings in it
    NSArray *stockArray = [NSArray arrayWithObjects:firstStock, secondStock, thirdStock, firstForeignStock, secondForeignStock, nil];
    
    // Step through the array and print the items in it
    for (StockHolding *stock in stockArray) {
        NSLog(@"The cost of a stock was %.2f and the value is %.2f.", [stock costInDollars], [stock valueInDollars]);
    }
}
return 0;

}[/code]


#4

You could try debugging the cause of the problem before escalating it any further in the forum.

To start with, I would put an assert macro after every stock-object creation to see if the object is nil (highly unlikely):

// Create StockHolding objects and set instance variables StockHolding *firstStock = [[StockHolding alloc] init]; assert (firstStock != nil); ...

Also, I would put a sleep just before the scope of “autoreleasepool” ends (it could be that the output from NSLog is not making it to the console for some reason):

[code] …
// Step through the array and print the items in it
for (StockHolding *stock in stockArray) {
NSLog(@“The cost of a stock was %.2f and the value is %.2f.”, [stock costInDollars], [stock valueInDollars]);
}

   NSLog (@"Sleeping for 30 seconds...");
   [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:30]];

}
return 0;

}
[/code]


#5

Good tips folks.

I’d suggest adding the line

as the second-to-last line in your program, just before the final close-curly-brace of your main() function.

Sometimes in very short command-line programs, the program can exit before all of the output has actually made it to the screen. The fflush() function forces the program to flush all pending output to the screen before continuing to the next line (which in our case would be the end of the program).

It’s worth noting that this is not a problem with typical Mac and iOS applications; we typically only encounter output buffer issues in very short command-line programs.


#6

I’m not to sure of the code [super costInDollars] and [super valueInDollars] might that be the problem?

Mitch