0

I have a simple task, send one variable to a php page via GET. Nothing I seem to find works, and all are seemingly more than I need.

It seems I need code to set NSURL string, NSURL request, then execute.

Can someone perhaps paste me some simple code to just execute a URL like this:

http://localhost/trendypieces/site/ios/processLatest.php?caption=yosa

Thanks!

Here's the most current iteration of something that doesn't work, seems closer though as it actually throws back the error alert. Dunno what that error is...but....

//construct an URL for your script, containing the encoded text for parameter value
    NSURL* url = [NSURL URLWithString:
                  [NSString stringWithFormat:
                   @"http://localhost/trendypieces/site/ios/processLatest.php?caption=yosa"]];

    NSData *dataURL =  [NSData dataWithContentsOfURL:url];
    NSString *serverOutput = [[NSString alloc] initWithData:dataURL encoding: NSASCIIStringEncoding];

    if([serverOutput isEqualToString:@"OK"]) {

        alertsuccess = [[UIAlertView alloc] initWithTitle:@"Posted" message:@"Done"
                                                 delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];

    } else {
        alertsuccess = [[UIAlertView alloc] initWithTitle:@"Error" message:@"Done"
                                                 delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil, nil];

    }
    [alertsuccess show];
harp
  • 129
  • 1
  • 14
  • Have a look at https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/URLLoadingSystem/Articles/UsingNSURLSession.html and ask specific questions if you don't understand anything. Just asking for code is against the spirit of the site. – Abizern Mar 28 '14 at 23:09
  • possible duplicate of [Append data to a POST NSUrlRequest](http://stackoverflow.com/questions/6148900/append-data-to-a-post-nsurlrequest) – Dominik Hadl Mar 28 '14 at 23:17
  • ok then, adding code. i've tried SOOO many iterations of this code in the past 10 hours I'm not sure if its even useful. It just seemed like a very basic question for someone with experience. Sorry to have offend you. – harp Mar 28 '14 at 23:19
  • Nobody is offended, just normal practice at SO to flag similar questions :) – Dominik Hadl Mar 28 '14 at 23:22
  • @DominikHadl That post is a very different topic: That's because someone was trying to do a `POST` request with parameters in the URL (which is wrong, it should be in the body). But this question is about adding parameters to a `GET` request, and if he really wanted to do `GET` it _has to_ be in the URL, not the body, precisely the opposite scenario as suggested by that other question. I suspect the problem here may be the fact that he's starting connection two times, or something else. But not because he didn't put the parameters in the body. – Rob Mar 29 '14 at 00:57
  • @harp Did you implement `connection:didFailWithError:`? What `NSError` did that report? Also, I assume you're running this on the simulator (as `localhost` would not work from the device). – Rob Mar 29 '14 at 01:02

3 Answers3

2

