0

I have this snipped of code that results in an array with a whole bunch of "<null>" throughout and I need to figure out how to remove them. Obviously after smashing my head against the keyboard I'm asking for some help.

In my .h I have declared:

NSArray *sortedContacts;
NSArray *rawContacts;

And then in .m:

-(void) buildContacts {   
    ABAddressBook *addressBook = [ABAddressBook sharedAddressBook];
    NSArray *contacts = [addressBook people];
    rawContacts=contacts;

    NSArray *firstNames = [rawContacts valueForKey:@"First"];
    NSArray *lastNames = [rawContacts valueForKey:@"Last"];
    NSArray *organization = [rawContacts valueForKey:@"Organization"];

    NSMutableArray *fullNames = [NSMutableArray array];
    for(int i = 0; i < [firstNames count]; i++)
    {
        NSString *fullName = [NSString stringWithFormat:@"%@ %@ %@",
                               [firstNames objectAtIndex:i],
                               [lastNames objectAtIndex:i],
                               [organization objectAtIndex:i]];
        [fullNames addObject:fullName];
    }

    NSMutableArray *fullList = [[NSMutableArray alloc]initWithArray:fullNames];

    [fullList removeObjectIdenticalTo: @"<null>"];

    sortedContacts = [fullList sortedArrayUsingSelector:@selector(compare:)];

    NSLog(@"%@",sortedContacts);
}

I've tried so many things that I just can't see the forest for the trees anymore.

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
julian
  • 157
  • 1
  • 12

3 Answers3

3

The text <null> is how the singleton instance of NSNull describes itself. That is, it's what -[NSNull description] returns.

In turn, these NSNull objects are getting into your firstNames, lastNames, and organization arrays because that's what Key-Value Coding does when you call -valueForKey: on an array and some of the elements return nil when that message is forwarded on to them with the same key. That is, calling [rawContacts valueForKey:@"First"] causes NSArray to call [element valueForKey:@"First"] for each element in rawContacts and to put the result in the array it builds. But, since an array can't contain nil, if one of those elements returns nil from [element valueForKey:@"First"], an NSNull object is added in its place.

Then, you are formatting the string fullName from the corresponding elements of firstNames, lastNames, and organization. You need to check if any of those elements are NSNull using if ([value isKindOfClass:[NSNull class]]) and handling that. For instance, you might just skip that record. Or you might combine the available fields and leave out any unavailable ones.

In any case, none of the elements of fullList will be @"<null>" because formatting values into @"%@ %@ %@" can never result in that string. (It might be @"<null> <null> <null>" or something like that, but never just @"<null>".)

Ken Thomases
  • 88,520
  • 7
  • 116
  • 154
0

A quick look at your code suggests you cannot get any empty strings added to your array, (a) you add elements using:

[fullNames addObject:fullName];

and fullName is created using:

[NSString stringWithFormat:@"%@ %@ %@" ...

so even if the %@'s get replaced by nothing you'll still have 2 spaces...

Maybe this is why all the things you've tried fail, if you're looking for empty strings you won't find them.

(Addendum: Question now says you're looking for @"<null>", you won't get that either for the same reason - there is at least two spaces in your string.)

The simple answer to removing invalid entries in fullNames is not to add them in the first place. You are adding elements in a loop (for), and conditional logic (e.g. if) inside the loop to determine whether you have something valid to add - however you define "something valid" - and only add an item to fullNames if so.

HTH

CRD
  • 52,522
  • 5
  • 70
  • 86
0

I'm not really familiar with the AddressBook framework, however this might be what's causing the confusion:

The values you collect in your arrays firstNames, lastNames and organization can be of type NSString or NSNull. You have to do any null-checking within the for-loop, before the fullName-string is constructed.

Remove this useless line:

[fullList removeObjectIdenticalTo: @"<null>"];

And replace the contents of your for-loop with the following code:

for(int i = 0; i < [firstNames count]; i++)
{
    NSString *firstName = [firstNames objectAtIndex:i];
    NSString *lastName = [lastNames objectAtIndex:i];
    NSString *org = [organization objectAtIndex:i];

    NSMutableArray *namesArray = [NSMutableArray array];

    if ([firstName isKindOfClass:[NSString class]])
        [namesArray addObject:firstName];

    if ([lastName isKindOfClass:[NSString class]])
        [namesArray addObject:lastName];

    if ([org isKindOfClass:[NSString class]])
        [namesArray addObject:org];

    if (namesArray.count > 0)
        [fullNames addObject:[namesArray componentsJoinedByString:@" "]];
}
Toby
  • 181
  • 1
  • 9