how to add nil to nsmutablearray? - iphone

NSArray *array = [[NSArray alloc] initWithObjects:#"ΕΛΤΑ",
#"ΕΛΤΑ COURIER", #"ACS", #"ACS ΕΞΩΤΕΡΙΚΟ",
#"DHL", #"INTERATTICA", #"SPEEDEX",
#"UPS", #"ΓΕΝΙΚΗ ΤΑΧΥΔΡΟΜΙΚΗ", #"ΜΕΤΑΦΟΡΙΚΕΣ ΕΞΩΤΕΡΙΚΟΥ", nil];
This is working because it has nil at the end.
But I add objects like this: addObject:name etc...
So at the end I have to add nil I do this addObhect:nil but when I run the app it still crashes at cellForRowAtIndexPath:
how can I do this work?
Ok, I dont have to add nil
What is the reason that my app crashes then?

If you must add a nil object to a collection, use the NSNull class:
The NSNull class defines a singleton object used to represent null values in collection objects (which don’t allow nil values).
Assuming "array" is of type NSMutableArray:
....
[array addObject:[NSNumber numberWithInt:2];
[array addObject:#"string"];
[array addObject:[NSNull null]];

You don't need to call [addObject:nil]
The nil in initWithObjects: is only there to tell the method where the list ends, because of how C varargs work. When you add objects one-by-one with addObject: you don't need to add a nil.

You can't add nil when you're calling addObject.

If you really want a Null-ish item in your collection, NSNull is there for that.

You need to add NSNull class and the best way to do it is like this:
NSArray *array = #[ #"string", #42, [NSNull null] ];
I personally recommend to use a specific value like 0 instead of null or nil in your design of your code, but sometimes you need to add null.
There is a good explanation from this Apple reference.

nil is used to terminate the array

nil is not an object that you can add to an array: An array cannot contain nil. This is why addObject:nil crashes.

pass your object through this method when adding to array to avoid attempt to insert nil object from objects crashes.
-(id) returnNullIfNil:(id) obj {
return (obj == nil) ? ([NSNull null]) : (obj);
}
[NSNull null] returns an null object which represents nil.

You can't add an object to an NSArray because that class is immutable. You have to use NSMutableArray if you want to change the array after it is created.

Related

Find Existence of Key in NSDictionary

How can we identify the object is available for a particular key. I have tried following:
for(NSDictionary *item in jsonArray){
if([item objectForKey:#"EventDate"])
NSLog([item objectForKey:#"EventDate"]);
}
This is getting crash the code with error:
-[__NSCFString objectForKey:]: unrecognized selector sent to instance 0x6a567b0
I have also find many posts that is showing objectForKey will return nil if a key doesn't exists. Than my question is there is also a method in NSDictionary class that is "setNilValueForKey". How is this possible that we cannot specify the NSDictionary key with nil object and also we have the method to set nil value for object in NSDictionary.
Please Suggest on first and also make me clear on second query.
1) Your jsonArray contains other types of objects than NSDictionaries, including at least one NSString. NSString doesn't respond to objectForKey: so it throws an exception when you try to call it. You'll have to look at the JSON to determine how to proceed with whatever you were doing.
2) There is an NSObject method setNilValueForKey: which is related to key-value coding. This isn't really related to NSDictionary. If you really need to represent nil in your dictionary, set [NSNull null] as the object for your key that represents nil.
Hope this helps!
Not all the objects in your array are dictionaries. You need to check what kind of data you're processing before you work on it. Something like this:
for(NSObject* item in jsonArray) {
if ([item isKindOfClass:[NSDictionary class]]) {
// do dictionary stuff
}
else if ([item isKindOfClass:[NSString class]]) {
// do string stuff
}
}
item is not a NSDictionary its a String. So check your jsonArray it may be contains only strings not dictinaries
Answer to second query
There is a non-nil object called NSNull that is built specifically to represent nils in situations where "plain" nil is not acceptable. If you replace your nils with [NSNull null] object, NSDictionary will take them. You would need to check for NSNull on the way out, though.
Refer more here
Answer to first query
for(id *item in jsonArray)
{
if([item isKindofClass:[NSDictionary class])
{
NSArray *allKeys = [item allKeys];
for(NSString *strKey in allKeys)
{
if([strKey isEqualToString:#"EventDate"])
{
// EventDate key has object
NSLog([item objectForKey:#"EventDate"]);
}
}
}
}

How to create a NSArray of unknown NSStrings?

For example, I have #"John", #"Peter", ..., #"May" and need to construct NSArray:
[#"John", #"Peter", ..., #"May"]
The number of NSString is unknown and is taking from an import text file. As NSArray does not support appending new element, how can I create NSArray?
Thanks
UPDATE, let me rephrase the question. How can I create the dynamic array paremeter required by the follow function call?
[segmentedAttributes attributesWithTitlesArray:[NSArray arrayWithObjects:#"John", #"Peter", #"May", nil]]
You don't.
You misunderstand the library behavior.
It is true that there is a convenience constructor arrayWithObjects: which is used thus:
NSArray* array=[NSArray arrayWithObjects:#"Low", #"Medium", #"High", nil];
But this does not create an array with nil at the end. This nil is just to signify the end of the variable-length argument list. It just creates an NSArray with three elements, not four with the last one nil.
You just need to create an NSArray containing the required elements, and pass it to the library function. For example:
NSMutableArray*array=[NSMutableArray array];
while(...){
... get a string ...
[array addObject: string];
}
SCSegmentedAttributes*attributes=[SCSegmentedAttributes attributesWithSegmentTitlesArray:array];
should work, without adding a nil or [NSNull null].
You can't store nil in a Foundation collection class. Instead, you can use [NSNull null]. Use an NSMutableArray, then when you want to add your 'nil' object, use [NSNull null].
Note that when you want to see if an object is [NSNull null] later on, that method will return the same instance every time, so you can do a direct point equality test, like this:
for (id anObject in myArray) {
if (anObject == [NSNull null]) {
NSLog(#"object is nil");
}
else {
NSLog(#"object is not nil: %#", anObject);
}
}
create mutable array then just use
NSString *myString = [NSString stringWithFormat:#"ur new string"];
[myArray addObject:myString];
you have to add object type to array when adding new abject in mutable array.
hope this will help

NSMutableArray not retaining the value even after setting the property

In my iphone app i have implemented the SearchBar on TableView.
Now the SearchBar Searches the items but the searched items are not shown in the tableview as the NSMutableArray which fills up the table with the search results is not retaining the values.
I have put the screenshot of the code and the NSLog statements for the count of copyListOfItems always return 0 even though the NSLog(#"%#",sTemp); shows the searched items in Console.
I have created the property for the NSMutableArray copyListOfItems and also synthesized it but its count in the Console is always shown as Zero.
Here is the Code:
searchArray = [Food mutableCopy];
for (NSString *sTemp in searchArray)
{
NSLog(#"Value: %#",NSStringFromClass([sTemp class]));
NSRange titleResultsRange = [sTemp rangeOfString:searchText options:NSCaseInsensitiveSearch];
if (titleResultsRange.length > 0)
{
NSLog(#"sTemp is:%#",sTemp);
NSLog(#" is:%#",sTemp);
[copyListOfItems addObject:sTemp];
[copyListOfItems retain];
}
NSLog(#"Copy list count in Search Delegate Method inside For : %d",[copyListOfItems count]);
}
NSLog(#"Copy list count in Search Delegate Method : %d",[copyListOfItems count]);
[searchArray release];
searchArray = nil;
searching = YES;
[self.table reloadData];
de:
What should I do?
Please Help
Please Suggest
Thanks
From what you've said, it sounds as though the copyListOfItems array is never created. Synthesizing the property creates a pair of accessor methods, but doesn't automatically create an instance of NSMutableArray for you.
So somewhere, you'll need to call [[NSMutableArray alloc] init] (or some variant of init...), and assign the result to the instance variable, or call [NSMutableArray array] (or a variant of array...), and pass the result as an argument to the setCopyListOfItems: method.
I can only assume that you're over-releasing the items in the array. It appears that you do not have a good grip on the retain/release concept, since you're over-retaining the NSArray copyListOfItems. You shouldn't be calling -retain on the same object within a loop since you're incrementing a single object's retain count by 1 for each iteration of the loop.
That aside, what does this code output in its NSLog() calls? It doesn't make a lot of sense. Why do you try to take a mutable copy of (what appears to be) a class called Food?
What exactly is "Food"? An objective-C object, or an objective-C class? This should not be compiling at all in my opinion, unless it's just very badly named.
Make sure you always alloc init the NSMutableArray. If you don't do that, all the items you add will just euhm.. disappear. So make sure you do this somewhere:
searchArray = [[NSMutableArray alloc] init];
Oops..!!!! Cleaned my project and build and run again and it has started working.Thanks guys for being so helpful.. :]
where are you creating the copyListOfItems Array?
I guess copyListOfItems is nil. And you are trying to add something to nil array and trying to retain the nil.
Note: whatever the operation you do on the nil will not be affected. Check whether you are creating the copyListOfItems array properly.
And why are you trying to retain the same array after adding each object?

iphone - mutableArray cannot store nil objects

I have a mutable array that is retained and storing several objects. At some point, one object may become nil. When this happens the app will crash, because arrays cannot have nil objects. Imagine something like
[object1, object2, object3, nil];
then, object2 = nil
[object1, nil, object3, nil];
that is not possible because nil is the end of array marker. So, how can I solve that? thanks for any help.
Use [NSNull null] if you have to store an empty placeholder object.
For example:
NSArray * myArray = [NSArray arrayWithObjects:obj1, [NSNull null], obj3, nil];
myArray will contain 3 objects. When you retrieve the object, you can do a simple pointer equality test to see if it's the Null singleton:
id object = [myArray objectAtIndex:anIndex];
if (object == [NSNull null]) {
//it's the null object
} else {
//it's a normal object
}
EDIT (responding to a comment)
#Mike I think you're getting confused with what's actually going on.
If you have:
id obj = ...;
Then obj contains an address. It does not contain an object. As such, if you do NSLog(#"%p", obj), it'll print something like 0x1234567890. When you put obj into the array, it's not copying the object, it's copying the address of the object. So the array actually contains 0x1234567890. Therefore, when you later do: obj = nil;, you're only affecting the pointer outside of the array. The array will still contain 0x1234567890.

iPhone - Registering an Array containing NSNulls with NSUserDefaults

I have the Array defined below.
NSMutableArray *tempMPArray = [NSMutableArray arrayWithCapacity:16];
for (int i=0; i < chapters; i++)
{
[tempMPArray addObject:[NSNull null]];
}
Every time I use it as a one of the objects of a dictionary below to register default values it crashes with EXC_BAD_ACCESS.
[[NSUserDefaults standardUserDefaults] registerDefaults:myDict];
If I replace the objects in the array with any other object NSNumber etc it works fine. What am I doing wrong with my array that NSUserDefaults rejects it ? The stack trace or NSZombie does not give any additional info.
While the solution may be a "work-around" I don't think it answers the underlying question. By providing a dictionary with [NSNull null] values he is providing NSUserDefaults with a valid dictionary. Why is it crashing? Is it something he is doing "wrong" or is it a bug in registerDefaults?
There may be circumstances where it is important to know whether say a user has entered a value (ie there is a valid string) or not entered a value (null) and the method of creating a "valid but empty string" can't determine if the empty string was because the user created a string with no characters or if he had never created a string at all. You may want different logic in these two cases.
I'm in the same boat, I have an NSUserDefault value I want to be [NSNull null] and everything I've read suggests the "right" way to put a null value in a dictionary is with [NSNull null] and my dictionary creates fine. But registerDefaults with this valid dictionary causes a crash. That suggests a bug in the implementation of registerDefaults doesn't it? What is wrong with the following and why does it crash?
NSArray *defaultValues = [NSArray arrayWithObjects:[NSNull null], nil];
NSArray *CurrentKeys = [NSArray arrayWithObjects: #"NullKey", nil];
NSDictionary *resourceDict = [NSDictionary dictionaryWithObjects:defaultValues forKeys:CurrentKeys];
[[NSUserDefaults standardUserDefaults] registerDefaults:resourceDict];
Ultimately, i think the answer is that the userDefaults get written out as a plist and plists don't support NSNull. if that's the case, the documentation for registerDefaults should say that only plist object types are allowed in the dictionary
Here's a better solution!
Define a static after #implementation
NSString *const Null = #"";
Then
NSMutableArray *tempDSArray = [NSMutableArray arrayWithCapacity:16];
for (i=0; i < chapters; i++)
{
[tempDSArray addObject:Null];
}
Everything else should work fine!