The problem is that I am mutating a NSDictionary, but even after getting a mutableCopy, the app crashes.
Below is Method for copy :
+ (NSMutableDictionary *)updateQuery:(NSMutableDictionary *)currentQuery toSearchAfterAccountPaginationSequence:(NSString *)accountPaginationSequence {
//try1
NSMutableDictionary *mutableQuery = [currentQuery mutableCopy];
//try2
NSMutableDictionary *mutableQuery2=[NSMutableDictionary dictionaryWithDictionary:currentQuery];
//crashes on this line
mutableQuery[#"where"][#"account_pagination_sequence"] = #{ #"lt" : accountPaginationSequence };
return mutableQuery;
}
Error Log (the app crashes on a limited amount of devices)
[__NSDictionaryI setObject:forKey:]: unrecognized selector sent to instance
i think this is what you trying to achieve
+ (NSMutableDictionary *)updateQuery:(NSMutableDictionary *)currentQuery toSearchAfterAccountPaginationSequence:(NSString *)accountPaginationSequence {
//try1
NSMutableDictionary *mutableQuery = currentQuery.mutableCopy;
NSMutableDictionary *where = mutableQuery[#"where"].mutableCopy;
where[#"account_pagination_sequence"] = #{ #"lt" : accountPaginationSequence };
mutableQuery[#"where"] = where;
return mutableQuery;
}
Edit:
In Objective-C calling mutableCopy on objects is not recursive.You need to call mutableCopy in nested objects too.
Related
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
[jsonArray removeAllObjects];
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
responseData = nil;
NSMutableArray *sdf = [(NSDictionary*)[responseString JSONValue] objectForKey:#"DataTable"];
NSMutableArray * myArray = [[NSMutableArray alloc] init];
NSMutableDictionary * myDict = [[NSMutableDictionary alloc] init];
if (([(NSString*)sdf isEqual: [NSNull null]])) {
// Showing AlertView Here
}else {
for (int i=0; i<[sdf count]; i++) {
myDict=[sdf objectAtIndex:i];
[myArray addObject:[myDict objectForKey:#"RxnCustomerProfile"]];
}
jsonArray=[myArray mutableCopy];
NSMutableDictionary *dict=[jsonArray objectAtIndex:0];
if ([dict count]>1) {
// Showing AlertView Here
}
}
}
Hi Everyone, I have an issue regarding the -[__NSArrayM objectForKey:]: .
Tried to solve but did not get the better solution for it. Please help me to
find the solution. Thanks In Advance
Below is the issues
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM objectForKey:]: unrecognized selector sent to instance 0x19731d40'
This is a debugging problem and nobody can really solve it for you as you are using non-local variables whose definition and values are unknown, don't mention that you are using SBJSON (I guess), etc. But let's see if we can give you some pointers. Your error:
[__NSArrayM objectForKey:]: unrecognized selector sent to instance
That tells you that you sent a dictionary method (objectForKey) to an array (__NSArrayM). So somewhere you have an array when you think you have a dictionary.
Now you declare and allocate a dictionary:
NSMutableDictionary * myDict = [[NSMutableDictionary alloc] init];
but then assign to it:
myDict=[sdf objectAtIndex:i];
So this discards the dictionary you allocated and instead assigns whatever is at index i in the array sdf. How do you know, as opposed to think, that the element of the array is a dictionary? You don't test to check...
So where did sdf come from? This line:
NSMutableArray *sdf = [(NSDictionary*)[responseString JSONValue] objectForKey:#"DataTable"];
So that calls JSONValue on some unknown string, assumes the result is a dictionary (could it be an array? or a failure?), looks up a key (did your error come from this line?), and assumes the result is an array.
So what you need to do is go and test all those assumptions, and somewhere you'll find an array where you think you have a dictionary.
Happy hunting!
YOU FETCH THE VALUE IN ARRAY FORMAT AND YOU INTEGRATE METHOD IN DICTIONARY.
You do not need to iterate keys and values of dict can directly pass values to array inside else part like:
myArray = [sdf objectForKey:#"RxnCustomerProfile"];
Key RxnCustomerProfile itself containing array not dictionary.
Change your if else part use below code:
if (([(NSString*)sdf isEqual: [NSNull null]])) {
// Showing AlertView Here
}else {
myArray = [sdf objectForKey:#"RxnCustomerProfile"];
}
NSMutableArray *sdf = [(NSDictionary*)[responseString JSONValue] objectForKey:#"DataTable"];
Check Sdf
if([sdf isKindOfClass:[NSDictionary class]])
{
NSLog(#"Dictionary");
}
else if([sdf isKindOfClass:[NSArray class]])
{
NSLog(#"NSArray");
}
else if([sdf isKindOfClass:[NSMutableArray class]])
{
NSLog(#"NSMutableArray");
}
First of all it seems like your json is not actually correctly formatted. Without knowing what responseData looks like it's difficult to say exactly what is wrong. But in your code there are a few areas where it can be improved.
First of all you don't need to use [responseString JSONValue]. You can short circuit it entirely with
NSDictionary *responseDictionary = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:nil];
NSArray *sdf = responseDictionary[#"DataTable"];
Now, the rest all depends on the data in responseData.
But you can make your code a little bit cleaner with (if I understand what you're trying to achieve correctly:
NSMutableArray *myArray = [NSMutableArray array];
if ([sdf isEqual:[NSNull null]]) {
// Showing AlertView here
} else {
for (NSDictionary *myDict in sdf) {
[myArray addObject:dict[#"RxnCustomerProfile"]];
}
}
// No idea what you're trying to achieve here, but here goes:
jsonArray = [myArray mutableCopy];
NSDictionary *dict = jsonArray.first;
if (dict.count > 1) {
// Showing AlertView here
}
Some things to note. You make very liberal use of NSMutableArray and NSMutableDictionary for no apparent reason. Only use mutable if you're actually changing the array or dictionary.
I have an NSMutableArray called myMutbaleArray that looks like this when I log it
2015-12-08 17:04:21.679 APP[3342:573379] (
{
id = 19;
"num_test" = 100000;
url = "http://fsad.com";
},
{
id = 20;
"num_test" = 100001;
url = "http://teeeet.com";
}
)
And I want to add an object that looks like this
{
id = 21;
"num" = 100002;
url = "http://example.com";
}
So I am trying this
[myMutbaleArray addObject:#{ #"id":#"23",#"num_test":#"100000", #"url":mainDict[#"website_url"],#"website_name":#"website"}];
But when I do this I get
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFArray insertObject:atIndex:]: mutating method sent to immutable object'
I initialize the array like this
#interface {
NSMutableArray *socailArray;
}
//inside connectionDidFinishLoading
socailArray = [dataDict valueForKey:#"socail"];
Why can I add another dictionary to the MutableArray?
Thanks
If you see this, your array is actually not a mutable array. Here is the hint:
-[__NSCFArray insertObject:atIndex:]
^^^^^^^^^^^
The object is of type __NSCFArray, which is an internal counterpart of NSArray.
Even if you declare your variable as NSMutableArray the pointer can point to an object of any type (event for example NSRegularExpression). Important is, how it is created.
This happens to most people if they serialise an array either using NSUserDefaults, NSJSONSerialization or what ever.
The key is to create a mutable copy when the array gets deserialised using
-[NSArray mutableCopy]
Note that this is not deep-copy. This means an array contained in the root array will not be mutable copied and needs to be replaced separately.
Deep copying can be achieved using this:
// array
NSArray *originalArray = #[#"a", #"b", #[#1, #2]];
NSMutableArray *mutableArray = (NSMutableArray *)CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFArrayRef)originalArray, kCFPropertyListMutableContainers);
// dictionary
NSDictionary *originalDictionary = #{#"a": #"b", #"c": #[#{#"abc": #123}]};
NSMutableDictionary *mutableDictionary = (NSMutableDictionary *)CFPropertyListCreateDeepCopy(kCFAllocatorDefault, (CFDictionaryRef)originalDictionary, kCFPropertyListMutableContainers);
You should change init to:
//inside connectionDidFinishLoading
socailArray = [NSMutableArray arrayWithArray:[dataDict valueForKey:#"socail"]];
Because: [dataDict valueForKey:#"socail"] is a NSArray.
With socailArray = [dataDict valueForKey:#"socail"];, the type of [dataDict valueForKey:#"socail"] is NSArray, so it auto cast socailArray into NSArray, that's why you can not insert thing into this.
To avoid this, you must be hold socailArray as NSMutableArray using:
socailArray = [[dataDict valueForKey:#"socail"] mutableCopy];
Hope this could help.
I've looked at lots of questions about NS(Mutable)Arrays. I guess I am not grokking the concept, or the questions don't seem relevant.
What I' trying to do is the following:
Incoming Array 1:
Name
Code
Start time
End Time
etc
Incoming Array 2
Code
Ordinal
What I want:
Ordinal
Name
Code
Start time
End Time
etc
This is my code at present:
int i=0;
for (i=0; i < stationListArray.count; i++) {
NSString *slCodeString = [stationListArray[i] valueForKey:#"Code"];
NSLog(#"slCodeString: %#", slCodeString);
int j=0;
for (j=0; j< lineSequenceArray.count; j++) {
NSString *lsCodeString = [lineSequenceArray[j]valueForKey:#"StationCode"];
NSLog(#"lsCodeString: %#", lsCodeString);
if ([slCodeString isEqualToString:lsCodeString]) {
NSLog(#"match");
NSString *ordinalString = [lineSequenceArray[j] valueForKey:#"SeqNum"];
NSLog(#"ordinalString: %#", ordinalString);
[stationListArray[i] addObject:ordinalString]; <------
}
}
}
I'm logging the values and they return correctly.
The compiler doesn't like the last statement. I get this error:
[__NSCFDictionary addObject:]: unrecognized selector sent to instance 0x7f9f63e13c30
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary addObject:]: unrecognized selector sent to instance 0x7f9f63e13c30'
Here is an excerpt from the StationListArray:
(
{
Address = {
City = Greenbelt;
State = MD;
Street = ".....";
Zip = 20740;
};
Code = E10;
Lat = "39.0111458605";
Lon = "-76.9110575731";
Name = Greenbelt;
}
)
NSString *ordinalString = [lineSequenceArray[j] valueForKey:#"SeqNum"]; //Is NSString
[stationListArray[i] addObject:ordinalString];//<----- trying to call addObject method of NSMutableArray on NSDictionary -> Not GOOD
When you do [stationListArray[i] you get NSDictionary in your case
(Generally it returns an NSObject that is inside the NSArray at the given index, in your case is NSDictionary).
So in order to complete your desired operation: you should make an NSMutableDictionary instance (In this case it should be the mutableCopy from the stationListArray[i]'s NSObject which is NSDictionary, when you do mutableCopy it copies the entire NSDictionary and makes it Mutable)
make the changes on it and then assign it in to the stationListArray[i]
For example:
NSMutableDictionary * tempDict = [[stationArray objectAtIndex:i]mutableCopy];//Create a mutable copy of the `NSDictionary` that is inside the `NSArray`
[[tempDict setObject:ordinalString forKey:#"Ordinal"]; //In this line you are adding the Ordinal `NSString` in to the tempDict `NSMutableDictionary` so now you have the desired `NSMutableDictionary`. You can change the key to whatever you wish.
[stationArray replaceObjectAtIndex:i withObject:[tempDict copy]];//Swap the original(old NSDictionary) with the new updated `NSMutableDictionary` I used the copy method in order to replace it with the IMMUTABLE `NSDictionary`
[stationListArray[i] addObject:ordinalString]; <------
This is not an NSMutableArray. You must use
[stationListArray addObject:ordinalString]; <------
instead of the what you have done.
Here is the way you can write a better understandable code because for me the code is not clear.You can also try like this in loop to achieve what you want.
NSMutableArray *array = [NSMutableArray new];
NSMutableDictionary *dictMain = [NSMutableDictionary new];
NSMutableDictionary *dictAddress = [NSMutableDictionary new];
[dictAddress setValue:#"Greenbelt" forKey:#"City"];
[dictAddress setValue:#"MD" forKey:#"State"];
[dictAddress setValue:#"....." forKey:#"Street"];
[dictAddress setValue:#"20740" forKey:#"Zip"];
[dictMain setValue:dictAddress forKey:#"Address"];
[dictMain setValue:#"E10" forKey:#"Code"];
[dictMain setValue:#"39.0111458605" forKey:#"Lat"];
[dictMain setValue:#"-76.9110575731" forKey:#"Lon"];
[dictMain setValue:#"Greenbelt" forKey:#"Name"];
[array addObject:dictMain];
I am using Realm 0.92.3 but it crashed when I have null value despite I have set the default properties. Is there any solution on this? If not I might convert using coredata as this is very important to me. The null will be random on several properties
#interface WatchlistNews : RLMObject
#property NSString *nid;
#property NSString *tid;
#property NSString *country;
#end
#implementation WatchlistNews
+ (NSString *)primaryKey {
return #"nid";
}
+ (NSDictionary *)defaultPropertyValues {
return #{#"nid" : #"", #"tid": #"", #"country": #""};
}
#end
Data response:
nid = 509319;
tid = <null>;
country = my;
Error code:
-[NSNull UTF8String]: unrecognized selector sent to instance 0x10712b4c0
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSNull UTF8String]: unrecognized selector sent to instance 0x10712b4c0'
Realm do not support complex data types, so if you try to assign a complex value such as <null>, it gets crashed.
You should check the response you are getting from the server for the <null> values. And if it exists in the response replace it with an empty string. Try following code on the response you are getting, to remove the occurance of <null> values.
-(NSMutableDictionary *) removeNullFromDictionary:(NSDictionary *) originalDictionary{
NSArray *allKeysArray = [originalDictionary allKeys];
const NSMutableDictionary *replaced = [originalDictionary mutableCopy];
const id nul = [NSNull null];
const NSString *blank = #"";
for(NSString *key in allKeysArray) {
const id object = [originalDictionary objectForKey:key];
if(object == nul) {
[replaced setObject:blank forKey:key];
}
}
return [replaced copy];
}
Realm does not yet support setting nil for NSString properties, but you can track progress on that by following https://github.com/realm/realm-cocoa/issues/628.
- (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.