Edu
Edu

Reputation: 25

NSArray with objects that "might" be nil

I have 3 objects that might be or not initialized in a random order.

so, if objects "objectOne, "objectTwo", "objectThree" are initialized in this order with

myArray  = [NSArray arrayWithObjects:objectOne,objectTwo,objectThree nil];

all objects get inside the array without problem but in my case objectOne, objectTwo might be nil and objectThree might not be nil, and in this case I would like myArray to return(count) 1.

if objectOne is nil but objectTwo and objectThree are not nil I want my array to return(count) 2.

In these 2 last cases my array always return nil. What would be the best approach to this?

Upvotes: 0

Views: 1787

Answers (3)

dgatwood
dgatwood

Reputation: 10417

If you're doing this rarely and you aren't trying to make things neat, you can, of course, use a mutable array and either add or don't add the items one at a time in code, depending on whether they are nil.

If you're doing this frequently and you want a syntax that looks similar to the array literal notation, you can take advantage of the C preprocessor and C arrays to create a smarter NSArray class constructor that handles nil:

#define NSArrayWithCArray(array) \
    [NSArray arrayWithCArray:cArray count:sizeof(cArray) / sizeof(cArray[0])];

id cArray[] = {
    object1,
    object2,
    object3,
    ...
};
NSArray *array = NSArrayWithCArray(cArray);

and then define a method on NSObject that walks through the C array programmatically, dropping any nil values.

+ (NSArray *)arrayWithCArray:(__strong id[])cArray count:(NSUInteger)count {
  NSMutableArray *array = [NSMutableArray arrayWithCapacity:count];
  for (__strong id *item = cArray; item < cArray + count; item++) {
    if (*item != nil) {
      [array addObject:*item];
    }
  }
  return array;
}

Note: The code above is untested, but at least close enough to give you an idea of how to do it. :-)

Upvotes: 0

Duncan C
Duncan C

Reputation: 131436

arrays can't contain nil. There is a special object, NSNull ([NSNull null]), that serves as a placeholder for nil. You can put NSNull in an array, but I don't think that solves your problem either.

How about this:

Create an empty mutable array.

In 3 separate statements:

If objectOne is not nil, add it to the array

if objectTwo is not nil, add it to the array

If objectThree is not nil, add it to the array.

If you need your objects to be in random order, scramble the array afterwords:

for (int index = 0; index < array.count; index++)
{ 
  int randomIndex = arc4random_uniform()
  [array exchangeObjectAtIndex: index withObjectAtIndex: randomIndex];
}

This is known as a Fisher–Yates shuffle. (or a minor variation on Fisher-Yates, anyway.)

Upvotes: 2

Bryan Chen
Bryan Chen

Reputation: 46598

There are no magic method can solve the problem for you, you need to build the array from NSMutableArray

NSMutableArray *array = [NSMutableArray array];
if (objectOne) [array addObject:objectOne];
if (objectTwo) [array addObject:objectTwo];
if (objectThree) [array addObject:objectThree];

Upvotes: 5

Related Questions