Foursquare API UIWebView - iphone

As suggested here "https://developer.foursquare.com/overview/auth" I get the access token in a webview and then I close the browser by after getting the accesstoken:
- (void)webViewDidFinishLoad:(UIWebView *)webView {
NSString *URLString = [[self.webView.request URL] absoluteString];
NSLog(#"--> %#", URLString);
if ([URLString rangeOfString:#"access_token="].location != NSNotFound) {
NSString *accessToken = [[URLString componentsSeparatedByString:#"="] lastObject];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:accessToken forKey:#"access_token"];
[defaults synchronize];
[self.webView removeFromSuperview];
}
}
a similar example "https://github.com/anoopr/core-data-talk/blob/master/example/Classes/FoursquareAuthViewController.m"
But once I remove the webview, I get a dark screen. Which makes sense because I dont have a view anymore. But i probably should do something like [self.view addSubview:self.Anotherview], I am not sure what that Anotherview should be. Can I just segue to another ViewController?
I am pretty new to IOS so any help would be much appreciated.

You can put whatever you want after removing the UIWebView from the view. For example, if you just want to display a map, you can add a map view, or even easier, you can have a map view and a web view on top if you are using the interface builder, and removing the web view will leave you with the map view. But if what you have on the web view's view controller (the view controller that you've put the web view) is irrelevant of what you are trying to achieve after you get the access token, the cleanest way is just storing the access token somewhere else (e.g. App delegate class) performing a segue to another view controller, and using the token from there for whatever you need. You don't even need to deal with removing the web view from superview, you are already leaving that view controller and segueing to another one. Especially, when you are a beginner, as long as you can use storyboards, segues, and NIBs, go with them, try to do stuff in Interface Builder visually rather than trying to remove/add views/viewcontrollers (yes, it is also possible) within the code.

Related

How to add Pop up Button in UIWebView

The deafult pop up is get opened when I long press the music play option in any url from UIWebView.
I Want to add one more button in the pop up..Is it possible to do it..
Like I want to add FETCH button.
And Can I make changes in the default pop up functioning which is OPEN and COPY. shown below
I come to know that by google -
First of all, you really can’t add additional menu items to the default ones of the standard contextual menu. But you can switch off the contextual menu using a certain CSS property. So the solution would be to switch off the default menu and implement your own from scratch. And to implement your own contextual menu, you have to first catch the tab-and-hold gesture, get the coordinates of the finger on the screen, translate these coordinates into the coordinate system of the web page and finally look for the HTML elements at this location.
NEW ANSWER:
Looks like this is what we want, here:
https://stackoverflow.com/a/3198220/700471
OLD ANSWER:
Okay, after some research, here's the deal:
What you describe in your question seems accurate:
First of all, you really can’t add additional menu items to the
default ones of the standard contextual menu. But you can switch off
the contextual menu using a certain CSS property. So the solution
would be to switch off the default menu and implement your own from
scratch. And to implement your own contextual menu, you have to first
catch the tab-and-hold gesture, get the coordinates of the finger on
the screen, translate these coordinates into the coordinate system of
the web page and finally look for the HTML elements at this location.
So you are planning on implementing your own popover controller with contextual menu--fine, I won't get into that at all, I will assume you know how to do that.
What your question seems to be is, how do you take a long-tap gesture in the UIWebView and transform it into the coordinates of the webpage to find the DOM element that was selected, and use that as a context from which to generate your popover menu.
What I found was this, specifically this with this line of code:
NSString *js = [NSString stringWithFormat:#"document.elementFromPoint(%f, %f).innerHTML", touchPoint.x, touchPoint.y];
That looks like the JS you would need to figure out what element had just been long-pressed, and of course you would need to do some figure-figure to see if it was a link and execute your context menu from there, but that's not something I've looked into.
Some further thoughts:
Probably the easiest course would be to attach a UILongPressGestureRecognizer to your UIWebView (this can be done easily in a nib) and make sure that the "Sent Action" points to an appropriate IBAction on your ViewController. (I suppose you could use the delegate outlet as well, but I have never needed to do that.)
In any case, you can use the locationOfTouch:inView: method of your gesture recognizer, and the view you will probably want to use will be the UIWebView's content view, which I believe you can get with something like myWebView.scrollView.subviews[0] (or the objectAtIndex: variation if you are not using the new array index subscripts).
Anyway, I think I have provided enough to answer your question.
EDIT:
Okay, so you are still having trouble with this, so I went and made a test project and got it to work. One thing that is slightly annoying about this is that WebKit somehow adds a "buffer" area around objects in the DOM, meaning that if you touch slightly next to a link it will still highlight, but when you use the JS command elementFromPoint it doesn't do that, so you kinda have to touch more carefully to trigger the popup using this method. But, it works.
I made a blank project with the "single view" template, and threw a UIWebView into the xib, pointed its delegate outlet to File's Owner. Then I put a UILongPressGestureRecognizer into the xib, attached to the UIWebView. I set its delegate as File's Owner, and set its selector outlet to the longPressDetected IBAction in File's Owner. I also unchecked "Canceled in View" in the recognizer's properties in Interface Builder.
Here is the code for the view controller.
Interface:
//
// WVTViewController.h
// WebViewTest
//
#import <UIKit/UIKit.h>
#interface WVTViewController : UIViewController <UIWebViewDelegate, UIGestureRecognizerDelegate>
#property (nonatomic, weak) IBOutlet UIWebView *myWebView;
#property (nonatomic) BOOL didFirstLoad;
- (IBAction)longPressDetected:(id)sender;
#end
Implementation:
//
// WVTViewController.m
// WebViewTest
//
#import "WVTViewController.h"
#interface WVTViewController ()
#end
#implementation WVTViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// Just load google.
NSURL *theURL = [NSURL URLWithString:#"http://www.google.com"];
NSURLRequest *request = [NSURLRequest requestWithURL:theURL];
[self.myWebView loadRequest:request];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
if (!self.didFirstLoad) {
// Disable the default contextual menu.
[webView stringByEvaluatingJavaScriptFromString:#"document.body.style.webkitTouchCallout='none';"];
}
}
// Called by the gesture recognizer.
- (IBAction)longPressDetected:(UILongPressGestureRecognizer *)sender
{
if (sender.state == UIGestureRecognizerStateBegan) {
NSLog(#"Long press detected.");
CGPoint webViewCoordinates = [sender locationInView:self.myWebView];
NSLog(#"WebView coordinates are: %#", NSStringFromCGPoint(webViewCoordinates));
// Find the DOM element
NSString *locatorString = [NSString stringWithFormat:#"document.elementFromPoint(%f, %f).innerHTML", webViewCoordinates.x, webViewCoordinates.y];
NSString *result = [self.myWebView stringByEvaluatingJavaScriptFromString: locatorString];
NSLog(#"Element Found: %#", result);
}
}
// Necessary or the gesture recognizer won't call the IBAction.
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer
{
return YES;
}
#end
As I said, I tested the above code and it works fine. You can of course change up your JS and use something other than innerHTML, such as tagName or href or whatever you like. Multiple checks may be necessary for what you're trying to do, possibly with queued JS commands (which would be lame), unless you could JSON-stringify the DOM object, pass it back to the Objective-C, convert to native objects and perform your checks in that environment--but, I'm no JS pro and I'm not going to investigate that.
As a note, I was a bit surprised that the coordinates that worked for elementFromPoint were the touch coordinates within the UIWebView itself. I had rigged up a whole block of code that iterated through myWebView.scrollView.subviews and found the content view, then called locationOfTouch:inView: on that view. But I was getting funky behavior, so on a hunch I used the webview coordinates and it worked fine, even on a big webpage when I was scrolled off to the side and down. I suspect that some kind of Apple-programmed behavior inside the webview may translate those coordinates. Possibly the JS's coordinate system is altered based on the way the content view is moved around inside the scrollview--that makes the most sense to me.
The proper and accurate way to answer this question is below link
http://www.icab.de/blog/2010/07/11/customize-the-contextual-menu-of-uiwebview/
you can fire the event with something like this:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
if( navigationType == UIWebViewNavigationTypeLinkClicked )
{
// Handle your URL click here (open the popup menu)
// ...
return NO;
}
return YES;
}
don't forget to delegate the UIWebView

How to make a favourite list iphone

I am making an app that has two tabs, one of which is a "favourite" tab. In the other tab called "search", I have a list of results displayed in a table view, when you tap one, you get to see the detail of that particular result. What I'm trying to do here is, there is a button in the detail view, when it is pressed, the current result gets sent to the "favourite" tab. I tried to use delegate to pass the information, but it didn't work out. Here is my code:
DetailViewController.m
-(IBAction) addSomething {
[self.delegate detailViewController:self addToFavourite:self.something];
}
FavouriteViewController.m, implement the delegate method:
- (void) detailViewController:(DetailViewController *)detailViewController addToFavourite:(Something *)something{
detailViewController.delegate = self;
[thingsList addObject:something];
[theTableView reloadData];
}
Everything is built and fine, but when I click "add" button in the detail view, the data doesn't get sent to "favourite" tab's view. Can anyone help me with this one? Do I need to use core data in this case, I never used core data before. Thanks.
One way to do it that is drop dead easy is storing your information in NSUserDefaults.
NSUserDefaults *defaults = [NSUserDefaults standardDefaults];
[defaults setObject:thingsList forKey:#"myData"];
[defaults synchronize];
When you load your data up in your other tab, just fill it from user defaults.
NSUserDefaults *defaults = [NSUserDefaults standardDefaults];
otherData = [defaults objectForKey:#"myData"];
I probably abuse user defaults more than I should, but it makes for a very easy way to store your data locally and have it persist between runs. It will also backup with iTunes for added persistence. Hope this helps.

How do i update webview from settings preferences

very simple question. I have an app with a single view (webview) that loads a url. The app has a settings bundle attached to it with one field asking for a string. Here is the code in my viewcontroller:
-(void)viewDidLoad{
[super viewDidLoad];
NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
NSString *settingString = [prefs stringForKey:#"name_preference"];
[prefs synchronize];
[webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"http://www.stackoverflow.com/%#", settingString]]]];
}
So Far So good right. It takes the string from settings and concatenates the end of the url and all is well. when i run in the simulator i have to close the sim everytime to update the view if i change the string in settings. Is there somewhere else i should put this code instead of "viewDidLoad"? I want my webview to update everytime i re-open my app from settings. Thanks for all of your help....
You can put it in viewDidAppear (in the vc) or applicationDidEnterForeground in your app delegate.
The problem you're having is when you 'launch' the app by tapping it on the home screen, you're actually just using iOS's multitasking to switch back to it (it never quit).
What Alex said will work. But Apple will never accept an app with only one UIWebView. I hope there's more to your app if you're hoping to publish it.

Getting variables from one view to another

I realise that there are other topics like this, but none of them really help. I'm trying to get variables from one view into another, but I have absolutely no idea how.
To give some backstory, my game is a fruit ninja like game where stuff goes on the screen and you have to slice it. If 3 sprites leave the screen unsliced, the game is over and it flips to the game over view screen with a button to go back. Additionally, this SHOULD go to the "flipSideView", which is the highscore, but my implementation of the flipSideView transition doesn't work. This isn't the main issue, the main issue is that I don't know how to get the score from the game in the mainView (which stores it as an int) into the flipSideView (which has the player name).
The main view changes to the gameOverView through this condition in the tick method (which performs regular checks and methods for the game)
if (lifeCounter < 1)
{
gameIsOver = YES;
[self showInfo:0];
[self viewGameOverScreen];
}
That goes to the gameOverView, which will sit there until the replay button is pressed with:
- (IBAction)replayAction:(id)sender
{
[self.delegate gameOverViewControllerDidFinish: self];
}
gameOverViewControllerDidFinish restarts the game and dismisses the view.
- (void) gameOverViewControllerDidFinish: (GameOverViewController *) controller
{
[self restart];
[self dismissModalViewControllerAnimated: YES];
}
The restart method just resets the 3 primary values in the main view (The score, the level, the lives).
As it restarts, the game should take the score and whatever name is stored in the text field in the flipSideView (which can be viewed at any one time gameplay) and store it somehow for future reference. It's not supposed to store it in a file yet because that's next week's task.
I don't wanna post the entire program due to plagiarism issues, but if there are additional parts that might make it easier to understand, I will definitely post them.
Thanks in advance,
Christian
Use Search
NSUserDefaults *currentScore = [NSUserDefaults standardUserDefaults];
[currentDefaults setFloat:yourScoreVariable forKey:#"HighScore"];
[currentDefaults synchronize];
Above to store the score.
Below to retrieve the score.
CGFloat fltHighScore;
NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
fltHighScore = [currentDefaults floatForKey:#"HighScore"];
Suggestion:
You could put the variable in your Controller class,where they both could access.
It is always better to have sharable data in Controller then views if data has to be shared among views.
Update the shareable data through delegate method.
You can use your app delegate for this. You need to declare your variable there, and then you can access this in the following way throughout your whole app:
TestAppDelegate *appDelegate = (TestAppDelegate *)[[UIApplication sharedApplication] delegate];
NSString *string = [appDelegate.Placemarks objectForKey:appDelegate.title];
Don't know if it's the best way tough...
Luck with it!

Put a link on home screen of my app and connect it to WebView

In my app i want to put my website's url on home screen and on clicking on it i want it to be open as a WebView.
How should i go for this.
Thanks,
Previous commenter is incorrect. You can open any hyperlink either externally with Safari or internally with a UIWebView.
Add a UIWebViewController to your project. Then, instantiate an instance of a the UIWebViewController that will be shown inside your app--you'll do this by declaring a property & synthesizing it within your main view controller (which will need to be declared as a UIWebViewDelegate), such as:
#interface MyMainViewController: UIViewController <UIWebViewDelegate> {
// Your implementation code here
}
When a user taps the button (assuming you make it a button, rather than just a text hyperlink), you instruct your app to add the UIWebView to the view stack, loading the correct link. You'll want to either do this within a modal view or within a navigation stack so your users can get back out of the web view, of course.
In your MyMainViewController implementation file, something like this:
-(void) showWebView {
// NOTE: I have not tested this, just prototyping
// off the top of my head
UIWebView *myWebView = [[UIWebView alloc] init];
myWebView.delegate = self;
NSURL *homeUrl = [[NSURL alloc] initWithString:#"http://example.com"];
NSURLRequest *homeRequest = [NSURLRequest requestWithURL:homeURL];
[myWebView loadRequest:homeRequest];
[self.presentModalViewController: myWebView animated:YES];
// Don't forget to release objects when you're done
[myWebView release]; // etc.
}
Now, this is off the top of my head from what I know and have done. But I hope you get the general idea. I offer no warranty of any kind here, but do guarantee this is entirely possible with minimal headache. If you get stuck, check out the developer references for UIWebView. Apple's docs are top-notch & show great examples to get you up and running quickly.
Best.