Reputation: 4173
I'm trying to send a NSArray *appData
as it is a NSArray
that contains a NSDictionary
(See data layout below) but when I receive the Array
in PHP
all the values in NSDictionary
are sent as single Arrays and not in the same format they were sent (See below PHP log data).
All other values in NSDictionary* params
are sent and received correctly.
Is this a bug or a problem in my code? if the later is the issue, What am i doing wrong?
Note: I am using the laster version of AFNetworking
EDIT:
As a result of @dpassage
answer I edited to include a more extensive test and to send the information as form-data
. The interesting thing around the test is that the @"test"
param sent to the server is showing great in PHP
but not the @"share":appData
its very strange
- (void) checkForUploadEligibility {
NSArray* dates = [myModel getStatsMaxAndMinResults];
if ( dates ) {
NSDictionary* d = [dates objectAtIndex:0];
NSDate* minDate = d[@"minDate"];
NSDate* maxDate = d[@"maxDate"];
NSTimeInterval secondsBetween = [maxDate timeIntervalSinceDate:minDate];
int numberOfDays = secondsBetween / 86400;
numberOfDays = abs(numberOfDays);
if (numberOfDays >= 0) {
myUser = [myModel getCurrentUser];
if ( myUser.userWebID && myUser.authToken ) {
NSArray* appData = [myModel getAllStatsData];
if (!appData) {
return;
}
NSDictionary* params = @{ @"userID": myUser.userWebID,
@"authCode": myUser.authToken,
@"interact":@{@"action":@"uploadAppStats",
@"actionTarget":@"uploadAppStats"},
@"share":appData,
@"test":@[@{@"test1":@{@"test2":@"test2"}},@{@"test3":@"test3"}]
};
[myShare uploadStats:params statsData:appData];
}
}
}
}
- (void) uploadStats:(NSDictionary*)params statsData:(NSArray *)statsData {
NSLog(@"count %i, %@",[statsData count],statsData);
NSURL *url = [[NSURL alloc]initWithString:sysURL];
AFHTTPClient *httpClient = [[AFHTTPClient alloc]initWithBaseURL:url];
NSURLRequest *request = [httpClient requestWithMethod:@"POST" path:sysAppURLPath parameters:params];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON){
NSLog(@"a: Inside the success block %@",JSON);
if ( [JSON objectForKey:@"ok"] ) {
// [myModel deleteAllStatsData:statsData];
}
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON){
NSLog(@"json text is: %@", JSON);
NSLog(@"Request failed with error: %@, %@", error, error.userInfo);
}];
// Debug HTTP response
BOOL dbug = YES;
if (dbug) {
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"HTTP r: %@", operation.responseString);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"HTTP Error: %@", operation.responseString);
}
];
}
[operation start];
}
Error log
count 5, (
{
date = "2013-09-09 16:10:51 +0000";
name = selectRoutine;
shared = 0;
timeSpent = 3;
},
{
date = "2013-09-09 16:10:53 +0000";
name = manageExercises;
shared = 0;
timeSpent = 1;
}, // MORE.....
HTTP Error: array(24) {
multipart/form-data; boundary=Boundary+0xAbCdEfGbOuNdArY
array(5) {
["authCode"]=>
string(32) "e186cdd000a741ef76555009d7e86d80"
["interact"]=>
array(2) {
["action"]=>
string(14) "uploadAppStats"
["actionTarget"]=>
string(14) "uploadAppStats"
}
["share"]=>
array(15) {
[0]=>
array(1) {
["date"]=>
string(19) "2013-09-09 19:52:31"
}
[1]=>
array(1) {
["name"]=>
string(13) "selectRoutine"
}
[2]=>
array(1) {
["timeSpent"]=>
string(1) "3"
}
[3]=>
array(1) {
["date"]=>
string(19) "2013-09-09 19:52:33"
}
[4]=>
array(1) {
["name"]=>
string(14) "manageRoutines"
}
[5]=>
array(1) {
["timeSpent"]=>
string(1) "2"
}
[6]=>
array(1) {
["date"]=>
string(19) "2013-09-09 22:24:31"
}
[7]=>
array(1) {
["name"]=>
string(13) "selectRoutine"
}
[8]=>
array(1) {
["timeSpent"]=>
string(2) "19"
}
[9]=>
array(1) {
["date"]=>
string(19) "2013-09-09 22:24:45"
}
[10]=>
array(1) {
["name"]=>
string(14) "manageRoutines"
}
[11]=>
array(1) {
["timeSpent"]=>
string(2) "14"
}
[12]=>
array(1) {
["date"]=>
string(19) "2013-09-09 22:25:58"
}
[13]=>
array(1) {
["name"]=>
string(15) "manageExercises"
}
[14]=>
array(1) {
["timeSpent"]=>
string(2) "73"
}
}
["test"]=>
array(2) {
[0]=>
array(1) {
["test1"]=>
array(1) {
["test2"]=>
string(5) "test2"
}
}
[1]=>
array(1) {
["test3"]=>
string(5) "test3"
}
}
["userID"]=>
string(24) "5224b598f86f265801000008"
}
Upvotes: 3
Views: 1888
Reputation: 4173
The Problem:
NSArray* appData
that is inserted into @"share":appData
somehow is translated into a multitude of little arrays.
The solution:
Somehow if I insert a NSArray
to the Key-Value NSDictionary @"share"
it doesn't work as expected. Then I went on changed that NSArray
into a NSDictionary
that didn't work either.
What worked is the code below. I had to recreate NSArray* appData
as NSDictionary* appData2
. Then I had to wrap what would be each individual NSDictionary data object
into another NSDictionary
but I had to give this new object an explicit numeric index... After doing that it would then send the information correctly.
I guess that my problem is a bug? I don't really know... but if anyone has the problem too, this could help you.
NSArray* appData = [myModel getAllStatsData];
if (!appData) {
return;
}
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat: @"yyyy-MM-dd HH:mm:ss"];
NSMutableDictionary* choa = [[NSMutableDictionary alloc]init];
int i = 0;
for (StatsAppUsage*statObj in appData) {
[choa addEntriesFromDictionary:@{[NSNumber numberWithInteger:i]:@{@"date":[dateFormat stringFromDate:statObj.date],
@"name":statObj.name,
@"timeSpent": statObj.timeSpent
}
}];
i++;
}
NSDictionary* appData2 = [[NSDictionary alloc]initWithDictionary:choa];
NSDictionary* params = @{ @"userID": myUser.userWebID,
@"authCode": myUser.authToken,
@"interact":@{@"action":@"uploadAppStats",
@"actionTarget":@"uploadAppStats"},
@"share":appData2
};
@"share" PHP output
(
[0] => Array
(
[date] => 2013-09-09 19:52:31
[name] => selectRoutine
[timeSpent] => 3
)
[1] => Array
(
[date] => 2013-09-09 19:52:33
[name] => manageRoutines
[timeSpent] => 2
)
Upvotes: 2
Reputation: 5453
I think the issue comes about because you're using a default HTTP POST with arguments to send your value. You can confirm this by printing out the content-type of the post on the server side; it should be something along the lines of x-www-form-urlencoded
. If that's the case, that data format can't really express arrays and dictionaries well. So you get the odd format you're seeing on the server side.
What you probably want to do is send your data as JSON, not as plain form parameters. I believe the thing you want to do is set the parameterEncoding
property of your AFHTTPClient
to AFJSONParameterEncoding
. This will send your request as JSON, which is capable of representing arrays and dictionaries correctly on the wire.
Upvotes: 0