NSArray initWithObjects only initializing with some of the objects - objective-c

I've encountered a weird issue thats causing me quite the headache. I am initializing an NSArray object using initWithObjects. I'm passing in 7 objects but immediately afterwords, if I log the count of the array, I only have a count of 3. Has anyone else seen this? I've used this method countless times with no problem before and I can't see what I'm doing wrong. The code is below:
-(DMORecipe *) saveRecipe:(NSNumber *)recipeID recipeTitle:(NSString *)title recipeDescription:(NSString *)description pictureFile:(NSString *)picFile preparationTime:(NSString *)prepTime cookingTime:(NSString *)cookTime ovenTemperature:(NSString *)ovenTemp {
NSArray *newRow = [[NSArray alloc] initWithObjects:recipeID,title, description, picFile, prepTime, cookTime, ovenTemp, nil];
NSLog(#"Before update, the number of args is %i", [newRow count]);
}
Do I have a type-o somewhere that I'm missing? You can see I'm passing in 7 objects to the array initializer but the NSLog method shows [newRow count] = 3.

If any of the object passed in is nil, the rest of the argument will be ignored.
In this case, it seems that picFile is nil.

Related

Adding and getting values of NSMutableDictionary not working [duplicate]

This question already has an answer here:
NSMutableDictionary setObject:forKey: fails to add key
(1 answer)
Closed 8 years ago.
I'm trying to do some complex stuff, but when I add to an nsmutabledictionary and try to get values from it, it's simply returning nothing and not printing anything when I try to print what it returns. I can't even get the following to print anything in an ibaction, even though the action is being triggered. Could you like me know if I'm doing anything wrong and what it is? Thanks!
Sample code of super simplified version of what I'm doing:
NSMutableDictionary *test;
[test setObject:#"ValueIWantToGet" forKey:#"KeyIAmSetting"];
NSLog([test objectForKey:#"KeyIAmSetting"]); //Should print "ValueIWantToGet", right?
Your test variable is not initialized. Do this instead:
NSMutableDictionary *test = [NSMutableDictionary dictionary];
or
NSMutableDictionary *test = [[NSMutableDictionary alloc] init];
In Objective-C all objects are manipulated through pointers. Hence the asterisks in declarations in front of variable names. When you do not assign anything to a pointer, its value remains uninitialized, so any reference to it is undefined behavior. In situations when the value happens to be nil, however, you would not see a crash, because Objective-C allows sending messages to nil (they have no effect).
I'm making a property of an NSMutableDictionary, so how should I initialized it if it's a property?
Properties should be initialized in the initializer of your class, for example
-(instancetype)init {
if (self = [super init]) {
_test = [NSMutableDictionary dictionary];
}
return self;
}

Objective-C Changing values of instance variables in method

I am write a Objective-C Code on XCode 4.4.
I have a NSMutableArray as a instance variable of my class k_info
I have defined and synthesized (nonatomic,retain) property by the name of onesplaces too.
I am unable to add a NSMUtableString object in the NSMutableArray onesplaces.
When I try to add it.The size of onesplaces remains 0 and object at zero index obviously remains null.
I tried doing this with and without using "self" key-word but it didnt worked in either case.
My syntax of adding object and printing it is right because when I create a new NSMutableArray test
and try to do the same thing it works for it but not for the instance variable onesplaces.
I cannot proceed any further in my project without solving this issue.please tell me why is it
happening and how should I solve this problem.
-(void)createinfo:(NSMutableArray )al varsis:(int)vars
{
NSMutableString stes=[[NSMutableString alloc]init];
stes=(NSMutableString*)#"string0";
[ onesplaces addObject:stes];
NSLog(#"%u",[onesplaces count]);
NSLog(#"value is: %# ",[ onesplaces objectAtIndex:0]);
[ self.onesplaces addObject:stes];
NSLog(#"%u",[onesplaces count]);
NSLog(#"value is: %# ",[self.onesplaces objectAtIndex:0]);
NSMutableArray* test=[[NSMutableArray alloc]init];
[ test addObject:stes];
NSLog(#"%u",[test count]);
NSLog(#"value is: %# ",[test objectAtIndex:0]);
}
You probably forgot to create the array. Somewhere in your code, maybe in your init method, you need to create the array before using it.
self.onesplaces = [[NSMutableArray alloc] init];
You get nil instead of error messages because Objective-C allows you to send messages to nil, which always return nil.

PFUser throwing NSInternalInconsistencyException when calling objectForKey after fetchAllIfNeeded

I have two additional columns on my PFUser "firstName" and "lastName". They are saving properly; I can see the data in the data browser.
I have another PFObject "class" that has a property with a NSArray of PFUsers. I use the class method +fetchAllIfNeededInBackground:block: on PFObject to fetch the array of PFUsers. In the callback block, I call objectForKey: on each of the PFUsers in the array, but I access them through the owning PFObject.
// invited is the NSArray of PFUsers
self.whoCell.mainLabel.text = [[self.plan.invited objectAtIndex:0]
objectForKey:#"firstName"];
Debugger outputs this at a breakpoint right before the objectForKey call:
(lldb) po self.plan.invited
(NSArray *) $4 = 0x06e62a60 <__NSArrayM 0x6e62a60>(
<PFUser:GCCdPjCU2J> {
firstName = Fake;
lastName = Account;
username = yyajnbafv53qw4yhjm9sfoiis;
}
)
Edit: adding implementation of self.plan.invited because the above is misleading.
- (NSArray*)invited
{
// self.dataSource is a PFObject*
return [self.dataSource objectForKey:INVITED_PROP];
}
Yet when the above call it made to objectForKey: this exception is thrown:
'NSInternalInconsistencyException', reason: 'Key "firstName" has no data. Call fetchIfNeeded before getting its value.'
Edit: Accessing the array of fetchedObjects that is passed to the block callback for +fetchAllIfNeededInBackground doesn't throw, but accessing the actual array that was originally passed to +fetchAllIfNeededInBackground throws.
Calling fetchIfNeeded before the call solves the problem, but why? The data is already there. Do I miss understand +fetchAllIfNeededInBackground in that it DOES NOT updated the PFObject that owns to collection of PFUsers?
I figured out what was happening. Let me explain with code:
PFQuery *query = [PFQuery queryWithClassName:#"TestClass"];
PFObject *testObj = [query getObjectWithId:#"xWMyZ4YEGZ"];
// an array of PFUser "pointers" (pointers in Parse parlance)
NSLog(#"%#", [testObj objectForKey:#"userArrayProp"]);
[PFObject fetchAll:[testObj objectForKey:#"userArrayProp"]];
// now userArrayProp contains fully fetched PFObjects
NSLog(#"%#", [testObj objectForKey:#"userArrayProp"]);
For me, after a certain amount of time userArrayProp would revert to an array of "pointers" and this mystified me. My problem was that calling refresh on a PFObject will revert a fetched array BACK to an array of pointers. Like this:
PFQuery *query = [PFQuery queryWithClassName:#"TestClass"];
PFObject *testObj = [query getObjectWithId:#"xWMyZ4YEGZ"];
// an array of PFUser "pointers" (pointers in Parse parlance)
NSLog(#"%#", [testObj objectForKey:#"userArrayProp"]);
[PFObject fetchAll:[testObj objectForKey:#"userArrayProp"]];
// now userArrayProp contains fully fetched PFObjects
NSLog(#"%#", [testObj objectForKey:#"userArrayProp"]);
[testObj refresh];
// now userArrayProp contains pointers again :(
NSLog(#"%#", [testObj objectForKey:#"userArrayProp"]);
Wish it said that [PFObject refresh] did that in the documentation....
What you are describing should work fine. fetchAllIfNeeded updates the objects in the array themselves, so it shouldn't matter how you access them. You say you are accessing them through the parent PFObject, but your debugger output is showing access through the array directly. Is it possible the array isn't pointing to the current PFObject member?
One thing you could try while debugging is calling isDataAvailable on the instances of PFUser, both after the fetchAllIfNeeded, and right before you access their first and last names. After the call to fetchAllIfNeeded, isDataAvailable should return YES for every element of the array. If it still returns YES when you access the names, they should not give this error.
Otherwise, if you can provide a minimal code sample that reproduces the problem, I'd be glad to debug it further.
Thanks,

Objective C - EXC_BAD_ACCESS on [NSArray count] but can't see how

I'm working on a piece of code that GETs a URL and parses the contents for data between a asset of tags. In this case, it's looking for the code between and . When the URL body returned doesn't contain those tags, the cullXML: method returns an empty array like this:
return [NSArray arrayWithObjects: nil];
I check to be sure that the returned array has objects with:
if ( matchesXML.count ) {
In my debug code, I check twice. The first time, it works fine. The second time, just a couple lines later, it crashes. I can't see why. The lines look the same to me.
What am I missing?
A bigger chunk of the code is included below. Thanks!
if (self.newResults) {
NSString *urlResult;
NSArray *matchesXML;
NSArray *match;
NSDictionary *currentResult;
NSMutableDictionary *results = [[NSMutableDictionary alloc] init];
NSArray *returnedObjects;
NSArray *dictionaryKeys;
NSMutableArray *currentResultObjects;
int i = 0;
// determine tournament type, because the fields are different per type
NSString *tournamentType;
tournamentType = [[AFMethods tournamentTypeFromId:self.inputTournamentId] objectAtIndex:0];
urlResult = [NSString stringWithFormat:#"%#", responseHandle];
[responseHandle release];
NSLog(#"urlResult retrieved: %#", urlResult);
matchesXML = [AFMethods cullXML: urlResult forTag: #"matches"];
NSLog(#"matches loaded: %#", matchesXML);
NSLog(#"matchesXML.count %i", matchesXML.count);
if ( matchesXML.count ) {
NSLog(#"not nil");
}
NSLog(#"just before tested");
if ( matchesXML.count ) {
NSLog(#"tested");
I found the issue!
It wasn't crashing where I thought. It was a couple lines later. I was releasing an auto-released object. It must have been a left-over line from a previous organization of the code.
I removed the release and it's working perfectly again.
My guess is that you're not using the return statement you listed, but rather one that returns a different NSArray, only this one isn't retained. The first NSLog causes heap to be used, stomping on the array object.

Is if (variable) the same as if (variable != nil) in Objective-C

I am getting a EXC_BAD_ACCESS (SIGBUS) on this line in my iPhone project:
if (timeoutTimer) [timeoutTimer invalidate];
The thing that has me stumped is that I don't understand how that line could crash, since the if statement is meant to be checking for nil. Am I misunderstanding the way Objective-C works, or do line numbers in crash statements sometime have the wrong line in them?
Just because a variable is set to a value other than nil doesn't mean it's pointing to a valid object. For example:
id object = [[NSObject alloc] init];
[object release];
NSLog(#"%#", object); // Not nil, but a deallocated object,
// meaning a likely crash
Your timer has probably already been gotten rid of (or possibly hasn't been created at all?) but the variable wasn't set to nil.
I just ran into a similar issue, so here's another example of what might cause a check such as yours to fail.
In my case, I was getting the value from a dictionary like this:
NSString *text = [dict objectForKey:#"text"];
Later on, I was using the variable like this:
if (text) {
// do something with "text"
}
This resulted in a EXC_BAD_ACCESS error and program crash.
The problem was that my dictionary used NSNull values in cases where an object had an empty value (it had been deserialized from JSON), since NSDictionary cannot hold nil values. I ended up working around it like this:
NSString *text = [dict objectForKey:#"text"];
if ([[NSNull null] isEqual:text]) {
text = nil;
}
They should be the same. Perhaps the line number is in fact incorrect.
Look for other possible errors near that in your code and see if you find anything.