My client webservice send me a result like this:
{"login":{"EMAIL":"none","ID":"none","NOME":"none"}}
So, in AFN doesn't work.
But, if have one more result works:
{"login":[{"EMAIL":"none","ID":"none","NOME":"none"},{"EMAIL":"none","ID":"none","NOME":"none"}]}
My code:
NSDictionary *paramLogin = [NSDictionary dictionaryWithObjectsAndKeys:_txtEmail.text, #"email",_txtSenha.text, #"senha", nil];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:#"http://webservice.info" parameters:paramLogin success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"%#" , responseObject );
for (NSDictionary *retLogin in [responseObject valueForKeyPath:#"login"]) {
nome = [retLogin objectForKey:#"nome"];
email = [retLogin objectForKey:#"email"];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
why it is like this? or what I've to do ?
Sometimes [responseObject valueForKeyPath:#"login"] returns and array, sometimes it returns a dictionary. You need to test for this.
id loginValue = [responseObject valueForKeyPath:#"login"];
if ([loginValue isKindOfClass:[NSDictionary class]]) {
nome = [loginValue objectForKey:#"nome"];
email = [loginValue objectForKey:#"email"];
} else if ([loginValue isKindOfClass:[NSArray class]]) {
for (NSDictionary *retLogin in [responseObject valueForKeyPath:#"login"]) {
nome = [retLogin objectForKey:#"nome"];
email = [retLogin objectForKey:#"email"];
}
} else {
// ERROR: Unexpected value
}
When you have 1 value, then loginValue is an NSDictionary. It contains {"EMAIL":"none","ID":"none","NOME":"none"}.
When you have more than 1 value, then loginValue is an NSArray. The array contains [<NSDictionary>, <NSDictionary>]. Each of of these dictionaries contains {"EMAIL":"none","ID":"none","NOME":"none"}.
Problem is with your json data structure. It's not consistent.
{"login":{"EMAIL":"none","ID":"none","NOME":"none"}}
Here [responseObject valueForKeyPath:#"login"] is a single NSDictionary object.
But here,
{"login":[{"EMAIL":"none","ID":"none","NOME":"none"},{"EMAIL":"none","ID":"none","NOME":"none"}]}
Here [responseObject valueForKeyPath:#"login"] is an NSArray. So your fast enumeration works.
Best solution is to ask your webservice developer to send an array all the time, even 'login' has a single object. so it should look like this,
{"login": [{"EMAIL":"none","ID":"none","NOME":"none"}]} //notice square brackets
Otherwise you have to modify your code to check for an NSDictionary instead of array when there's only one object.
I suspect the issue is that you aren't retaining the AFHTTPRequestOperationManager object.
Assuming this code is in something like viewDidAppear:
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:...];
Then manager will be destroyed before it has a chance to complete.
Instead add a property and store the manager object in that:
#interface MyViewController ()
#property (nonatomic) AFHTTPRequestOperationManager *manager;
#end
and use:
self.manager = [AFHTTPRequestOperationManager manager];
[self.manager GET:...];
if you are getting response like that than use below code
NSMutableArray *category = [[NSMutableArray alloc]init];
category = [responseObject objectForKey:#"login"];
for(int i = 0; i < [category count]; i++)
{
NSDictionary *dic = [category objectAtIndex:i];
nome = [dic objectForKey:#"nome"];
email = [dic objectForKey:#"email"];
}
Related
I'm attempting to obtain elements extracted from a dictionary and convert them to doubles. The data is being pulled from JSON and seems to be extracted into a type of array (not sure which type). Is there a way to obtain the numbers listed below individually out of the array? Please let me know if you need more information.
NSDictionary *parameters = #{#"username":savedUser,#"password":savedPass};
NSURL *URL = [NSURL URLWithString:#"testwebsite"];
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager GET:URL.absoluteString parameters:parameters progress:nil success:^(NSURLSessionTask *task, id responseObject)
{
NSError *error = nil;
JSON = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingAllowFragments error:&error];
if (error) {
NSLog(#"Error serializing %#", error);
}
NSLog(#"%#",JSON);
NSString *price = [NSString stringWithFormat:#"%#",[JSON valueForKey:#"UnitPrice"]];
price= [price stringByReplacingOccurrencesOfString:#"\"" withString:#""];
NSLog(#"Price: %#",price);
[transactionTotals addObject:price];
[self createGraph:100];
}
failure:^(NSURLSessionTask *operation, NSError *error)
{
NSLog(#"Error1: %#", [error debugDescription]);
NSLog(#"Error2: %#", [error localizedDescription]);
}];
}
#catch (NSException *exception)
{
NSLog(#"%#",exception);
}
Log (UnitPrice values I need individually extracted):
Dictionary output:
2016-07-03 22:52:21.330 T2PApp[2272:658440] (
{
OrderDetailID = 3;
ProductName = Oranges;
UnitPrice = "399.99";
date = "2016-06-09T21:45:06";
},
{
OrderDetailID = 7;
ProductName = Oranges;
UnitPrice = 1000;
date = "2016-06-13T22:15:47.107";
}
)
Extracted UnitPrice output (still not completely extracted):
2016-07-03 22:52:21.330 T2PApp[2272:658440] Price: (
399.99,
1000
)
I think what you need is digging out the data from the objects in array. It not about the JSON.
There is many way to do it, but not one simply way to dig it out.
For example, create a new array, and traverse the target array, put the property you need into the new array.
It is basically like that.
In your code, maybe the code below will work.
NSLog(#"%#",JSON);
NSMutableArray *priceArr = [NSMutableArray array];
NSArray *arr = nil;
if ([JSON isKindOfClass:[NSArray class]]) {
arr = (NSArray *)JSON;
for (NSDictionary *dic in arr) {
NSString *price = [NSString stringWithFormat:#"%#",[dic valueForKey:#"UnitPrice"]];
price= [price stringByReplacingOccurrencesOfString:#"\"" withString:#""];
[priceArr addObject:price];
}
}
priceArr is what you need.
- The structure that I am trying to create is
[{'category_id': '3'}, {'category_id': '2'}, {'category_id': '1'}]
- I tried creating the same using NSMutableArray of NSMutableDictionary & the structure that i got back was:
<__NSArrayM 0x7c186080>(
{
"category_id" = 1;
},
{
"category_id" = 2;
},
{
"category_id" = 3;
}
)
- I am sending this to server over HTTPPost.
- But on the server the request is reaching as:
{(null)[][category_id]': ['1', '2', '3']}
Which is not in the desired format as i showed above in point 1.
- Can anyone please help me out create an JSONArray of JSONObjects, I would be really obliged.
The code that i used to create and send the request to server is:
-(void) getProductList:(NSString *)strToken andCatId:(NSArray *)arrCategory{
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager.requestSerializer setValue:strToken forHTTPHeaderField:#"Authorization"];
manager.responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments];
NSString *strSuffix = #"unfollow/productList/";
NSString *strUrl = [NSString stringWithFormat:#"%#%#",BASE_URL,strSuffix];
api_categoryProductList *currentObj = self;
[manager POST:strUrl parameters:arrCategory success:^(AFHTTPRequestOperation *operation, id responseObject) {
[currentObj httpOperationDidSuccess:oper
ation responseObject:responseObject];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[currentObj httpOperationDidFail:operation error:error];
}];
}
Try this:
NSMutableArray *array = [[NSMutableArray alloc] init];
NSNumber *id = [NSNumber numberWithInt:1];
for (int i = 0; i < 5; ++i) {
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:id forKey:#"category_id"];
[array addObject:dict];
}
Right now it has static id as 1. You can change it to whatever value you like.
I am trying to parse some JSON with AFNetworking and an NSDictionary. However something seems strange with the JSON. The JSON contains routes for shuttles, but I do not see a 'route' in the JSON.
When I run this code I get an empty NSDictionary with 15 allocated spaces.
NSString *methodURL = [NSString stringWithFormat:#"%#GetRoutesForMapWithSchedule", BASE_URL];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
[manager GET:methodURL parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
_routes = (NSDictionary *)responseObject;
//_route = _routes[#"Stops"];
NSLog(#"JSON: %#", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
Can anyone explain how I can get all the info for one route? This is the JSON.
NSArray *routes = (NSArray *)responseObject;
NSDictionary *oneRoute = responseObject[0];
NSDictionary *stops = oneRoute[#"Stops"];
The problem is that the top level JSON object is actually an array, not a dictionary as you're trying to cast it to. Each element of the array on the other hand, is a dictionary.
Here is some code to get the general data structure and to get a piece of data out of one of the routes.
NSArray *routes = (NSArray *)responseObject;
NSDictionary *firstRoute = responseObject[0];
NSString *description = firstRoute[#"Description"];
Edit: To parse Stops, you would do something like this:
NSArray *stops = firstRoute[#"Stops"];
NSDictionary *firstStop = stops[0];
NSString *stopDescription = firstStop[#"Description"];
i have a request which returns information from a php web service. I'm having trouble adding this to a array which can be used in my UICollectionView. It seems like whatever i do i cant return the data. I think it is because i'm returning the array before i've added any objects. I've tried placing the NSLog several places, but without luck. What am i doing wrong?
When i place this NSLog(#"%d", imagesArray.count); beyond the request it returns 0.
ViewDidAppear:
-(void)viewDidAppear:(BOOL)animated {
imagesArray = [[NSMutableArray alloc] init];
[self getImages];
}
getImages method:
-(void)getImages {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager GET:#"http://URL.COM" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:responseObject options:kNilOptions error:nil];
NSString *theTitle = [[json objectForKey:#"response"] valueForKey:#"title"];
NSString *theUrl = [[json objectForKey:#"response"] valueForKey:#"imageUrl"];
[imagesArray addObject:[[NSMutableDictionary alloc] initWithObjectsAndKeys:
theTitle, #"title",
theUrl, #"url",
nil]];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
NSLog(#"%d", imagesArray.count);
}
AFNetworking is Asynchronous, you have to place the log inside the success block. Otherwise the array will always be empty.
One good solution would be to pass a block to your getImages function like that
-(void) getImages:(void (^)(BOOL result))callback {
// your code here then you call callback(YES or NO) inside your success or failure block.
}
[self getImages:^(BOOL result){
if(result)
//we got the images, we can now display them etc.
}];
I'm working on an iOS project in which huge amounts of data need to be downloaded from the internet and saved in a database. I'm using MagicalRecord to handle CoreData.
It works great for a while. Then, around the time when the sqlite database reaches around 3.6-4.0 MB it suddenly stops saving the information. That is in the same run with no apparent reason. The console printing just keeps going on as if there is no issues.
I'm new to MagicalRecord and CoreData in general. Not sure what the issue is. Thanks
This is the code that is responsible for the collection:
+ (void)downloadObjects {
NSString *urlString = [NSString stringWithFormat:#"http://url.to.backend/server?with=parameters"];
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFXMLParserResponseSerializer serializer];
[manager GET:urlString parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
// Parse the XML into a dictionary
NSError *parseError = nil;
NSDictionary *xmlDictionary = [XMLReader dictionaryForXMLParser:(NSXMLParser *)responseObject error:&parseError];
__block NSArray *objectsArray = xmlDictionary[#"list"][#"object"];
[MagicalRecord saveWithBlock:^(NSManagedObjectContext *localContext) {
NSLog(#"PROCESSING: %d objects", [objectsArray count]);
if (objectsArray.count) {
for (NSDictionary *object in objectsArray) {
long long objectID = [object[#"objectid"] longLongValue];
__block NSString *latitude = object[#"latitude"];
__block NSString *longitude = object[#"longitude"];
__block NSString *speed = object[#"speed"];
__block NSString *distance = object[#"distance"];
__block NSDate *time = object[#"time"];
[MagicalRecord saveWithBlockAndWait:^(NSManagedObjectContext *localContext) {
if (time) { //Check if valid object
Object *existingObject = [ObjectManager objectWithID:objectID];
if (!existingObject) { //Check if existing object
if (DEBUG_DATA_COLLECTION) NSLog(#"%lld: NEW OBJECT", objectID);
Object *anObject = [Object MR_createEntity];
anObject.time = time;
anObject.objectID = #(objectID);
if (distance) anObject.distance = #([distance floatValue]);
if (latitude) anObject.latitude = #([latitude floatValue]);
if (longitude) anObject.longitude = #([longitude floatValue]);
if (speed) anObject.speed = #([speed floatValue]);
}
else {
if (DEBUG_DATA_COLLECTION) NSLog(#"%lld: EXISTING OBJECT", objectID);
}
}
}];
}
}
[ObjectManager aggregatePerDay];
[ObjectManager aggregatePerMonth];
} completion:^(BOOL success, NSError *error) {
NSLog(#"COMPLETED: %d objects", [objectsArray count]);
NSLog(#"---------------------");
}];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Error: %#", error);
}];
}
After 3 days of debugging and retracing my steps, I finally figured out what the issue is.
It had nothing to do with CoreData or MagicalRecord.
One of the objects I was getting from the server had speed = (null). This basically, stopped all entries in the database from that object and beyond instead of just failing and working for the rest. It might be because I was using saveWithBlockAndWait: instead of just saveWithBlock: but I'm not experienced enough to say for sure.