Remove null objects from mutable array in objective c - objective-c

I have a mutable array of checked box
NSMutableArray *arrayOfCheckedBox = [NSMutableArray arrayWithObjects:namePropertyString, lastNamePropertyString, companyPropertyString, workEmailPropertyString, personalEmailPropertyString, workPhonePropertyString, cellNumberPropertyString, nil];
[arrayOfCheckedBox removeObjectIdenticalTo:[NSNull null]]; //not working
NSLog(#"array of check box = %#", arrayOfCheckedBox);
If I click on check boxes at index 0, 1 and 4, it will only collect object at indexes 0 and 1 only and will not detect index 4 at all.
I get the values at the selected index in log before getting it in arrayOfCheckedBox. How to get checked values in this case?

The problem is that you're hitting a nil value, so the arrayWithObjects: method thinks you're at the end of the list of objects.
Something like this will work:
NSMutableArray *arrayOfCheckedBox = [NSMutableArray arrayWithCapacity:7];
if (namePropertyString)
[arrayOfCheckedBox addObject:namePropertyString];
if (lastNamePropertyString)
[arrayOfCheckedBox addObject:lastNamePropertyString];

I would suggest storing the check box values in an array of BOOLs.
Wrap them in NSNumbers first and unwrap them to retrieve them.
Wrap to store,
[NSNumber numberWithBool:YES]]
Unwrap to retrieve,
[[your_array objectAtIndex:index] boolValue]

