简体   繁体   中英

what exactly constitutes a conditional statement in Objective C?

I've been reading the book Learn Objective C on the Mac, and I was looking at this bit of sample code:

#import <Foundation/Foundation.h>

int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];

    NSFileManager *manager;
    manager = [NSFileManager defaultManager];

    NSString *home;
    home = [@"~" stringByExpandingTildeInPath];

    NSDirectoryEnumerator *direnum;
    direnum = [manager enumeratorAtPath: home];

    NSMutableArray *files;
    files = [NSMutableArray arrayWithCapacity: 42];

    // “Slow” enumeration
    NSString *filename;
    while ( filename = [direnum nextObject] )
    {
            if ([[filename pathExtension] isEqualTo: @”jpg”])
            {
                    [files addObject: filename];
            } // end if
    } // end while


    NSEnumerator *filenum;
    filenum = [files objectEnumerator];

    while ( filename = [filenum nextObject] )
    {
            NSLog(@”%@”, filename);
    }

[pool drain];
return 0;
} // main

what stood out for me was while ( filename = [filenum nextObject] ) and I thought, 'how this is actually a conditional statement?' I suppose a call to [filenum nextObject] is an NSString with a filename, or nil , but how do we get to execute filename = while we are evaluating that? can you point me to the correct documentation that would explain more clearly just what is possible here?

This is actually a feature of C. The while statement takes an expression like an if statement and an assignment is a valid expression. In this C grammar file you can see the following is valid

IF '(' expression ')' statement

and also

WHILE '(' expression ')' statement

As long as the result from the expression is non zero the condition will be true. A nil value is 0 and will cause the condition to fail. Once the enumerator is done nextObject will return nil and the condition will fail. It is however recommended when doing an assignment as a conditional expression you should surround it with parentheses to state your intentions.

while ( (filename = [direnum nextObject]) )

This is a conditional statement since every assignation has a value, which is the value on the right hand side assigned to the var on the left. In this case, the final value turns out to be, either a valid NSString object, or nil. As long as nil represents "nothing", the condition is interpreted as false, otherwise it's true.

while ( filename = [filenum nextObject] )

This statement is complex and performs multiple operations.

  1. [filenum nextObject] method is called and returns an NSString
  2. filename = gets assigned the address of the NSString
  3. the value of filename is evaluated as a condition for the while (... ) operation

As you pointed out if the returned value is nil then filename equals nil and the condition evaluates to false else filename is non-zero and the condition evaluates to true.

Many programers don't like this kind of syntax. It is terse and can be difficult to maintain. Compilers will generate a warning, to flag a common syntax error for when the developer actually intend to compare the two values,

while ( filename == [filenum nextObject] )

It would be cleaner to write the original statement as

while ( (filename = [filenum nextObject]) != nil )

This statement will behave the same as the original but eliminates the ambiguity of the assignment and the conditional operations.

You have raised a good question. Consider the code

while ( obj = [enumerator nextObject] ) {
    printf( "%s\n", [[obj description] cString] );
}

The reason why while ( obj = [array objectEnumerator] ) works is because objectEnumerator returns nil on the last object. Since in C nil is usually 0, this is the same as false. ( ( obj = [array objectEnumerator] ) != nil ) might be preferable

Source: Click This Link !

In your case, ((filename = [direnum nextObject]) ) is another way of doing this to avoid compiler errors.

The expression

(file = [filenum nextObject])

Will be executed each time through the loop. After it is excecuted it is then evaluated as the Boolean condition for the if statement

It's the same as a normal statement like

x = 13 * 4;

Everything to the right of the equals is executed and then it is assigned to the variable x.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM