-1

I have wrote this code to do an HTTP request to a server that sends to me a json string:

-(NSDictionary*)doRequestWithCommand:(NSString*)command andBody:(NSString*)requestBody {
    __block NSDictionary *result = nil;
    NSURL *URL = [NSURL URLWithString: [NSString stringWithFormat:@"%@%@", PREFIX_URL, command] ];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL
                                                           cachePolicy:NSURLRequestUseProtocolCachePolicy
                                                       timeoutInterval:60.0];
    [request setHTTPMethod:REQUEST_TYPE_POST];
    [request setHTTPBody:[requestBody dataUsingEncoding:NSUTF8StringEncoding]];
    dispatch_semaphore_t sem = dispatch_semaphore_create(0);
    __block BOOL done = NO;
    while ( !done ) {
        NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
            if ( data != nil ) {
                result = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
                NSLog(@"%@", [[NSString alloc] initWithData:data encoding:4]);
                NSLog(@"len %lu", [[[NSString alloc] initWithData:data encoding:4] length]);
                done = YES;
            }
            dispatch_semaphore_signal(sem);
        }];
        [dataTask resume];
        dispatch_semaphore_wait(sem, DISPATCH_TIME_FOREVER);
    }
    return result;
}

This code works fine with iOS 9 and lower, but with iOS 10 no! Practically the answer from the server is cut 1610th character!

I don't know what is the matter! Can you help me?

Thanks

frank
  • 15
  • 3
  • You should examine the error object returned by `dataTaskWithRequest`. Is that `nil`? Also, you should capture the error object returned by `JSONObjectWithData` and see if that's `nil` or not. Whenever code doesn't work, the first thing you should do is start examining the error objects. – Rob Oct 10 '16 at 22:10
  • Is `result` reference `nil`? If `nil`, I'd suspect some problem in the JSON response from the server. Are you building this JSON manually, or are you using API to build that for you? Again, if there is a problem, the error object returned by `JSONObjectWithData` will tell you what, if anything, is wrong with the JSON. – Rob Oct 10 '16 at 22:12
  • The error is nil! And the answer (result) isn't nil, but is cut from iOS. The answer is generated from the server and is complete and correct! If I try to do a request from a rest client the answer is correct and not cut, so the problem is iOS, but I don't know what is it! – frank Oct 11 '16 at 09:43
  • Note that with iOS this code works perfectly! – frank Oct 11 '16 at 10:04
  • I'd suggest watching this with [Charles](http://charlesproxy.com) or [WireShark](https://www.wireshark.org) and looking at the actual response you got. If the network response was cut off, not only would you have gotten some error in the data task's completion handler, but the parsing of the JSON would have failed, too. I suspect that the actual response from the server is shortened for some reason, perhaps something to do with the nature of the request. By using Charles or Wireshark, you can identify precisely what went down the wire and what came back. – Rob Oct 11 '16 at 15:33
  • 1
    The problem can be that in your console doesn't print all the response!!! Try with the debugger if the String arrives! Don't trust into prints! ;-) – Francesco Scala Oct 11 '16 at 15:24
  • Hi @frank, did you found a solution? Currently I am facing same problem. I am contacting Twitter api, and my nsurlsession result is cut off midway. It works on simulator but only on device it is cut offf. – GeneCode Dec 24 '16 at 03:32
  • 1
    @GeneCode Francesco Scala gives the answer: The problem can be that in your console doesn't print all the response!!! Try with the debugger if the String arrives! Don't trust into prints! ;-) – – frank Jan 29 '17 at 00:25
  • @frank exactly that was my problem. NSLog doesnt print all response. Wasted days for this problem alone RIP XCode T_T – GeneCode Jan 29 '17 at 05:04

1 Answers1

0

This entire use of dispatch_semaphore_t is wrong, and you should never have been doing it in the first place. If you need to do something after the data arrives, do that in the completion handler, just after the line where data is set; don't play silly semaphore games and try to do it after the completion handler. You cannot return a result from a method that uses asynchronous networking, based on the data from that networking. You cannot.

matt
  • 447,615
  • 74
  • 748
  • 977
  • 3
    You are correct that he should not use a semaphore, but doesn't answer the question. The semaphore wouldn't account for the behavior he describes. – Rob Oct 10 '16 at 22:07
  • @Rob I don't know that. Maybe the semaphore is being unlocked and that's why his data is curtailed. – matt Oct 10 '16 at 23:11
  • Tbh this should probably be a comment Matt ;) Got flagged in the low quality posts. I'll leave it here, but hopefully you can migrate it to a comment. – brandonscript Oct 11 '16 at 17:36