I am developing application using Objective C.
I am getting following array in the response from server side ( i'm using Get method of AFNetworking).
Response from server: `[{"name":"option1","profile_id":0,"profile_name":"option1"},{"name":"option2","profile_id":0,"profile_name":"option2"},{"name":"option3","profile_id":0,"profile_name":"option3"},{"name":"option4","profile_id":0,"profile_name":"option4"},{"name":"option5","profile_id":0,"profile_name":"option5"},{"name":"option6","profile_id":0,"profile_name":"option6"},{"name":"option7","profile_id":0,"profile_name":"option7"},{"name":"option8","profile_id":0,"profile_name":"option8"},{"name":"option9","profile_id":0,"profile_name":"option9"},{"name":"option10","profile_id":0,"profile_name":"option10"}]`
I want to separate values for the key name.
In short, i want output like:[option1,option2,option3,option4,option5,option6,option7,option8,option9,option10]
For that i tried like following way:
store that response in array (_arr). and then try to separate values for key name like following way,
NSArray *optionArray = [_arr valueForKey:#"name"];
NSLog(#"%#",optionArray);
but, unfortunately this is not working. Application crashes and gives following logs.
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSCFString 0x7abd0600> valueForUndefinedKey:]: this class is not key value coding-compliant for the key name.'
*** First throw call stack:
(
0 CoreFoundation 0x00ae2a14 __exceptionPreprocess + 180
1 libobjc.A.dylib 0x005a3e02 objc_exception_throw + 50
2 CoreFoundation 0x00ae2631 -[NSException raise] + 17
3 Foundation 0x00239098 -[NSObject(NSKeyValueCoding) valueForUndefinedKey:] + 282
4 Foundation 0x0017a798 _NSGetUsingKeyValueGetter + 105
5 Foundation 0x0017a727 -[NSObject(NSKeyValueCoding) valueForKey:] + 288
6 Foundation 0x001bac40 -[NSFunctionExpression expressionValueWithObject:context:] + 1079
7 Foundation 0x001ba739 -[NSComparisonPredicate evaluateWithObject:substitutionVariables:] + 290
8 Foundation 0x001ba60f -[NSPredicate evaluateWithObject:] + 48
9 Foundation 0x001ba593 _filterObjectsUsingPredicate + 437
10 Foundation 0x001ba360 -[NSArray(NSPredicateSupport) filteredArrayUsingPredicate:] + 314
11 Wellness_24x7 0x0008fbc4 __31-[ForthViewController Donating]_block_invoke + 564
12 Wellness_24x7 0x0006c097 __116-[AFHTTPSessionManager dataTaskWithHTTPMethod:URLString:parameters:uploadProgress:downloadProgress:success:failure:]_block_invoke97 + 231
13 Wellness_24x7 0x00080bd5 __72-[AFURLSessionManagerTaskDelegate URLSession:task:didCompleteWithError:]_block_invoke_2132 + 213
14 libdispatch.dylib 0x0330e377 _dispatch_call_block_and_release + 15
15 libdispatch.dylib 0x033319cd _dispatch_client_callout + 14
16 libdispatch.dylib 0x03316f90 _dispatch_main_queue_callback_4CF + 910
17 CoreFoundation 0x00a33fde __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 14
18 CoreFoundation 0x009f1cd4 __CFRunLoopRun + 2356
19 CoreFoundation 0x009f10e6 CFRunLoopRunSpecific + 470
20 CoreFoundation 0x009f0efb CFRunLoopRunInMode + 123
21 GraphicsServices 0x050c8664 GSEventRunModal + 192
22 GraphicsServices 0x050c84a1 GSEventRun + 104
23 UIKit 0x012ecbfa UIApplicationMain + 160
24 Wellness_24x7 0x0006905a main + 138
25 libdyld.dylib 0x0335ba21 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Thank you in advance.
actually your JSON Response started with Array, so do like
NSArray *ResponseArray = [NSJSONSerialization JSONObjectWithData: data options: KNilOptions error: nil];
NSMutableArray *finalArray = [NSMutableArray array];
for (NSDictionary *temp in ResponseArray) {
[finalArray addObject:temp[#"name"]];
}
Choice-2 for AFNetworking
NSMutableArray *finalArray = [NSMutableArray array];
for (NSDictionary *temp in responseObject) {
[finalArray addObject:temp[#"name"]];
}
Try this
NSMutableArray *arrOptions = [NSMutableArray new];
for (int i=0; i<_arr.count; i++) {
[arrOptions addObject:[[_arr objectAtIndex:i] objectForKey:#"name"]];
}
here arrOptions will contain your desired output.
I can see that you are getting response in JSON format. So you can convert JSON into mutable containers like Dictionary and Arrays. In your case it is array of dictionaries.
NSArray *jsonArray = [NSJSONSerialization JSONObjectWithData: data options: NSJSONReadingMutableContainers error: &e];
if(!jsonArray)
{
for(NSDictionary *dict in jsonArray)
{
NSLog(#"%#", dict valueForKey: #"name");
}
}
According to your JSON data below you need to store data using NSDictionary instead of an Array.
[{
"name": "option1",
"profile_id": 0,
"profile_name": "option1"
}, {
"name": "option2",
"profile_id": 0,
"profile_name": "option2"
}, {
"name": "option3",
"profile_id": 0,
"profile_name": "option3"
}, {
"name": "option4",
"profile_id": 0,
"profile_name": "option4"
}, {
"name": "option5",
"profile_id": 0,
"profile_name": "option5"
}, {
"name": "option6",
"profile_id": 0,
"profile_name": "option6"
}, {
"name": "option7",
"profile_id": 0,
"profile_name": "option7"
}, {
"name": "option8",
"profile_id": 0,
"profile_name": "option8"
}, {
"name": "option9",
"profile_id": 0,
"profile_name": "option9"
}, {
"name": "option10",
"profile_id": 0,
"profile_name": "option10"
}]
Get the data using dict like:
NSDictionary *jsonDataDict = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSArray *optionArray = [jsonDataDict valueForKey:#"name"];
Problem: you are trying to get data of name key and you storing whole JSON data inside an array.
Array doesn't contain key value pair use NSDictionary.
What you want to achieve and your thinking i can say you are on right track.
You have converted your response Data in NSDictionary but it must be an array.
NSArray *responseArray = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
this will convert your response to array and you can use
NSArray *optionArray = [responseArray valueForKey:#"name"];
This will lead to same result as answer from #Krishna Kumar but with this you will be able to avoid "for" loop.
Related
I want to get the json data to a block, but it failed.
the Internet request is
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *dataResult, NSError *connectionError) {
if (!connectionError) {
if (successBlock) {
//NSString* str = [[NSString alloc] initWithData:dataResult encoding:NSUTF8StringEncoding];
//NSLog(#"response data: %#", str);
NSDictionary *json = [[NSDictionary alloc]init];
json = [NSJSONSerialization JSONObjectWithData:dataResult options:kNilOptions error:nil];
successBlock(json);
}
} else {
if (failureBlock) {
failureBlock(connectionError);
}
}
}];
the successBlock is defined like this:
typedef void(^HttpRequestSuccessBlock)(id responseObject);
typedef void(^HttpRequestFailBlock)(NSError *error);
I can successfully get the dataResult in 1 and translate it into NSString, and I NSlog it, it is actually the Json format.
But when run the code, it crashed and shows the following errors:
2017-08-21 09:43:22.258 shopiPhoneDemo[24397:5799646] -[__NSDictionaryI bytes]: unrecognized selector sent to instance 0x7faa75501220
2017-08-21 09:43:22.264 shopiPhoneDemo[24397:5799646] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSDictionaryI bytes]: unrecognized selector sent to instance 0x7faa75501220'
Update the stack trace:
2017-08-21 09:43:22.258 shopiPhoneDemo[24397:5799646] -[__NSDictionaryI bytes]: unrecognized selector sent to instance 0x7faa75501220
2017-08-21 09:43:22.264 shopiPhoneDemo[24397:5799646] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSDictionaryI bytes]: unrecognized selector sent to instance 0x7faa75501220'
*** First throw call stack:
(
0 CoreFoundation 0x0000000105e8cb0b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x00000001058f1141 objc_exception_throw + 48
2 CoreFoundation 0x0000000105efc134 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
3 CoreFoundation 0x0000000105e13840 ___forwarding___ + 1024
4 CoreFoundation 0x0000000105e133b8 _CF_forwarding_prep_0 + 120
5 Foundation 0x00000001054281a1 -[_NSJSONReader findEncodingFromData:withBOMSkipLength:] + 46
6 Foundation 0x0000000105428087 -[_NSJSONReader parseData:options:] + 58
7 Foundation 0x0000000105427fbb +[NSJSONSerialization JSONObjectWithData:options:error:] + 139
8 shopiPhoneDemo 0x0000000104cc4e2d __24-[AppDelegate youtuTest]_block_invoke + 77
9 shopiPhoneDemo 0x0000000104cbfc3f __62-[TXQcloudFrSDK sendRequest:mothod:successBlock:failureBlock:]_block_invoke + 271
10 CFNetwork 0x0000000108a045ae __67+[NSURLConnection sendAsynchronousRequest:queue:completionHandler:]_block_invoke_2 + 161
11 Foundation 0x00000001053fb3b7 __NSBLOCKOPERATION_IS_CALLING_OUT_TO_A_BLOCK__ + 7
12 Foundation 0x00000001053fb0bb -[NSBlockOperation main] + 101
13 Foundation 0x00000001053f9877 -[__NSOperationInternal _start:] + 627
14 Foundation 0x00000001053f55fc __NSOQSchedule_f + 198
15 libdispatch.dylib 0x000000010940905c _dispatch_client_callout + 8
16 libdispatch.dylib 0x00000001093ea40b _dispatch_main_queue_callback_4CF + 411
17 CoreFoundation 0x0000000105e51909 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
18 CoreFoundation 0x0000000105e17ae4 __CFRunLoopRun + 2164
19 CoreFoundation 0x0000000105e17016 CFRunLoopRunSpecific + 406
20 GraphicsServices 0x000000010b4bba24 GSEventRunModal + 62
21 UIKit 0x0000000106999134 UIApplicationMain + 159
22 shopiPhoneDemo 0x0000000104cd0eff main + 111
23 libdyld.dylib 0x000000010945565d start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
the Json NSLog is:
{"errorcode":0,"errormsg":"OK","session_id":"","name":"陈佳佳","name_confidence_all":[99,99,99],"sex":"女","sex_confidence_all":[99],"nation":"汉","nation_confidence_all":[99],"birth":"1985/9/11","birth_confidence_all":[100,100,100,100,100,100,100,100,100],"address":"福建省尤溪县汤川乡汤三村16号","address_confidence_all":[99,99,99,99,99,99,99,99,99,99,99,99,99,99,99],"id":"350426198509113027","id_confidence_all":[100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100,100],"frontimage":"","frontimage_confidence_all":[],"watermask_confidence_all":[],"valid_date_confidence_all":[],"authority_confidence_all":[],"backimage_confidence_all":[],"detail_errorcode":[],"detail_errormsg":[]}
I use json editor format is:
{
"errorcode": 0,
"errormsg": "OK",
"session_id": "",
"name": "陈佳佳",
"name_confidence_all": [
99,
99,
99
],
"sex": "女",
"sex_confidence_all": [
99
],
"nation": "汉",
"nation_confidence_all": [
99
],
"birth": "1985/9/11",
"birth_confidence_all": [
100,
100,
100,
100,
100,
100,
100,
100,
100
],
"address": "福建省尤溪县汤川乡汤三村16号",
"address_confidence_all": [
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99,
99
],
"id": "350426198509113027",
"id_confidence_all": [
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100,
100
],
"frontimage": "",
"frontimage_confidence_all": [],
"watermask_confidence_all": [],
"valid_date_confidence_all": [],
"authority_confidence_all": [],
"backimage_confidence_all": [],
"detail_errorcode": [],
"detail_errormsg": []
}
What I have tried to do:
I try to make a mutablecopy for json, but it doesn't working.
I try to change the id into NSDictionary, but it doesn't working either.
Might be you are dealing with NSArray rather than NSDictionary. So it's better to handle both of the cases.
id json = [NSJSONSerialization JSONObjectWithData:dataResult options:kNilOptions error:nil];
if ([json isKindOfClass:[NSArray class]]) {
NSLog(#"its an array!");
NSArray *jsonArray = (NSArray *)json;
NSLog(#"jsonArray - %#",jsonArray);
}
else {
NSLog(#"its probably a dictionary");
NSDictionary *jsonDictionary = (NSDictionary *)json;
NSLog(#"jsonDictionary - %#",jsonDictionary);
}
I think problem inside the data or inside the json parcer. Try to use other json parser with open code, for example https://github.com/johnezang/JSONKit/blob/master/JSONKit.h. You can find, what exactly sends this exception.
I download my Firebase database in json with AFNetworking 3. Everything works fine but there is a crash in the function cellForRoAtIndexPath.
Thanks
Work :
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
[manager GET:#"https://jojol-concours-lists.firebaseio.com/.json" parameters:URLParameters progress:nil success:^(NSURLSessionTask *task, id responseObject) {
self.contestArray = responseObject;
[_collectionView reloadData];
} failure:^(NSURLSessionTask *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
Work :
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section {
return [self.contestArray count];
}
Not work : (NSDictionary *array = [self.contestArray objectAtIndex:indexPath.row];)
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView
cellForItemAtIndexPath:(NSIndexPath *)indexPath {
DemoCollectionViewCell *retVal = [collectionView dequeueReusableCellWithReuseIdentifier:#"collectionViewCell"
forIndexPath:indexPath];
//////// Not work ///////
NSDictionary *array = [self.contestArray objectAtIndex:indexPath.row];
//////// Not work ///////
retVal.name.text = #"";
retVal.contentView.layer.cornerRadius = 10;
retVal.contentView.layer.masksToBounds = YES;
return retVal;
}
JSON :
{
"Concours-1" : {
"Description" : "Description du concours",
"Title" : "Titre"
},
"Concours-2" : {
"Description" : "Description du concours",
"Titre" : "iPhone 6"
}
}
Log Crash :
-[NSDictionaryI objectAtIndex:]: unrecognized selector sent to instance 0x61000086c8c0
2017-07-18 10:00:26.787 jojol67[7003:4420828] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSDictionaryI objectAtIndex:]: unrecognized selector sent to instance 0x61000086c8c0'
*** First throw call stack:
(
0 CoreFoundation 0x000000010c084b0b __exceptionPreprocess + 171
1 libobjc.A.dylib 0x000000010e5c9141 objc_exception_throw + 48
2 CoreFoundation 0x000000010c0f4134 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
3 CoreFoundation 0x000000010c00b840 ___forwarding_ + 1024
4 CoreFoundation 0x000000010c00b3b8 _CF_forwarding_prep_0 + 120
5 jojol67 0x000000010756db3f -[DEMOConcoursTableViewController collectionView:cellForItemAtIndexPath:] + 191
6 UIKit 0x000000010d162925 -[UICollectionView _createPreparedCellForItemAtIndexPath:withLayoutAttributes:applyAttributes:isFocused:notify:] + 446
7 UIKit 0x000000010d162761 -[UICollectionView _createPreparedCellForItemAtIndexPath:withLayoutAttributes:applyAttributes:] + 35
8 UIKit 0x000000010d1679bd -[UICollectionView _updateVisibleCellsNow:] + 4764
9 UIKit 0x000000010d16d38e -[UICollectionView layoutSubviews] + 313
10 UIKit 0x000000010c8f355b -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 1268
11 QuartzCore 0x000000010c6a4904 -[CALayer layoutSublayers] + 146
12 QuartzCore 0x000000010c698526 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 370
13 QuartzCore 0x000000010c6983a0 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
14 QuartzCore 0x000000010c627e92 _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 294
15 QuartzCore 0x000000010c654130 _ZN2CA11Transaction6commitEv + 468
16 QuartzCore 0x000000010c654b37 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 115
17 CoreFoundation 0x000000010c02a717 CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION + 23
18 CoreFoundation 0x000000010c02a687 __CFRunLoopDoObservers + 391
19 CoreFoundation 0x000000010c00f720 __CFRunLoopRun + 1200
20 CoreFoundation 0x000000010c00f016 CFRunLoopRunSpecific + 406
21 GraphicsServices 0x00000001103c2a24 GSEventRunModal + 62
22 UIKit 0x000000010c830134 UIApplicationMain + 159
23 jojol67 0x000000010752ef5f main + 111
24 libdyld.dylib 0x000000010f31d65d start + 1
25 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
/////// Firebase realtime database ////////
Your id responseObject is not an array because your JSON contains an object not an array. App crashes because you are calling objectAtIndex on a NSDictionary object.
If you want to access this JSON as an array, you may want to format it to something like this,
[{
"Concours": 1,
"Description": "Description du concours",
"Title": "Titre"
}, {
"Concours": 2,
"Description": "Description du concours",
"Titre": "iPhone 6"
}]
It will help you for such responce:
NSDictionary *jsonDict =responseObject;
NSArray *allKeys = [jsonDict allKeys];
NSMutableArray *allDataArray = [NSMutableArray new];
for (int x = 0; x<allKeys.count; x++) {
NSString *key = [allKeys objectAtIndex:x];
[allDataArray addObject:[jsonDict valueForKey:key]];
// then reload your collection on allDataArray
}
Current JSON:
{
"Concours-1" : {
"Description" : "Description du concours",
"Title" : "Titre"
},
"Concours-2" : {
"Description" : "Description du concours",
"Titre" : "iPhone 6"
}
}
How it should be:
[
{
"Description": "Description du concours",
"Title": "Titre"
},
{
"Description": "Description du concours",
"Titre": "iPhone 6"
}
]
"-[NSDictionaryI objectAtIndex:]: unrecognized selector sent to instance 0x61000086c8c0 "
It seems that the self.contestArray is NSDictionary class;
You can log the responseObject it maybe a Dictionary , not Array;
My problem is this. When Im parsing my JSON data it is getting returned to me as an NSSArray with one element. Inside this one element it looks like this:
2015-07-14 20:45:38.467 ICBuses[51840:14872349] Bus Location: {
agencyname = Cambus;
agencytag = uiowa;
color = 00ff66;
directions = (
{
direction = Loop;
directiontag = loop;
stops = (
{
directiontitle = Loop;
stoplat = "41.659541";
stoplng = "-91.53775";
stopnumber = 1050;
stoptitle = "Main Library";
},
{
directiontitle = Loop;
stoplat = "41.6414999";
stoplng = "-91.55676";
stopnumber = 3200;
stoptitle = "Studio Arts Building";
},
{
directiontitle = Loop;
stoplat = "41.66504";
stoplng = "-91.54094";
stopnumber = 2100;
stoptitle = "Art Building";
},
{
directiontitle = Loop;
stoplat = "41.6662587";
stoplng = "-91.5405201";
stopnumber = 2106;
stoptitle = "Theatre Building";
},
{
directiontitle = Loop;
stoplat = "41.6679058";
stoplng = "-91.5401033";
stopnumber = 2120;
stoptitle = "Hancher/North Riverside";
},
{
directiontitle = Loop;
stoplat = "41.6660209";
stoplng = "-91.5406198";
stopnumber = 2105;
stoptitle = "Riverside & River St";
},
{
directiontitle = Loop;
stoplat = "41.66499";
stoplng = "-91.54106";
stopnumber = 2101;
stoptitle = "Art Building West";
},
{
directiontitle = Loop;
stoplat = "41.6612";
stoplng = "-91.5403422";
stopnumber = 145;
stoptitle = EPB;
}
);
}
);
I want each block to be in there once element...How do I do this? Below is my coded that parses the data and stores it to an array.
code that stores it to an array:
self.routeInfo = [[API sharedAPI] routeInfoAgency:self.routeAgency
Route:self.route];
self.busLocation = [[API sharedAPI] busLocation:self.routeAgency
Route:self.route];
NSLog(#"Bus Location: %#", self.routeInfo);
Heres the code that gets it from the server and parses it:
- (NSArray *) routeInfoAgency:(NSString *)agency Route:(NSString *)route {
NSError *error;
NSString *requestString = [NSString stringWithFormat:#"http://api.ebongo.org/route?format=json&agency=%#&route=%#&api_key=", agency, route];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#%#",requestString, kApiKey]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error];
if (!data) {
NSLog(#"Download Error: %#", error.localizedDescription);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:[NSString stringWithFormat:#"Error %#", error.localizedDescription] delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
return nil;
}
NSDictionary *JSON = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&error];
NSArray *JSONArray = [JSON valueForKeyPath:#"route.directions"];
return JSONArray;
}
I want what is after stops = to be in an array that where each element is a block of directions title, stipulate, stoping, stop number and stoptitle.
Thank you
When I try to use floatValue I get this error:
{
When I do that I'm getting this error {2015-07-15 10:31:05.821 ICBuses[56344:16107040] -[__NSArrayI floatValue]: unrecognized selector sent to instance 0x7f91fb5bdf90
2015-07-15 10:31:05.868 ICBuses[56344:16107040] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI floatValue]: unrecognized selector sent to instance 0x7f91fb5bdf90'
*** First throw call stack:
(
0 CoreFoundation 0x000000010bc53c65 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010b8ecbb7 objc_exception_throw + 45
2 CoreFoundation 0x000000010bc5b0ad -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x000000010bbb113c ___forwarding___ + 988
4 CoreFoundation 0x000000010bbb0cd8 _CF_forwarding_prep_0 + 120
5 ICBuses 0x000000010958f26e -[MapViewController viewDidLoad] + 3950
6 UIKit 0x000000010c17d1d0 -[UIViewController loadViewIfRequired] + 738
7 UIKit 0x000000010c17d3ce -[UIViewController view] + 27
8 UIKit 0x000000010c1a2257 -[UINavigationController _startCustomTransition:] + 633
9 UIKit 0x000000010c1ae37f -[UINavigationController _startDeferredTransitionIfNeeded:] + 386
10 UIKit 0x000000010c1aeece -[UINavigationController __viewWillLayoutSubviews] + 43
11 UIKit 0x000000010c2f96d5 -[UILayoutContainerView layoutSubviews] + 202
12 UIKit 0x000000010c0cc9eb -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 536
13 QuartzCore 0x000000010b18eed2 -[CALayer layoutSublayers] + 146
14 QuartzCore 0x000000010b1836e6 _ZN2CA5Layer16layout_if_neededEPNS_11TransactionE + 380
15 QuartzCore 0x000000010b183556 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 24
16 QuartzCore 0x000000010b0ef86e _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 242
17 QuartzCore 0x000000010b0f0a22 _ZN2CA11Transaction6commitEv + 462
18 QuartzCore 0x000000010b0f10d3 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 89
19 CoreFoundation 0x000000010bb86ca7 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
20 CoreFoundation 0x000000010bb86c00 __CFRunLoopDoObservers + 368
21 CoreFoundation 0x000000010bb7ca33 __CFRunLoopRun + 1123
22 CoreFoundation 0x000000010bb7c366 CFRunLoopRunSpecific + 470
23 GraphicsServices 0x000000010e727a3e GSEventRunModal + 161
24 UIKit 0x000000010c04c8c0 UIApplicationMain + 1282
25 ICBuses 0x000000010958e2cf main + 111
26 libdyld.dylib 0x000000010d481145 start + 1
27 ??? 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
I think it is because the for loop is saving it as an array with one element.
Any suggestions?
It looks like it's not an array at all. It looks like it's actually a dictionary. When you log a collection like that you can see dictionaries because they are marked with { and arrays are marked with (. Based on the structure of your data, something like this should get the correct members:
NSDictionary *JSONDict = [JSON valueForKeyPath:#"route.directions"];
NSArray *directions = JSONDict[#"directions"];
NSDictionary *directionsDict = directions.firstObject; // seems to be an array with just 1 element.
NSArray *stops = directionsDict[#"stops"];
for(NSDictionary *stop in stops)
{
NSString *title = stop[#"directiontitle"];
NSString *stopLat = stop[#"stoplat"];
// etc
}
In your example, it appears that [JSON valueForKeyPath:#"route.directions"]; returns a NSSdictionary, not a NSArray.
NSDictionary *json = [NSJSONSerialization
JSONObjectWithData:data
options:NSJSONReadingMutableContainers
error:&error];
NSDictionary * directions = [json valueForKeyPath:#"route.directions"];
NSArray * stops = [directions valueForKeyPath:#"stops"];
You can then iterate through the stops array.
I have two modes - Mode 1 and Mode 2 which can be switched by a central button. Switch between modes allows user to see two different types of clustered annotations.
I can switch from Mode 1 to Mode 2 easily, but when I switch back to Mode 1 I'm getting this nasty error
-[__NSCFDictionary componentsSeparatedByString:]: unrecognized selector sent to instance 0x7fb1308cca50
I'm opening my code and in the TBClusteredAnnotations.m (script I'm using for clusterization). I have the following snippet of code relating to componentsSeparatedByString:
TBQuadTreeNodeData TBDataFromLine(NSString *line)
{
NSString *separator=#">>>>>>>>";
NSArray *components = [line componentsSeparatedByString: separator];
double latitude = [components[0] doubleValue];
double longitude = [components[1] doubleValue];
TBUserInfo* userInfo = malloc(sizeof(TBUserInfo));
NSString *userName = [components[2] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
userInfo->userId = malloc(sizeof(char) * userName.length + 1);
strncpy(userInfo->userId, [userName UTF8String], userName.length + 1);
NSString *userId = [components [3] stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
userInfo->userImage = malloc(sizeof(char) * userId.length + 1);
strncpy(userInfo->userImage, [userId UTF8String], userId.length + 1);
return TBQuadTreeNodeDataMake(latitude, longitude, userInfo);
}
but I'm loading my annotations with the following code in the MainViewController:
-(void)annotationsmode1:(NSMutableArray*)marr
{
if(marr.count>0)
{
NSMutableArray *newMarr1=[NSMutableArray new];
NSString *separatestuff=#">>>>>>>>";
for(NSMutableDictionary *dic in marr)
{
NSString *newStr=[NSString stringWithFormat:#"%#%#",[dic[#"latitude"] isEqualToString:#""]?#" ":dic[#"latitude"],separatestuff];
newStr=[NSString stringWithFormat:#"%#%#%#",newStr,[dic[#"longitude"] isEqualToString:#""]?#" ":dic[#"longitude"],separatestuff];
newStr=[NSString stringWithFormat:#"%#%#%#",newStr,[dic[#"id"] isEqualToString:#""]?#" ":dic[#"id"],separatestuff];
newStr=[NSString stringWithFormat:#"%#%#",newStr,[dic[#"image"] isEqualToString:#""]?#" ":dic[#"image"]];
[newMarr1 addObject:newStr];
}
//NSLog(#"NEW Array: %#",newMarr);
[self.coordinateQuadTree buildTree:newMarr1];
}
}
-(void)annotationsmode2:(NSMutableArray*)marr
{
if(marr.count>0)
{
NSMutableArray *newMarr=[NSMutableArray new];
NSString *separatestuff2=#">>>>>>>>";
for(NSMutableDictionary *dic in marr)
{
NSString *newStr=[NSString stringWithFormat:#"%#%#",[dic[#"lat"] isEqualToString:#""]?#" ":dic[#"lat"],separatestuff2];
newStr=[NSString stringWithFormat:#"%#%#%#",newStr,[dic[#"lang"] isEqualToString:#""]?#" ":dic[#"lang"],separatestuff2];
newStr=[NSString stringWithFormat:#"%#%#%#",newStr,[dic[#"id"] isEqualToString:#""]?#" ":dic[#"id"],separatestuff2];
newStr=[NSString stringWithFormat:#"%#%#",newStr,[dic[#"image"] isEqualToString:#""]?#" ":dic[#"image"]];
[newMarr addObject:newStr];
}
//NSLog(#"NEW Array: %#",newMarr);
[self.coordinateQuadTree buildTree:newMarr];
}
}
UPDATE: This is the block of code where the TBDataFromLine is used
- (void)buildTree:(NSMutableArray *)lines
{
#autoreleasepool {
NSInteger count = lines.count - 1;
TBQuadTreeNodeData *dataArray = malloc(sizeof(TBQuadTreeNodeData) * count);
for (NSInteger i = 0; i < count; i++) {
dataArray[i] = TBDataFromLine(lines[i]);
}
//TBBoundingBox world = TBBoundingBoxMake(19, -166, 72, -53);
TBBoundingBox world = TBBoundingBoxMake(0,0,100,100);
_root = TBQuadTreeBuildWithData(dataArray, count, world, 4);
}
}
I've been working on this issue for hours now and still have no clue.
UPDATE: Here is the debugger's log I'm getting
2015-06-20 19:40:23.759 MapProject[13426:395344] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFDictionary componentsSeparatedByString:]: unrecognized selector sent to instance 0x7fdf93775680'
*** First throw call stack:
(
0 CoreFoundation 0x0000000112699c65 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x00000001121c3bb7 objc_exception_throw + 45
2 CoreFoundation 0x00000001126a10ad -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3 CoreFoundation 0x00000001125f713c ___forwarding___ + 988
4 CoreFoundation 0x00000001125f6cd8 _CF_forwarding_prep_0 + 120
5 MapProject 0x000000010f469ac4 TBDataFromLine + 84
6 MapProject 0x000000010f46a36f -[TBCoordinateQuadTree buildTree:] + 191
7 MapProject 0x000000010f3d2503 -[MMViewController findSpot:] + 771
8 UIKit 0x0000000110a52da2 -[UIApplication sendAction:to:from:forEvent:] + 75
9 UIKit 0x0000000110b6454a -[UIControl _sendActionsForEvents:withEvent:] + 467
10 UIKit 0x0000000110b63919 -[UIControl touchesEnded:withEvent:] + 522
11 UIKit 0x0000000110a9f998 -[UIWindow _sendTouchesForEvent:] + 735
12 UIKit 0x0000000110aa02c2 -[UIWindow sendEvent:] + 682
13 UIKit 0x0000000110a66581 -[UIApplication sendEvent:] + 246
14 UIKit 0x0000000110a73d1c _UIApplicationHandleEventFromQueueEvent + 18265
15 UIKit 0x0000000110a4e5dc _UIApplicationHandleEventQueue + 2066
16 CoreFoundation 0x00000001125cd431 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 17
17 CoreFoundation 0x00000001125c32fd __CFRunLoopDoSources0 + 269
18 CoreFoundation 0x00000001125c2934 __CFRunLoopRun + 868
19 CoreFoundation 0x00000001125c2366 CFRunLoopRunSpecific + 470
20 GraphicsServices 0x000000011444da3e GSEventRunModal + 161
21 UIKit 0x0000000110a51900 UIApplicationMain + 1282
22 MapProject 0x000000010f474c2f main + 111
23 libdyld.dy
)
libc++abi.dylib: terminating with uncaught exception of type NSException
Add an Exception break point and it will take to exactly to that line where that crash is happening. Also check 'line' cause it is changed to dictionary but you code expect it
to be a string
There is no [] operator on NSArray or NSMutableArray.
You need this:
for (NSInteger i = 0; i < count; i++) {
dataArray[i] = TBDataFromLine([lines objectAtIndex:i]);
}
Using [] on NSArray* effectively acted like "lines" was really a pointer to an array of NSMutableArray instances, whereas you wanted to get one of the items out of the array to which it pointed.
Here's a little test:
NSDictionary * test = # { #"centers" : #[
#{ #"id":#"12345", #"favorite":#NO },
#{ #"id":#"2345", #"favorite":#NO },
#{ #"id":#"345", #"favorite":#YES },
#{ #"favorite":#NO }
]};
NSMutableArray * test2 = [test mutableArrayValueForKeyPath:#"centers.id"];
NSLog(#"%#",test2);
The log gives:
(
12345,
2345,
345,
"<null>"
)
That's great, now, I wish to get rid of the NSNull values... According to How will I be able to remove [NSNull Null] objects from NSMutableArray? this is the way:
[test2 removeObjectIdenticalTo:[NSNull null]];
NSLog(#"%#",test2);
Unfortunately, it crashes:
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSDictionaryI 0x7fe2ee01e970> setValue:forUndefinedKey:]: this class is not key value coding-compliant for the key id.'
*** First throw call stack:
(
0 CoreFoundation 0x000000010e47df35 __exceptionPreprocess + 165
1 libobjc.A.dylib 0x000000010e116bb7 objc_exception_throw + 45
2 CoreFoundation 0x000000010e47db79 -[NSException raise] + 9
3 Foundation 0x000000010dcb37b3 -[NSObject(NSKeyValueCoding) setValue:forKey:] + 259
4 Foundation 0x000000010dd44be0 -[NSArray(NSKeyValueCoding) setValue:forKey:] + 186
5 Foundation 0x000000010dd471cc -[NSKeyValueSlowMutableArray removeObjectAtIndex:] + 89
6 CoreFoundation 0x000000010e3d75a3 -[NSMutableArray removeObjectIdenticalTo:] + 131
7 TestImageSizeReduction 0x000000010dbe6d35 -[ViewController viewDidLoad] + 1397
8 UIKit 0x000000010ebd2a90 -[UIViewController loadViewIfRequired] + 738
9 UIKit 0x000000010ebd2c8e -[UIViewController view] + 27
10 UIKit 0x000000010eaf1ca9 -[UIWindow addRootViewControllerViewIfPossible] + 58
11 UIKit 0x000000010eaf2041 -[UIWindow _setHidden:forced:] + 247
12 UIKit 0x000000010eafe72c -[UIWindow makeKeyAndVisible] + 42
13 UIKit 0x000000010eaa9061 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 2628
14 UIKit 0x000000010eaabd2c -[UIApplication _runWithMainScene:transitionContext:completion:] + 1350
15 UIKit 0x000000010eaaabf2 -[UIApplication workspaceDidEndTransaction:] + 179
16 FrontBoardServices 0x0000000111f582a3 __31-[FBSSerialQueue performAsync:]_block_invoke + 16
17 CoreFoundation 0x000000010e3b353c __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 12
18 CoreFoundation 0x000000010e3a9285 __CFRunLoopDoBlocks + 341
19 CoreFoundation 0x000000010e3a9045 __CFRunLoopRun + 2389
20 CoreFoundation 0x000000010e3a8486 CFRunLoopRunSpecific + 470
21 UIKit 0x000000010eaaa669 -[UIApplication _run] + 413
22 UIKit 0x000000010eaad420 UIApplicationMain + 1282
23 TestImageSizeReduction 0x000000010dbe81f3 main + 115
24 libdyld.dylib 0x0000000110c50145 start + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
So, I know many ways of removing NSNull instances from the array (predicates, indexesPassingTests, etc.) but I really want to understand why this fails with so little explanations.
Thanks in advance.
Edit:
To prevent the proxy problem given in Ian's answer the simplest solution is:
NSMutableArray * test2 = [[test valueForKeyPath:#"centers.id"] mutableCopy];
The NSMutableArray returned from mutableArrayValueForKeyPath is not a copy of the values, but instead a proxy mutable array that does a lookup to the original object on each access.
Telling it to remove objects will act upon your original object. Telling it to remove objects whose centers.id is [NSNull null] causes a failure because those objects do not respond to the key-value mapping for id. It's strange to think that it would have given you any result in the first place, but you cannot use this [NSNull null] result in the way that you want.
If you just want the values and you don't want any operations available to allow modification of the original object, I suggest that you construct your array in a different way to begin with; perhaps with a predicate.
NSNull is a null object type which allows to add NULL object to array because array doesn't accept nil value as input. If anything as a NULL we have to feed into array we use [NSNull null] singleton type object.
In your case is generated because of empty memory location it is not [NSNull null] object type. You cannot remove it using [test2 removeObjectIdenticalTo:[NSNull null]];
It can be removed by using NSPredicate Search
Try this Use NSPredicate Search to filter NSArray. You can remove null by using NSPredicate
NSDictionary * test = # { #"centers" : #[
#{ #"id":#"12345", #"favorite":#NO },
#{ #"id":#"2345", #"favorite":#NO },
#{ #"id":#"345", #"favorite":#YES },
#{ #"favorite":#NO }
]};
NSMutableArray * test2 = [test mutableArrayValueForKeyPath:#"centers.id"];
NSLog(#"%#",test2);
NSPredicate *predicate=[NSPredicate predicateWithFormat:#"SELF!=nil"];
NSArray *test3=[test2 filteredArrayUsingPredicate:predicate];
NSLog(#"%#",test3);