UIWebView capture post - objective-c

I am looking for a starting point on a project that needs to display a UIWebView on an iPad. THe catch is that the HTML will be generated by the pad and displayed in the UIWebView, and will contain many input controls.
What is needed is a way to grab the contents of these controls after the user has completed entry similar to how I would do it on a server. I need to grab this entered data on the iPad without an actual submit.
Does anyone know the starting point for this type of interaction?

You can do this by implementing the UIWebViewDelegate delegate's shouldStartLoadWithRequest method:
- (BOOL)webView:(UIWebView*)webView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
{
NSData* data = request.HTTPBody;
NSString* s = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if([s length] == 0)
return YES;
else
return NO;
}
It works fine with a post.

Within the previously posted article it also mentioned the UIWebViewDelegate method,
webView:shouldStartLoadWithRequest:navigationType:
This gets invoked on the delegate before a link is followed. I haven't tried it, but this method might be invoked when submitting the form. Use a GET method. Easier than having to loop out of the app and back.

It can be done in simple way..
we know HTTP request contains -
Method (GET,POST..etc)
HTTP header
HTTP body
we can check header field value for Conent-type if it is x-www-form-urlencoded
then form field values are sending thru them as key=value pairs
then we can catch therse paires in
webView:shouldStartLoadWithRequest:navigationType: - in request parameter as
[request HTTPBody], similarly we can get method [HTTPMethod]..etc
if it is simply GET method then all pairs will be in request itself.
:) hope it helps

