SRSR333
SRSR333

Reputation: 276

Objective-C method with variable arguments - first argument skipped?

I'm following Stephen Kochan's Programming in Objective-C, 6th edition, and I'd like some help with this particular method. Basically I have a class, AddressBook, that has two instance variables: an NSMutableArray called book, and an NSString called bookName. Quite self-explanatory.

book holds AddressCards, and I was trying to implement a method that takes multiple variables of type id and adds all of them to the array book. Here it is:

-(void) addCards:(id)firstCard, ... NS_REQUIRES_NIL_TERMINATION
{
    va_list argumentList;
    va_start(argumentList, firstCard);

    id theArgument = firstCard;
    while ((theArgument = va_arg(argumentList, id)))
    {
        [self addCard:theArgument];
    }
    va_end(argumentList);
}

The addCard method is a customised implementation of NSMutableArray's addObject method. Problem is, the first argument that I provide to addCards isn't added to book. Here is main.m and the accompanying output:

int main(int argc, const char * argv[])
{
    @autoreleasepool
    {
        AddressCard *card1 = [[AddressCard alloc] initWithName:@"Joseph Brown" andEmail:@"[email protected]"];
        AddressCard *card2 = [[AddressCard alloc] initWithName:@"Thomas Walter" andEmail:@"[email protected]"];
        AddressCard *card3 = [[AddressCard alloc] initWithName:@"Jonathan Green" andEmail:@"[email protected]"];
        AddressCard *card4 = [[AddressCard alloc] initWithName:@"Elizabeth White" andEmail:@"[email protected]"];

        AddressBook *myBook = [[AddressBook alloc] initWithName:@"My Address Book"];

        [myBook addCards:card1, card2, card3, card4, nil];

        NSLog(@"Lookup: Joseph Brown");

        if ([myBook lookup:@"joseph Brown"] == nil)
        {                                   
            NSLog(@"Not Found!");
        }

        else
        {                                   
            [[myBook lookup:@"Joseph Brown"] print];
        }
        [myBook list];
    }
    return 0;
}

Output:

2014-06-25 11:43:25.997 AddressBook[19454:303] Lookup: Joseph Brown
2014-06-25 11:43:25.999 AddressBook[19454:303] Not Found!
2014-06-25 11:43:25.999 AddressBook[19454:303] ======== Contents of My Address Book ========
2014-06-25 11:43:26.000 AddressBook[19454:303] Thomas Walter           [email protected]              
2014-06-25 11:43:26.000 AddressBook[19454:303] Jonathan Green          [email protected]             
2014-06-25 11:43:26.000 AddressBook[19454:303] Elizabeth White         [email protected]              
2014-06-25 11:43:26.001 AddressBook[19454:303] =============================================
Program ended with exit code: 0

lookup does exactly that: looks up the AddressCard specified by the argument to it; print prints the AddressCard in a nice format; list also does its namesake: list the contents of book. Now, as can be seen in the output, Joseph Brown, although added to the AddressBook as card1, isn't actually added, as proved twice by the output. What's wrong?

Upvotes: 0

Views: 100

Answers (2)

CrimsonChris
CrimsonChris

Reputation: 4651

Alternative solution using an NSArray...

AddressCard *card1 = [[AddressCard alloc] initWithName:@"Joseph Brown" andEmail:@"[email protected]"];
AddressCard *card2 = [[AddressCard alloc] initWithName:@"Thomas Walter" andEmail:@"[email protected]"];
AddressCard *card3 = [[AddressCard alloc] initWithName:@"Jonathan Green" andEmail:@"[email protected]"];
AddressCard *card4 = [[AddressCard alloc] initWithName:@"Elizabeth White" andEmail:@"[email protected]"];

AddressBook *myBook = [[AddressBook alloc] initWithName:@"My Address Book"];
[myBook addCards:@[card1, card2, card3, card4]];

-(void)addCards:(NSArray *)cards {
    for (AddressCard *card in cards) {
        [self addCard:card];
    }
}

Upvotes: 1

Bryan Chen
Bryan Chen

Reputation: 46608

In your code

id theArgument = firstCard;
while ((theArgument = va_arg(argumentList, id)))

you did not do anything with firstCard. second argument overrides it

-(void) addCards:(id)firstCard, ... NS_REQUIRES_NIL_TERMINATION
{
    va_list argumentList;
    va_start(argumentList, firstCard);

    id theArgument = firstCard;
    while (theArgument)
    {
        [self addCard:theArgument];
        theArgument = va_arg(argumentList, id);
    }
    va_end(argumentList);
}

Upvotes: 1

Related Questions