I'm working on an iPad app which is based on a UIWebView: to explain it in the simplest possible terms, the app shows one big interactive webview and in addition it supports custom gestures.
I need to catch events that represent single taps on the webview, but only when the taps have not already been consumed by the webview (i.e. they are not the beginning of a scroll/zoom operation, they are not taps on links, they are not taps that trigger some javascript).
The UIWebView is very greedy with its events, and in my experience it tends not to propagate them, even when they are not consumed. To catch the events, I ended up subclassing the main UIWindow (see http://mithin.in/2009/08/26/detecting-taps-and-events-on-uiwebview-the-right-way/). This is working well, but the problem is I'm not able to recognize whether the taps I'm getting have triggered some javascript in the webview or not.
As an additional restriction, I have no control over the javascript that's going to run in the UIWebView or the HTML that it's going to be displayed.
So, the question goes like this: what would be a way to detect all and only the tap events which did not trigger any other action in the UIWebView itself, especially javascript actions?
~
Should you be curious, the source code of the project I'm working on is on GitHub: to find it, just ask Google to point you to Baker Framework.
Do this with JavaScript. First, after your webview finishes loading, attach a javascript click handler to the body to soak up any unused clicks. Have it load a made-up domain as it's action:
- (void)webViewDidFinishLoad:(UIWebView *)webView
{
NSString *script = #"document.body.onclick = function () { document.location.href = 'http://clickhandler'; }"
[webView stringByEvaluatingJavaScriptFromString:script];
}
Then in your webview delegate, look out for attempts to load that made up domain and intercept them. You now have a way to intercept that javascript click handler with native code and react accordingly:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
if ([request.URL.host isEqualToString:#"clickhandler"])
{
//handle click
//your logic here
return NO;
}
return YES;
}
Related
I am working on a project using Objective C on macOS. The project is Document-Base Application. Each window contains a WebView. I want to implement copy: cut: and paste: where the menu items for these actions should be enabled/disabled according to the object selected inside the WebView. I started a new Document-Base Application and added the following code inside AppDelegate.m:
- (void)copy:(id)sender {
NSLog(#"%# %s", self, __func__);
}
- (BOOL)validateMenuItem:(NSMenuItem *)menuItem {
NSString *title = [menuItem title];
NSLog(#"%#",title);
return YES;
}
Before I add the WebView to the Document.xib file, everything is working fine and both copy and validateMenuItem functions are called normally. When I add WebView to the Document.xib file, these function stop working. I tried many things (such as override the WebView class) without any success. I know WebView is deprecated, but using WKWebView will cause other issues.
The WebHTMLView inside the WebView is the target for the copy: action. The editingDelegate of the WebView can intercept the copy: action. Implement
- (BOOL)webView:(WebView *)webView doCommandBySelector:(SEL)selector;
The UIDelegate of the WebView can validate the Copy menu item.
- (BOOL)webView:(WebView *)webView validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item defaultValidation:(BOOL)defaultValidation;
I load up a UIWebView in my app which displays html text and a sign out button.
Is it at all possible that when the user taps the html button it can then change the view? ie: it will go back in navigation of the app to the previous view?
Any examples of this being done?
Can this also be done in java for my Android version?
Edit: If I place an event using JS or something on the button can I then use a listener within the app's web view to go back a view?
What you could do is...
When one of your buttons is pressed, it actually attempts to send the user to a new URL (eg, through a href="", or javascript redirect). But, in your app's code you can use UIWebView's delegate methods to intercept the loading of the URL and instead run some app-based code.
Eg.
- (BOOL) webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType {
NSString *_url = [NSString stringWithFormat:#"%#", request.URL];
if ([_url rangeOfString:#"?signout"].location != NSNotFound) {
[self userRequestsLogout];
return NO;
}
return YES;
}
Don't forget that UIWebView also has;
- (NSString *)stringByEvaluatingJavaScriptFromString:(NSString *)script
Hopefully this helps.
There are many tabs in my screen,I want to give an alert box which says "Do you want to save the changes?" if user changes anything in the page, without clicking on the save button provided in the page,he is clicking on diff tab.
I'm able to get the alert view but the tab click moves the screen to the tab which was clicked. The screen should not change until the alert view is answered.
Can anyone let me know how to suppress the screen change until the alert view is answered ?
This doesn't directly answer your question, but: what you're trying to do sounds like bad UI design. (In general, if it feels like you are fighting against UIKit, you're probably doing it the wrong.)
In this case: if you really want to ensure that a user taps a Save button before moving to a different screen, you should present that screen in a modal view, so that it is impossible to navigate to any other part of the app.
In other words, if you want to prevent a user from navigating away from a screen, don't show them buttons or tabs that would allow them to navigate away. Otherwise, you're just making more work for yourself and frustrating a user.
Implement UITabBarControllerDelegate in your app delegate's applicationDidFinishLaunching
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
self.tabBarController.delegate = self;
[window addSubview:self.tabBarController.view];
}
Then use the below delegate method,
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController;
This method is called before the tab switch and you can return no here to disable that and show an alert message instead. Once the user has performed the save either he can press on tab again or you can programmatically switch to the new tab as,
self.tabBarController.selectedViewController = [self.tabBarController.viewControllers objectAtIndex:0];
Add this inside your delegate,
How about this for switching to the tab programmatically,
- (BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController {
if () {
//some code
} else {
//some other code
self.tabBarController.selectedViewController = viewController;
}
}
i have a button in my app a button that submit score to gamecenter and works.
this is the code:
-(void)subScore{
GKScore *scoreRepoter = [[[GKScore alloc] initWithCategory:#"123456"] autorelease];
scoreRepoter.value=100;
[scoreRepoter reportScoreWithCompletionHandler:^(NSError *error) {
if (error!=nil) {
NSLog(#"errr submitting");
}else
NSLog(#"ok!");
}];
now i'd like to submit score before app is closed with home button.
i thought to customize an action of home button (if it is possible)
or perhaps i make the same line of code in viewDidUload...or something like that...
will i be sure that that action will be performed before unloading the app?
i should make that code in dealloc method?
thanks
You can't customize behaviour of Home button directly, but iOS provides some methods in your application's delegate, by which you can control lifecycle of the application.
Method called right before the application goes to background is applicationWillResignActive: in your application's delegate (usually this method is located in AppDelegate.m file).
I think you can get needed effect by calling your method like that:
- (void)applicationWillResignActive:(UIApplication *)application {
[mygame subScore];
}
Also please note that iOS has time limit of execution for this method: you must do all saving-the-game work in less that five seconds or your application will be killed.
I am new to iphone application.I have 6 uiimages in a view.fifth image is facebook and sixth one is twiter.Under images,Iplaced two roundrectbuttons named as click5 and click6. My requirement is,when i click on those images,I have to go to login pages of facebook and twitter.how can i do this?can anyone send me sample example and explain it detai?
If you want to send the user to the website using Safari, you invoke the openURL: method in the UIApplication class, like this:
NSURL *facebookURL = [NSURL URLWithString:#"http://www.facebook.com"];
[[UIApplication sharedApplication] openURL:facebookURL];
When assigning a button to an action, you use the UIButton's addTarget:action:forControlEvents:, providing an event handler as action. Say you're setting this up in viewDidLoad, it might look like this:
- (void) viewDidLoad {
[myButton addTarget:self
action:#selector(btnClicked:)
forControlEvents:UIControlEventTouchUpInside];
}
/**
* Click/tap event handler for some buttons
*/
- (IBAction) btnClicked:(id)sender {
// Check which button was pressed.
if (sender == self.click5) {
// ...
}
else if (sender == self.click6) {
// ...
}
}
You know the very easiest way to do this? With the free 3rd party component ShareKit. It wraps the Facebook and Twitter (and several other social network) APIs to literally make it a three-line deal to post things.
I used it for the first time in the last app I built and I was SHOCKED at how easy to use it was.