iphone - iOS7 NSURLConnection sendAsynchronousRequest failed with POST data -
my problem adopt [nsurlconnection sendasynchronousrequest...] post method fails on ios7 failed succeeds on ios6 environment.
other information:
in ios6 environment can json data server this. (successful)
{ "status": 200, "data": [ { "oauth_token": "bvgoa01tg6jvfuxopojs8wb26tpvaads" } ] }same code on ios7 error message. (failed)
error:error domain=nscocoaerrordomain code=3840 "the operation couldn’t completed. (cocoa error 3840.)" (no value.)
i check server side php code, found server can data ios6 post data, can't post data ios7. (same code different result, strange.)
have can me or suggestion me? lot.
my code below (updated v3, successful)(thanks rob' answer)
- (void) apilogin { nsdictionary *params = @{@"client_id" : @"1234567", @"response_type" : @"token", @"redirect_uri" : @"/oauth2-php/server/examples/pdo/", @"state" : @"test_state", @"scope" : @"", @"accept" : @"yep", @"uid" : uid, @"pwd" : withpwd}; nsdata *postdatastring = [self dataforhttppost:params]; // server api 位置 nsurl *url=[nsurl urlwithstring:@"http://xxx.xxx.tw/xxx.php"]; nsmutableurlrequest *request = [nsmutableurlrequest requestwithurl:url cachepolicy:nsurlrequestuseprotocolcachepolicy timeoutinterval:120]; [request seturl:url]; // solution3: nsstring *postlength = [nsstring stringwithformat:@"%d", [postdatastring length]]; [request sethttpmethod:@"post"]; [request setvalue:postlength forhttpheaderfield:@"content-length"]; [request setvalue:@"application/x-www-form-urlencoded" forhttpheaderfield:@"content-type"]; [request sethttpbody:postdatastring]; [nsurlconnection sendasynchronousrequest:request queue:[nsoperationqueue currentqueue] completionhandler:^(nsurlresponse *response, nsdata *data, nserror *connectionerror) { nsinteger responsecode = [(nshttpurlresponse *)response statuscode]; nslog(@"d1: responsecode: %d", responsecode); if (!connectionerror && responsecode == 200) { // 採用apple官方方法將 來源轉成json format並交由nsdictionary 接手. nserror *localerror = nil; nslog(@"data:%@", data); nsdictionary *allindic = [nsjsonserialization jsonobjectwithdata:data options:nsjsonreadingmutablecontainers error:&localerror]; nslog(@"source:%@", allindic); nslog(@"error:%@", localerror); // 取出oauth_token資料 if ([[allindic objectforkey:@"status"] integervalue] == 200) { // 將新取得之 oauth_token 寫入db nsarray * dataarray = [allindic objectforkey:@"data"]; nsdictionary *responsedata = [dataarray objectatindex:0]; nsstring *t = [responsedata objectforkey:@"oauth_token"]; [helper setdboauthtoken:nil :t :table_user_profiles]; nslog(@"(api-new)oauth_token:%@", t); } else { nslog(@"connectionerror=%@", connectionerror); nslog(@"responsecode=%d", responsecode); } } }]; } - (nsdata *)dataforhttppost:(nsdictionary*) parms { nsmutablearray *array = [nsmutablearray array]; (nsstring *key in parms) { id obj = [parms objectforkey:key]; nsstring *valuestring; if ([obj iskindofclass:[nsstring class]]) valuestring = obj; else if ([obj iskindofclass:[nsnumber class]]) valuestring = [(nsnumber *)obj stringvalue]; else if ([obj iskindofclass:[nsurl class]]) valuestring = [(nsurl *)obj absolutestring]; else valuestring = [obj description]; [array addobject:[nsstring stringwithformat:@"%@=%@", key, valuestring]]; } nsstring *poststring = [array componentsjoinedbystring:@"&"]; nslog(@"new2a httppost data:%@", poststring); return [poststring datausingencoding:nsutf8stringencoding]; } - (ibaction)loginaction:(id)sender { [self apilogin]; } below code debugging output on ios6
new2a httppost data:response_type=token&uid=xxx&accept=yep&scope=&client_id=1234567&state=test_state&redirect_uri=/oauth2-php/server/examples/pdo/&pwd=xxx d1: responsecode: 200 data:<7b227374 61747573 223a3230 302c2264 61746122 3a5b7b22 6f617574 685f746f 6b656e22 3a224870 47366546 4b304a37 38434343 54306352 506e4d77 62544d5c 2f455631 32793422 7d5d7d> source:{ data = ( { "oauth_token" = "hpg6efk0j78ccct0crpnmwbtm/ev12y4"; } ); status = 200; } error:(null) (api-new)oauth_token:hpg6efk0j78ccct0crpnmwbtm/ev12y4 below code debugging output on ios7
new2a httppost data:response_type=token&uid=&accept=yep&scope=&client_id=1234567&state=test_state&redirect_uri=/oauth2-php/server/examples/pdo/&pwd= d1: responsecode: 200 data:<> source:(null) error:error domain=nscocoaerrordomain code=3840 "the operation couldn’t completed. (cocoa error 3840.)" (no value.) userinfo=0x8a28d90 {nsdebugdescription=no value.} connectionerror=(null) responsecode=200 thanks rob big helps, problems solved. root course below code. in ios6 can uid/withpwd default value when no input on "idfield.txt" field. in ios7 code can't default value (uid/withpwd). rob problem solved.
nsstring *uid = idfield.text; nsstring *withpwd = pwdfield.text; // testing account id if (!uid||!withpwd) { uid=@"xxx@gmail.com"; withpwd=@"xxxx"; } nslog(@"uid:%@ , pwd:%@", uid, withpwd); updated problem code fine work on ios6 & ios7
// testing account id if ([uid isequaltostring:@""] || [withpwd isequaltostring:@""] ) { uid=@"xxx@gmail.com"; withpwd=@"xxxx"; }
you logging data, want @ string representation of that. @ resulting string , see in response server. way, if server failed , returned non-json error message, can see string was.
likewise, might want log connectionerror if it's not nil. that's not case here (otherwise, wouldn't have gotten current nslog, it's worthwhile @ if it's not nil). thus:
if (!connectionerror && responsecode == 200) { // 採用apple官方方法將 來源轉成json format並交由nsdictionary 接手. if (data) nslog(@"data string: %@", [[nsstring alloc] initwithdata:data encoding:nsutf8stringencoding]); else nslog(@"data nil"); nserror *parseerror = nil; nsdictionary *allindic = [nsjsonserialization jsonobjectwithdata:data options:nsjsonreadingmutablecontainers error:&parseerror]; nslog(@"source:%@", allindic); nslog(@"error:%@", parseerror); // 取出oauth_token資料 if ([allindic[@"status"] integervalue] == 200) { // 將新取得之 oauth_token 寫入db nsarray * dataarray = allindic[@"data"]; nsdictionary *responsedictionary = dataarray[0]; nsstring *t = responsedictionary[@"oauth_token"]; [helper setdboauthtoken:nil :t :table_user_profiles]; nslog(@"(api-new)oauth_token:%@", t); } } else { nslog(@"connectionerror=%@", connectionerror); nslog(@"responsecode=%d", responsecode); } i suspect once @ string representation of data, problem may become self-evident.
by way, it's unlikely issue, make sure you're encoding strings you're adding postdata. example, if password contains ampersand, plus sign, space, or other reserved character (as described in section 2.2 of rfc2396), current code not work. may want apply cfurlcreatestringbyaddingpercentescapes value add postdata, example can use nsstring category so:
@implementation nsstring (urlpostencode) - (nsstring *)stringforhttppost { nsstring *result = cfbridgingrelease(cfurlcreatestringbyaddingpercentescapes(kcfallocatordefault, (cfstringref)self, (cfstringref)@" ", (cfstringref)@";/?:@&=+$,", kcfstringencodingutf8)); return [result stringbyreplacingoccurrencesofstring:@" " withstring:@"+"]; } @end i combine following nsdictionary category:
@implementation nsdictionary (urlpostencode) - (nsdata *)dataforhttppost { nsmutablearray *array = [nsmutablearray array]; [self enumeratekeysandobjectsusingblock:^(id key, id obj, bool *stop) { nsstring *valuestring; if ([obj iskindofclass:[nsstring class]]) valuestring = obj; else if ([obj iskindofclass:[nsnumber class]]) valuestring = [(nsnumber *)obj stringvalue]; else if ([obj iskindofclass:[nsurl class]]) valuestring = [(nsurl *)obj absolutestring]; else valuestring = [obj description]; [array addobject:[nsstring stringwithformat:@"%@=%@", key, [valuestring stringforhttppost]]]; }]; nsstring *poststring = [array componentsjoinedbystring:@"&"]; return [poststring datausingencoding:nsutf8stringencoding]; } @end having 2 categories, can like:
nsdictionary *params = @{@"client_id" : client_id, @"response_type" : response_type, @"redirect_uri" : redirect_uri, @"state" : state, @"scope" : scope, @"accept" : accept, @"uid" : uid, @"withpwd" : withpwd}; nsdata *postdata = [params dataforhttppost];
Comments
Post a Comment