For null values appear to be string literals #"" rather than the NSNull.So use following way to remove null object :
NSLog(#"%d", [arrayOfCheckedBox count]);
NSString *nullString = #"<null>";
[arrayOfCheckedBox removeObject:nullString];
NSLog(#"%d", [arrayOfCheckedBox count]);

Related

removing null from arrays in Object-c

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.
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>".)
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
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:#" "]];
}

Load an element value of an array to another array Xcode Objective-C

Here I am getting the cityName1 with the city names like Piscataway, Iselin, Broklyn etc fetched from the tgpList1 array and I need to put the values into an array called item5.
There are 133 records fetched by the above iteration. The following code stores only the last record's cityName1 and not the entire list of city names though inside the loop.
I tried many ways but I am missing something.
tgpList1 is an array.
tgpDAO is an NSObject with two objects NSString *airportCode and NSString *cityName
NSArray *item5 = [[NSArray alloc]init];
for (int currentIndex=0; currentIndex<[tgpList1 count]; currentIndex++)
{
tgpDAO *tgpTable = (tgpDAO *)[self.tgpList1 objectAtIndex:currentIndex];
NSLog(#"The array values are %#",tgpList1);
NSString *cityName1 = tgpTable.cityName;
item5 =[NSArray arrayWithObjects:cityName1, nil];
}
Use mutable array.
{
NSMutableArray *item5 = [[NSMutableArray alloc]initWithArray:nil];
for (int currentIndex=0; currentIndex<[tgpList1 count]; currentIndex++) {
tgpDAO *tgpTable = (tgpDAO *)[self.tgpList1 objectAtIndex:currentIndex];
NSLog(#"The array values are %#",tgpList1);
NSString *cityName1 = tgpTable.cityName;
[item5 addObject:cityName1];
}
}
Instead of
item5 =[NSArray arrayWithObjects:cityName1, nil];
use
[item5 addObject:cityName1];
There are more ways of achieving that. However, this is the one that is designed for that purpose and the most "readable" from my pont of view.
If you need to clear the contents of item5 before then call
[item5 removeAllObjects];
right before the for loop.
What you were doing: arrayWithObjects allways creates a new array that ist made of the objects that are passed to it as aguments. If you do not use ARC, then you would create some serious memory leak with your code because arrayWithObjects creates and retains an object on every loop and on the next loop all references to the array object, that was just created, are lost without being released. If you do ARC then you do not have to worry about in this case.
NSMutableArray *myCities = [NSMutableArray arrayWithCapacity:2]; // will grow if needed.
for( some loop conditions )
{
NSString* someCity = getCity();
[myCities addObject:someCity];
}
NSLog(#"number of cities in array: %#",[myCities count]);

replaceObjectAtIndex does not seem to be working

working with a basic objective c example here, tried to use replaceObjectAtIndex for an array and it doesn't seem to be working.
my code:
NSMutableArray *myArray=[NSMutableArray array];
[myArray addObject:#"First string"];
[myArray addObject:#"Second string"];
[myArray addObject:#"Third string"];
NSString *newElement=[myArray objectAtIndex:1];
NSLog(#"New object at index 1 BEFORE is %#", newElement);
[myArray replaceObjectAtIndex:1 withObject:#"Hello"];
NSLog(#"New object at index 1 AFTER is %#", newElement);
theoretically the output for newElement should now display "Hello", but it's still displaying "Second String"
output:
2012-05-30 11:21:16.638 cocoa lab[753:403] New object at index 1 BEFORE is Second string
2012-05-30 11:21:16.641 cocoa lab[753:403] New object at index 1 AFTER is Second string
please advise
thank you
You need to get the new value from the array after replacing it
// ...
[myArray replaceObjectAtIndex:1 withObject:#"Hello"];
/* ADD THIS */
newElement=[myArray objectAtIndex:1];
NSLog(#"New object at index 1 AFTER is %#", newElement);
At the moment you fetch the original string, replace the array's object, and print out the original string again.
You need to reset the value of newElement after calling replaceObjectAtIndex:, so add another line before logging the value the second time:
newElement=[myArray objectAtIndex:1];
UPDATE 1
And don't feel bad -- we've all done this to ourselves at one time or another. :-)
UPDATE 2
By the way, a good way to avoid this kind of problem in general is to get in the habit of using separate local variables in these kinds of situations, for example, you could rewrite the code you posted as follows:
NSString *initialValue = [myArray objectAtIndex:1];
NSLog(#"New object at index 1 BEFORE is %#", initialValue);
[myArray replaceObjectAtIndex:1 withObject:#"Hello"];
NSString *newValue = [myArray objectAtIndex:1];
NSLog(#"New object at index 1 AFTER is %#", newValue);

NSMutableArray contains Objects

I have to check whether an NSMutableArray contains an object multiple times (for e.g. the array contains 1,2,3,1,4), I want to know how many times 1 is present in the array. I am aware of containsObject: but how to use it for this kind of check?
NSCountedSet may help as you want to track how many times a duplicate value occurs.
http://developer.apple.com/library/ios/#documentation/Cocoa/Reference/Foundation/Classes/NSCountedSet_Class/Reference/Reference.html#//apple_ref/occ/cl/NSCountedSet
A quick way would be to convert it to an NSSet and then back to an array. NSSets cannot contain duplicates. Alternatively copy the values one by one into a new array using a loop, and each time check that the new array does not contain a copy of the object before adding it.
It depends on your object types, but if they can be used as keys for an NSDictionary, I would create an NSMutableDictionary that points to NSNumber objects containing counts for each object instance. Something like:
NSArray *array = whatever;
NSMutableDictionary *d = [NSMutableDictionary dictionaryWithCapacity:array.count];
for ( id obj in array )
{
NSNumber *number = [d objectForKey:obj];
if ( number == nil )
{
[d setObject:[NSNumber numberWithInt:1] forKey:obj];
}
else
{
[d setObject:[NSNumber numberWithInt:([number intValue]+1) forKey:obj];
}
}
At the end of this code, you are left with an NSDictionary where the keys are your original objects and the values are NSNumbers that contain the number of times that key exists in the original.

initialise an NSArray with an unknown size

Once an Array is initialized, in order to set value of desired position, I am using
[self.appName replaceObjectAtIndex:x withObject:[self.appCell objectAtIndex: 0]];
Problem is that if I initialize appName array without objects, this array keeps empty and I must initialize it using initWithObjects and then works. Problem is that I do not know the size of an array and if I set it like:
NSMutableArray *nameArray = [[ NSMutableArray alloc] initWithObjects:#"test",#"test",#"test",#"test", nil];
self.appName = nameArray;
[nameArray release];
For example, works from 0 to 3 but from position 4 to following ones, after replaceObjectAtIndex, position has a nil value. How to solve it? Thank you
It's a mutable array, you can add objects (to the end) and insert objects (in the middle) as well, whenever you like:
NSMutableArray *nameArray = [[NSMutableArray alloc] init];
[nameArray addObject:#"test"];
[nameArray insertObject:#"another test" atIndex:0];
[nameArray removeObjectAtIndex:1];
You can do this anywhere you have a pointer to the mutable array.
Look at the count methon on NSArray it gives you the number of elements in the array. So check that your index x is less than the count then you can remove the element.