Inside a method, I have:
[self makeRequestToServerForVehicles:self.load.loadId successBlock:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
Info *info = mappingResult.array[0];
self.load.bagOne = info.firstArray;
self.load.bagTwo = info.secondArray;
self.load.itemsNeeded = [self itemsFromBagTwo]; <---- App crashes here
- (NSArray *)itemsFromBagTwo{
NSMutableArray *items = [[NSMutableArray alloc] init];
for (Group *group in self.load.bagTwo) {
[items addObjectsFromArray:group.items];
}
return items;
}
When I run this, the app crashes with this error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'setObjectForKey: key cannot be nil'
When I NSLog the array that is returned, it does not come back nil. It comes back with the items that it needs to come back with.
If I do this,
NSArray *items = [self itemsFromBagTwo]; <--- Doesn't crash
I am not sure what is wrong, any help would be greatly appreciated.
The error makes it sound like the compiler is interpreting self.load.itemsNeeded using key value coding instead of getter and setter methods.
Try rewriting your code as
[[self load] setItemsNeeded: [self itemsFromBagTwo] ];
And see what happens. (That code does explicit method calls rather than ambiguous code that might invoke a getter and a setter, might reference items in a struct, or might compile as key-value coding.)
Related
as the title says I'm having an issue with taking objects out of an array, flipping them, and putting them back in. Below is the code I currently have that ends in this error
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI removeObjectsAtIndexes:]: unrecognized selector sent to instance
I was wondering if anyone knew how to fix this? Here's a little more info on how I have it set up:
The object "PEG" is an NSString that displays "-0.6", "4.36"
GlobalSortedArray is an array filled with dictionary containing the PEG object
//Declare variables
NSMutableArray *negArray = [[NSMutableArray alloc]init];
NSMutableIndexSet *index = [[NSMutableIndexSet alloc]init];
int negcount = 0;
NSDictionary *forLoopDict;
for (forLoopDict in globalSortedArray)
{
if ([[forLoopDict objectForKey:#"PEG"] hasPrefix:#"-"])
{
[index addIndex:negcount];
}
negcount++;
}
NSLog(#"%#", negArray);
// Removes objects from main array. This is what seems to be messing up.
[globalSortedArray removeObjectsAtIndexes:index];
// Reverses the array
NSArray* reversedArray = [[negArray reverseObjectEnumerator] allObjects];
// insters them back into the main array
[globalSortedArray insertObjects:negArray atIndexes:0];
You are trying to remove an item from globalSortedArray. It is an NSArray and not mutable.
globalSortedArray as NSmutableArray
NSArray -- > NSMutableArray
I am trying to add an object to an NSMutableArray. Initially I assign some response data to the array, and can display it in a table view. After loading more data, it seems to be crashing when trying to add the new information to my original array.
I am using AFNetworking for this:
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
if(!_myArray){
_myArray = [responseObject objectForKey:#"data"];
}
else{
[_myArray addObject:[responseObject objectForKey:#"data"]];
}
[self.tableView reloadData];
}
The error I am getting is as follows
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException',
reason: '-[__NSCFArray insertObject:atIndex:]: mutating method sent to immutable object'
Can anybody help out with this?
The object you're retrieving from the responseObject dictionary is most likely not an NSMutableArray, but an (immutable) NSArray. You have to create a mutable copy to be able to change it:
//...
if (!_myArray) {
_myArray = [[responseObject objectForKey:#"data"] mutableCopy];
}
//...
It sounds like AFNetworking generates immutable objects. You should call -mutableCopy instead of just assigning the result of -objectForKey: directly.
Also are you really intending to have a bunch of nested arrays? It seems like it would make more sense if you added the contents of the response array, rather than the array itself.
You need to make the copy of your array. After that you have to modify that array using, [NSMutableArray arrayWithArray: ]
Your array is must be mutable array
Use NSMutablearray instead NSArray
- (void)viewDidLoad
{
binding.logXMLInOut = YES; // to get logging to the console.
StationDetailsJsonSvc_getAvailableStations *request = [[StationDetailsJsonSvc_getAvailableStations new] autorelease];
request.userName=#"twinkle";
request.password=#"twinkle";
StationDetailsJsonSoap11BindingResponse *resp = [binding getAvailableStationsUsingParameters:request];
for (id mine in resp.bodyParts)
{
if ([mine isKindOfClass:[StationDetailsJsonSvc_getAvailableStationsResponse class]])
{
resultsring = [mine return_];
NSLog(#"list string is%#",resultsring);
}
}
#pragma mark parsing
SBJsonParser *parserq = [[SBJsonParser alloc] init];
//if successful, i can have a look inside parsedJSON - its worked as an NSdictionary and NSArray
results= [parserq objectWithString:resultsring error:nil];
NSLog(#"print %#",results);
for (status in results)
{
NSLog(#"%# ",[status objectForKey:#"1" ]);
events=[status objectForKey:#"1"];
NSLog(#"get%#",events);
NSLog(#"events%#",events);
}
events=[status objectForKey:#"1"];
NSLog(#"post%#",events);
self.navigationController.navigationBarHidden=YES;
[whethertableview reloadData];
[super viewDidLoad];
}
this is my code am not getting tableview contents if i run my app crashes getting [NSCFString count]:unrecognized selector sent to instance
You should not get count on NSString but on arrays
you should call [yourString length] to check if the string has something.
You are trying to get the count of a string , which is crashing the App
There are various improvements you could make with this code, but I think I see the problem:
As you are not using ARC, you need to retain what you take out of the parser:
So instead of:
events=[status objectForKey:#"1"]
You need to do:
events= [[status objectForKey:#"1"] retain];
Your crash is caused by accessing a variable that has already been released. More than likely it is the events variable.
...and to add to this. events is probably an NSArray which 'count' is being called on. And [status objectForKey:#"1"] is returning a string... there are many possibilities which i'm speculating about. If events is an NSArray, this isn't the way to add objects to the array.. you repeatedly call events=[status objectForKey:#"1"]; in a loop too.
I trying fill array from existing filled array but sometimes get this error:
*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[4830]
Exception caused by this code line:
NSArray *result = [NSArray arrayWithArray:self.testerLog];
testerLog is NSMutableArray and I use it for collect logs from App.
tester logs filled next way:
[self.testerLog addObject:[NSString stringWithFormat:#"%#: %# \n", [NSDate date], logRecord]];
How it could happens? No exception when I add object to testerLog and fail when trying fill array from this filled array?
Edit:
About initializing testerLog. Here is code of testerLog method:
- (NSMutableArray *)testerLog {
if (!_testerLog) {
_testerLog = [NSMutableArray array];
}
return _testerLog;
}
So I think it should be not nil.
UPDATE:
I forget to say that method that add NSString to testerLog may called from several threads;
The getter you posted is not thread safe. To get an equivalent thread safe getter, use the following code instead.
-(NSMutableArray *)testerLog {
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
// If you're not using ARC you most definitely want to retain the array!
// _testerLog = [[NSMutableArray array] retain];
// If you're using ARC you should just assign
_testerLog = [NSMutableArray array];
});
return _testerLog;
}
The dispatch_once call makes sure that whatever code you put into it, it will only be executed once during you app's lifetime (in a thread-safe manner). The static onceToken is what identifies the particular block. In your particular case this is useful because it guarantees that the array is instantiated only once no matter how many threads execute this getter.
NON-ARC ONLY: The retain is because you want the array to survive beyond this method's execution (again, ONLY if you are not using ARC).
Also, if you're not expecting to see a nil value somewhere because it means there was some logic error: use assertions. The following is an example of how to use them:
assert(self.testerLog != nil);
NSArray *result = [NSArray arrayWithArray:self.testerLog];
Make sure you properly initialized your testerLog array. It's nil and that's causing your problem!
addObject may not be throwing an error because you're trying to add a valid NSString to your testerLog array. Try doing an NSLog on self.testerLog immediately after the line where you add the object, and see that it's printing the testerLog array correctly as you would expect.
In my application I have a UITableView and some buttons that the user can click to sort the array to the order based upon some NSDate's or ints. So this is my method to try to sort my UITableView:
- (void)sortStats:(id)sender reloadData:(BOOL)dataBool {
NSSortDescriptor *descriptor = nil;
UIButton *clickedButton = (UIButton*)sender;
if (clickedButton.tag == 1) {
descriptor = [NSSortDescriptor sortDescriptorWithKey:#"Date" ascending:NO];
}
[self.cellArray sortUsingDescriptors:[NSArray arrayWithObject:descriptor]];
[[NSUserDefaults standardUserDefaults] setObject:self.cellArray forKey:#"cellArray"];
if (dataBool) {
[ivstatstableView reloadData];
}
[ivstatstableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:YES];
}
So originally I just had this method without the reloadData parameter because it seemed that reloadData on the UITableView was causing the crash.
This is what the console crash log is:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[__NSPlaceholderArray initWithObjects:count:]: attempt to insert nil object from objects[0]'
Anyway is there any code here that would be causing this crash? I really want to get this functionality working in my app and I know I am close to fixing it but I am just not sure whats causing this issue.
Any ideas?
There is at least one place where this could be happening, and perhaps others. In the code where you get the contents of the user defaults, you don't check for nil. So instead of this:
[self.cellArray addObjectsFromArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"array"]];
you might want to try this:
NSArray *defaultCellArray = [[NSUserDefaults standardUserDefaults] objectForKey:#"array"];
if (defaultCellArray) {
[self.cellArray addObjectsFromArray:defaultCellArray];
}
It is also possible that the initWithObjects call that is failing (according to your error message) is nested within another call, perhaps in this call:
[self.cellArray sortUsingDescriptors:[NSArray arrayWithObject:descriptor]];
If you look at the full call stack it would tell you if this call is making subsequent calls to initWithObjects and possibly passing it a nil. In your case, for example, you would pass in a nil yo the array you are creating if clickedButton.tag has not yet been set to a value of 1 or 2. You might want to add an additional else clause to help diagnose the problem:
if (clickedButton.tag == 1) {
descriptor = [NSSortDescriptor sortDescriptorWithKey:#"Date" ascending:NO];
} else if (clickedButton.tag == 2) {
descriptor = [NSSortDescriptor sortDescriptorWithKey:#"Score" ascending:NO];
} else {
NSLog(#"Unexpected error: Can't determine sort descriptor");
}
This is all pretty complicated, but one thing sticks out:
[[NSUserDefaults standardUserDefaults] setObject:self.cellArray
forKey:#"cellArray"];
I think you should change that to this:
NSArray *array = [NSArray arrayWithArray:self.cellArray];
[[NSUserDefaults standardUserDefaults] setObject:array forKey:#"cellArray"];
Secondly, add asserts() after every place where you think you should have an object, i.e.:
UIButton *theButton = ...
assert(theButton);
You also say that the number of rows is double the cellArray count, guess thats intentional.