Here's a way to do it:
Register a custom URL scheme for your App (see here f.e. http://iosdevelopertips.com/cocoa/launching-your-own-application-via-a-custom-url-scheme.html)
When the user touches your save/submit/whatever button you read out the values of all needed form-fields, construct a url that matches your URL scheme and redirect to this URL with JavaScript (window.location) and work with the data in Objective-C and do what you have to do.
Example URL could be: myapp://value_of_field1/value_of_field2/...
See the linked tutorial on how to register a custom scheme and how to retrieve the data in Obj-C.

Related

Pulling usable text from URL like Pocket and Instapaper

I know that this question has been posed for C# and possibly other languages but I haven't found one for Objective-C (Xcode)
The C# question can be found here C# Version
Im looking to be take any URL (NSURL or NSString) and convert that webpages contents into.
1) The Title of that webpage (New article title)
2) The Image for that article (First major image)
3) The Article text itself (Pure text, no ads)
Those are the 3 major things. Id also like to have the
1) Author
2) Date Updated
3) Website that posted the article
but those are not as important.
The way I have my code set up to parse the actual article (which doesn't do the job I want exactly) is:
- (void)viewDidLoad {
[super viewDidLoad];
NSURLRequest *request = [NSURLRequest requestWithURL:finalUrl];
[self.webview loadRequest:request];
}
- (void)webViewDidFinishLoad:(UIWebView *)webView {
NSString *fullArticle = [self.webview stringByEvaluatingJavaScriptFromString:#"document.body.innerText"];
self.story.text = fullArticle;
NSLog(#"Article: %#",fullArticle);
}
finalUrl being a NSURL variable.
The NSLog shows all the text from the inner body of the webpage but includes a lot of extra "garbage" that I don't want, It also doesn't give back the title, images or anything else that I wanted.
So how can this be done in objective-C? I know that Pocket does it very well in there app.
Readability.com has an incredible API that allows for this.
Its called the Parser API.
Steps:
Create an account on readability
Go to the Developer section
Generate Tokens
Use readability API url with your token and the URL you would like to parse.
It will return a HTML page filled with everything you want.

The correct way to design data loading and object creation

I'm working on an app for iphone where I load a JSON from a php server, parse it with a library and create an object with this data. My code works fine but the way I do it seems wrong to me:
A viewController shows to the user a loading view. Meanwhile the ViewController makes the get request and receive the data.
The VC parse the response and get a dictionary
The dictionary is send to a "creator class" who returns a object created from the dictionary
I do two times this operation but I think it's a bad design:
Should a View Controller do a http request? Don't shoud be a "objectLoader"? The main method of creation class makes a big bunch of if/else spaghettis, like:
for(NSString key in dictionary){
if(key isEqualToString "a key"){
perform action
}
else if(key isEqualToString "an other key"){
perform action
}
....
}
Any idea to solve that? I was thinking about make a dictionary of keys/selectors to solve it and do something like:
for(NSString key in dictionary){
[self performSelector:[selectors getObjectForKey:key]]
}
But I don't know if I can reference a selector in a dictionary...
Finally the other option that comes to me is send the parsed dictionary to the object with a class method like: [ClassName createObjectWithDictionary:parsedDictionary]. That's a good way to do it?
I know the question is a little ambiguous but I'm a little lost in what Design patterns I should apply and who is responsible of what in this story
the best way is to use MVC pattern and have model with data that has methods to push and remove some data inside it and a list of delegates (derived from UIViewController) which are notified in case of changed model data.
Controller (not UIViewController) is something that initiates fetching data from server and handles results.
And all of UIViewControllers handles data changes and user interaction.
For now, write some RequestController (singletone or not, doesn't matter) that handles request routines and stores all necessary data to trigger events in controller.
You can use blocks or NSNotificationCenter to handle request's completion.
After getting necessary data through RequestController from request, your Controller can create necessary parsers and push parsed data into model.
Personally, I would NOT let the ViewController do the HTTP request. I always write service classes in my apps, that do the low level stuff and inform the caller (e.g. a view controller) via delegation on any received result.
So the control flow in that case is:
-> ViewController locks screen with loading message
-> calls service with itself as delegate - the service does the work and receives the answer -> the answer is processed and the result passed to the delegate
-> the ViewController takes the response, removes the loading message and does whatever is necessary with the response.
Concerning your second question: yes, it is possible to dynamically chose a selector out of a dictionary - e.g. by storing the selector's name in the dictionary and then use
SEL selector = selectorFromString(#"doWork");
to create the right selector to call.

Sending multiple url requests with NSURL Connection

I need to send data many times within one view. I have about 6 UISwitches and every time there value gets changed, I need to send (via a POST method) data (a simple NSString) to my php script (http://www.mydomain.com/script/dowork.php)
I have been struggling over the last couple of days in doing this since I have only managed to get this to work with only 1 switch but not when users change multiple switches. If someone can please give me an example of how to do this it would mean a lot.
EDIT
This is how Im doing it now:
-(IBAction)switchSelector:(id)sender {
switch ([sender tag]) {
case 0:
if (switchMax.on) {
//here I Send it to the method that will make the connection
[self registerWithServer:#"Tokens"];
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[defaults setBool: switchMax.on forKey: K_SWITCH_KEY];
[defaults synchronize];
} else {
//other stuff
}
break;
}
}
How did you manage to do it with one switch? Could you post the code as well?
For multiple switches just hook up your method with the valueChanged in interface builder. Inside that method check which switch is on - if ([mySwitch1 isOn]), edit your NSString and send it.
Just some thoughts, but do you really need to send the changes to your server immediately? Assuming that these switches are used in some settings panel, you could save the settings once the user is done with the panel and send it to your server, e.g. when they press the Done button or exit from this view. This way, you only send the request once without having to be burdened with sending it multiple times.
Keep in mind that the user is on a mobile device and you should try to keep data usage as low as possible.

How to send information and receive from an website trough xcode

How can i send information and receive information from a website without "downloading" the file once and then using it. Like, every time I push on a button, i could receive what the text on the website is trough the code, and not by UIWebView.
And also, if i have a textfield, i could type some text in and then push at a button, and send this text to the website, in some kind of way.
Could someone give me an example of this?
By the way, sorry for my english. Let me know if it was something you didn't understand.
NSString has a method + (id)stringWithContentsOfURL:(NSURL *)url encoding:(NSStringEncoding)enc error:(NSError **)error that you can use for grabbing text in a very simple way. To upload the text you could use NSURLRequest together with NSURLConnection.
There are also this framework that might do stuff you'd like: http://restkit.org/
You can use NSURLConnection for grabbing stuff from HTML requests. You can read the Apple documentation on NSURLConnection here.

Simplest way to get a long URL for a shortened URL in Cocoa?

What is the simplest way to retrieve the original URL for a short URL in Cocoa? Anything that can be done in just a few lines?
UPDATE: I just saw your comment and realised it's following the redirect.
See the delegate method: connection:willSendRequest:redirectResponse:, which tells you it's doing a redirect to this new request, based on the previous response.
You can get the expanded URL either from the new request here, or from the Location header of the redirect response.
Discussion If the delegate wishes to
cancel the redirect, it should call
the connection object’s cancel method.
Alternatively, the delegate method can
return nil to cancel the redirect, and
the connection will continue to
process. This has special relevance in
the case where redirectResponse is not
nil. In this case, any data that is
loaded for the connection will be sent
to the delegate, and the delegate will
receive a connectionDidFinishLoading
or connection:didFailLoadingWithError:
message, as appropriate.
Original answer follows...
Use NSURLConnection with a delegate. In your delegate's connection:didReceiveResponse: method, fetch allHeaderFields and read the value of the "Location" header.
Something like:
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
NSLog(#"Expanded URL = %#", [[(NSHTTPURLResponse *)response allHeaderFields] objectForKey:#"Location"]);
}
I'd create a little URLExpander class to do this personally, with a signature something like:
+(void)asyncExpandURL:(NSURL *)aURL didExpandTarget:(id)target selector:(SEL)selector;
Then just pass back two arguments in your message, one for the short URL, one for the long.
there is no simple way, you have to request the short-url-providing-server and get the full url. This must be done with a url connection and maybe some logic behind to get the redirect link (I haven't tried yet)
If you don't want to make the request and follow the redirects, a simpler way is to use a link-lengthening service. Here are two simple APIs:
http://longurl.org/api/#expand-url
http://www.longurlplease.com/docs
I may post some code snippets soon especially if there is interest.