user3207681
user3207681

Reputation: 21

Objective-C URL Request while locking iPhone

I'm coding an iOS App which uses an URL Request to a PHP document to send and receive data. Here is my code.

    NSString *myRequestString = [NSString stringWithFormat:@"userid=%@&recieverid=%@&messege=%@&type=%@&password=%@", ownID, _friendID, content_encoded, msg_type, password];
    NSData *myRequestData = [NSData dataWithBytes: [myRequestString UTF8String] length: [myRequestString length]];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL: [NSURL URLWithString: @"something.php"]];
    [request setHTTPMethod: @"POST"];
    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"content-type"];
    [request setHTTPBody: myRequestData];

    //My activiy Indicator starts here

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        // Now send a request and get Response
        NSData *returnData = [NSURLConnection sendSynchronousRequest: request returningResponse: nil error: nil];
        NSString *result = [[NSString alloc] initWithBytes:[returnData bytes] length:[returnData length] encoding:NSUTF8StringEncoding];

        //Here some internal coding happens...

        dispatch_async(dispatch_get_main_queue(), ^(void) {

            //Stopping activity indicator

        });
    });

But if the user locks his Phone while he sends the data (possible in other apps like Snapchat etc as well) the app freezes when the user returns and has to reopen it. I want to know if theres a better way of doing if the app connects to the Server and the user closes the app that doesn't let this error occur.

Thank you :) Anton And sorry about my poor english Im not a native speaker.

Upvotes: 0

Views: 234

Answers (2)

Rob
Rob

Reputation: 437622

I'd suggest:

  1. Specifying a background task identifier, as suggested by John Woods, so that if the user leaves the app in the middle of the request, it will attempt to continue the network request in the background.

  2. Use sendAsynchronousRequest rather than dispatching sendSynchronousRequest to the background.

  3. Make sure you correctly detect and handle errors (because it's not entirely clear to me whether the problem rests in the code of your question or whatever processing you're doing with it later).

  4. Unrelated, but I'd avoid using the bytes-related NSData methods.

Thus:

// I'm guessing that you're percent encoding `messege` [sic], but I'd do it for all of those parameters (notably password)

NSString *myRequestString = [NSString stringWithFormat:@"userid=%@&recieverid=%@&messege=%@&type=%@&password=%@", ownID, _friendID, content_encoded, msg_type, password];

// Use `dataUsingEncoding` rather than bytes rendition:
//
//     NSData *myRequestData = [NSData dataWithBytes: [myRequestString UTF8String] length: [myRequestString length]];

NSData *myRequestData = [myRequestString dataUsingEncoding:NSUTF8StringEncoding];

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL: [NSURL URLWithString: @"something.php"]];
[request setHTTPMethod: @"POST"];
[request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"content-type"];
[request setHTTPBody: myRequestData];

// start background task

UIBackgroundTaskIdentifier __block task = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
    [[UIApplication sharedApplication] endBackgroundTask:task];
    task = UIBackgroundTaskInvalid;
}];

// activity indicator starts here

[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
    if (!data) {
        NSLog(@"%s: sendAsynchronousRequest error: %@", __PRETTY_FUNCTION__, connectionError);
    } else {

        // use NSData rendition rather than bytes rendition:
        //
        //     NSString *result = [[NSString alloc] initWithBytes:[returnData bytes] length:[returnData length] encoding:NSUTF8StringEncoding];

        NSString *result = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];

        // here some internal coding happens...
    }

    // stop activity indicator here

    // stop background task

    if (task != UIBackgroundTaskInvalid) {
        [[UIApplication sharedApplication] endBackgroundTask:task];
        task = UIBackgroundTaskInvalid;
    }
}];

Upvotes: 6

Woodstock
Woodstock

Reputation: 22926

You have to implement a background task. When the phone locks, all apps transition to a background "inactive" state. You need to implement a long running background task.

https://developer.apple.com/library/ios/documentation/iphone/conceptual/iphoneosprogrammingguide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html

Upvotes: 0

Related Questions