A couple of points:

  1. When you create a NSURLConnection with initWithRequest:delegate:, it automatically starts the connection. Do not call the start method yourself (in some cases, it can interfere with the initial connection). That is only intended for when you use initWithRequest:delegate:startImmediately: with NO for that final parameter.

  2. You then say:

    Current code that yields no active result (from within an IBAction function)

    Your code would not yield any "active result" within the IBAction method. It would call the NSURLConnectionDataDelegate and NSURLConnectionDelegate methods. Have you implemented them? Notably, make sure you also implement connection:didFailWithError:, which will tell you if there were any connection errors.

    If you need the result in the IBAction method, you should use the NSURLConnection method sendAsynchronousRequest.

  3. Going to the title of this question, "how to send a variable", you should be careful about just adding user input to a URL. (This isn't your immediate problem why you're not getting any reply, but this is important when sending the contents of a variable to a web server.)

    Notably, the caption=xxx portion, the xxx cannot contain spaces or reserved characters like +, &, etc. What you have to do is percent-encode it. So, you should:

    NSString *caption = ... // right now this is @"yosa", but presumably this will eventually be some variable
    
    NSMutableData *data = [[NSMutableData alloc] init];
    self.receivedData = data;
    // [data release];  // if not ARC, insert this line
    
    //initialize url that is going to be fetched.
    NSString *encodedCaption = [self percentEscapeString:caption];
    NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"http://localhost/trendypieces/site/ios/processLatest.php?caption=%@", encodedCaption]];
    
    //initialize a request from url
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    
    //initialize a connection from request
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    self.connection = connection;
    // [connection release]; // if not ARC, insert this line
    
    // DO NOT start the connection AGAIN
    //[connection start];
    

    Where that percentEscapeString is defined as:

    - (NSString *)percentEscapeString:(NSString *)string
    {
        NSString *result = CFBridgingRelease(CFURLCreateStringByAddingPercentEscapes(kCFAllocatorDefault,
                                                                                     (CFStringRef)string,
                                                                                     (CFStringRef)@" ",
                                                                                     (CFStringRef)@":/?@!$&'()*+,;=",
                                                                                     kCFStringEncodingUTF8));
        return [result stringByReplacingOccurrencesOfString:@" " withString:@"+"];
    }
    

    (Note, there is a promising NSString method, stringByAddingPercentEscapesUsingEncoding, that does something very similar, but resist the temptation to use that. It handles some characters (e.g. the space character), but not some of the others (e.g. the + or & characters).)

  4. Finally, you say that this is a GET request (which, implies you're not changing anything on the server). If it really is a GET request, see my prior point. But if this request is really updating data, you should be doing a POST request (where the caption=yosa goes in the body of the request, not the URL). This has another advantage as there are limitations as to how long a URL can be (and therefore what how long the parameters can be when you submit them in the URL in a GET request).

    Anyway, if you wanted to create a POST request, it would be like:

    NSString *caption = ... // right now this is @"yosa", but presumably this will eventually be some variable
    
    NSMutableData *data = [[NSMutableData alloc] init];
    self.receivedData = data;
    // [data release];  // if not ARC, insert this line
    
    //create body of the request
    NSString *encodedCaption = [self percentEscapeString:caption];
    NSString *postString = [NSString stringWithFormat:@"caption=%@", encodedCaption];
    NSData *postBody = [postString dataUsingEncoding:NSUTF8StringEncoding];
    
    //initialize url that is going to be fetched.
    NSURL *url = [NSURL URLWithString:@"http://localhost/trendypieces/site/ios/processLatest.php"];
    
    //initialize a request from url
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPBody:postBody];
    [request setHTTPMethod:@"POST"];
    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];
    
    //initialize a connection from request
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    self.connection = connection;
    // [connection release]; // if not ARC, insert this line
    
  5. While your initial code sample was using a delegate-based NSURLConnection, you've revised your answer to use dataWithContentsOfURL. If you really don't want to use the delegate-based NSURLConnection, then use its sendAsynchronousRequest instead, which offers the simplicity of dataWithContentsOfURL, but allows you to use either GET or POST requests, as well as performing it asynchronously. So, create the NSMutableURLRequest as shown above (use the appropriate method code depending upon whether you're GET or POST), eliminate the lines that instantiate the NSMutableData and the NSURLConnection and replace that with:

    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
    
        if (!data) {
            NSLog(@"Error = %@", connectionError);
    
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:@"Error" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
            [alert show];
    
            return;
        }
    
        NSString *serverOutput = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
    
        NSLog(@"Data = %@", serverOutput);
    
        UIAlertView *alert;
    
        if ([serverOutput isEqualToString:@"OK"]) {
            alert = [[UIAlertView alloc] initWithTitle:nil message:@"Posted" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        } else {
            alert = [[UIAlertView alloc] initWithTitle:nil message:@"Not OK" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
        }
    
        [alert show];
    }];
    
Rob
  • 371,891
  • 67
  • 713
  • 902
  • Thanks. I've tried all of these,many errors.Don't care if POST or GET,just want to send one variable to page. Insertion php page works whether I hit it POST or GET, takes anything. When I try the last code there,POST method, I get these errors: self.receivedData = data;...'prop not found on AppViewController' [data release];...'ARC forbids explicit message send of release' NSString *encodedCaption = [self percentEscapeString:caption]; .. gets 'no visible @interface for 'APPViewController' declares the selector self.connection = connection;...'prop not found' [connection release];...several – harp Mar 29 '14 at 04:15
  • @harp I don't understand the errors you provide, because your code sample would have generated the same errors. E.g., your code sample had `release` statements in it, so I assumed you weren't using ARC. If you're using ARC, remove those `release` statements. Your code sample referenced the `receivedData` and `connection` class properties, so I assumed you had such properties (`NSMutableData` and `NSURLConnection` properties, respectively). Add them if you don't have them. Re the `percentEscapeString` method warning, did you add that method (provided in my answer, above)? – Rob Mar 29 '14 at 04:33
  • Re `GET` or `POST`, I don't care which you use either. Obviously if you're updating the server, you should use `POST`. If you're just retrieving data, you should use `GET`. I'm just suggesting that you make sure that you pick one and use the appropriate method for setting the parameter (the body data for `POST`, the URL for `GET`). And change the PHP code accordingly (`$_POST` or `$_GET`, as appropriate). The only reason I belabored that point was that the other, well-intentioned, answer just got that backwards. – Rob Mar 29 '14 at 04:37
  • haha yeah i saw that that! those errors are just what immediately popped up when i pasted your code. I did add the trailing method which resolved a few errors not all. So I should have added a library or include for NSMutableData and NSURLConnection ? – harp Mar 29 '14 at 04:42
  • and btw i tried another chunk of code that may be getting closer, I edited the original post at the top to show it. It at least recognizes some sort of failure. lol. – harp Mar 29 '14 at 04:43
  • 1
    @harp I notice that you've now changed this to use dataWithContentsOfURL. Two points there. First, you can't do `POST` requests that way (which is ok if you've concluded `GET` is sufficient). Second, it's inadvisable to use synchronous network calls (your app will freeze during the network operation). Use `[NSURLRequest sendAsynchronousRequest:...]` (see point 6 above) if you don't want to avoid complications of the rich, delegate-based `NSURLConnection` API. – Rob Mar 29 '14 at 05:13
  • arg...i appreciate your comments but this isn't helping. There is no point 6 above. I can't tell what in that last code specifies get or post. i never would have thought such a simple task would so hard. i've been programming for years and years, this shouldn't be so difficult. – harp Mar 29 '14 at 14:43
  • @harp Point 5, above. – Rob Mar 29 '14 at 14:54
  • ok so i replaced with your code from number 4, added the escapeString function, now i have just two red errors: self.receivedData = data; === Property 'receivedData not found on object 'APPViewController' self.connection = connection; === Property 'connection not found on object 'APPViewController' – harp Mar 29 '14 at 15:09
  • @harp Let's step back for a sec: If you use option 4, that means that you have implemented the `NSURLConnectionDelegate` and `NSURLConnectionDataDelegate` methods. Have you? Then you must have property for the `NSMutableData` already defined, no? What did you call it, if not `receivedData`? I'm confused by your question about these two lines from my code sample, because these two lines are from _your original code sample._ lol. If you haven't implemented the delegate-based `NSURLConnection` code, then it might be easier to pursue option 5. – Rob Mar 29 '14 at 22:09
0

So the main problem was trying to hit localhost from the phone and not the simulator, duh. The code that runs successfully now is below. Thanks to all for the help.

NSURL *url = [NSURL URLWithString:@"http://localhost/trendypieces/site/ios/processLatest.php?caption=mycaption"];

    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setURL:url];
    [request setHTTPMethod:@"GET"];

    returnData = [[NSMutableData alloc] init];
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:YES];
harp
  • 129
  • 1
  • 14
0

Here it is adapted for POST with two variables, thanks to @Rob for code from another post.

NSURL *url = [NSURL URLWithString:@"http://192.168.1.5/trendypieces/site/ios/processLatest.php"];

    NSString *var2 = @"variable2";
    NSString *postString    = [NSString stringWithFormat:@"caption=%@&var2=%@", _captionField.text, var2];
    NSData   *postBody      = [postString dataUsingEncoding:NSUTF8StringEncoding];

    //initialize a request from url
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    [request setHTTPBody:postBody];
    [request setHTTPMethod:@"POST"];
    [request setValue:@"application/x-www-form-urlencoded" forHTTPHeaderField:@"Content-Type"];

    //initialize a connection from request, any way you want to, e.g.
    NSURLConnection *connection = [[NSURLConnection alloc] initWithRequest:request delegate:self];
harp
  • 129
  • 1
  • 14