UIWebView enable/disable back/forward buttons - objective-c

On the iPad I get weird situations with enabling and disabling the back/forward buttons. When web view starts and finishes the load, I check to enable/disable them based on canGoBack and canGoForward. But most of the time the buttons are enabled when they shouldn't be and disabled when they shouldn't be. Like on google, if I type something, no delegates are called so the buttons are disabled. In Safari their back/forward button changes. And if I go to a page on google, then back twice I'm on the first page again and my back button is still on. Is there a way to know when going back a page finished loading (seems like it doesn't call the delegate on back?) or know when canGoBack and canGoForward change YES/NO?

The delegate methods – webViewDidStartLoad: and – webViewDidFinishLoad: are not called sometimes, like on a google search. but i found out that – webView:shouldStartLoadWithRequest:navigationType: is called, so i can change the buttons and page title from that method now.

Related

Custom "undo" for Webview

OK, here's the situation. I have:
A Webview
Lots of NSTextFields
Other unrelated controls
Normally, the Edit > Undo menu item links to First Responder's undo: action. And everything works fine + you can even "undo" while typing in an NSTextField.
Now, what if I want to handle this "undo" action, in a different way, only for my WebView.
I've been thinking of two approaches:
Link the "Undo" item to a custom action and check who is the First Responder. If it's the Webview, then do what needs to be done. Else, "pass" the event to the control. (However, when attempting a [FIRST_RESPONDER performSelector:#selector(undo:)], first it doesn't seem to recognize the selector and last but not least nothing happens.)
Link the "Undo" to the first responder's undo:(as usual), subclass the Webview and add a custom - (void)undo:(id)sender action. In that case though, when the webview is active, the "Undo" item is grayed-out, so I can't do anything whatsoever, not even check whether the custom method would be called.
Suggestions? How would you go about that?
What am I missing?
I think this is the answer: https://developer.apple.com/library/mac/documentation/Cocoa/Reference/WebKit/Protocols/WebEditingDelegate_Protocol/
Also reference this: Removing undo actions for a WebView's NSUndoManager

View size when subclassing PFLogInViewController

When subclassing PFLogInViewController for customization. How do I change the size of the view?
I have looked at this tutorial: https://parse.com/tutorials/login-and-signup-views
but it does not seem to have the answer.
My app is based on a UITabBarController and one of the tabs needs log in.
Nevertheless if the user cannot log in, he should still be able to use the other tabs.
In the present situation, when the user taps on the tab asking for login; he has to log in or kill the app to get out. Because the PFLogInViewController takes up all the screen and there is no way out by hitting a different tab (all covered).
This is obviously not very nice.
How can I keep the tabs at the bottom visible?
I tried to change the self.view.frame or the self.logInView.frame in the viewDidLoad method of my PFLogInViewController subclass, but it seems to have no effect at all.
Then you should make your app so that it doesn't start with the login viewcontroller, but rather opens to the parts that are available to all. Include some button or other mechanic to take the user to the login page.
You could include a button on the login page that says "Use the app anonymously" or similar, which triggers a segue to a main view. On subsequent app launches, the user is taken to this main view immediately. You would still need a way for the user to login later on.

Prevent multiple IAP alert view

I have a UIButton that trigger the IAP process. There is some time (2/3s or more if internet connection is bad) before an alert view is displayed (either asking for id and password, or the confirmation one). So one may click several times, thinking that the button is not working. And then you get as much alert view in a row as times you clicked and they are shown even if I quit the app and I'm on another meanwhile. That's pretty annoying.
My solution so far is to set a boolean as property of the UIviewcontroller. If it's false, click does nothing, else click trigger payment process. I set it to false on first click and in viewwillappear i get it back to true. The problem is that to be able to click the button again you must leave view and come back to it. That's not cool...
So here is what I'm looking for ideally : a function that is triggered as soon as any alert view of any kind is shown or dismissed. Show is better because i could use that to stop an eventual activity indicator I'd like to add too.
Thank you for you ideas.
Don't base it on the alert view being shown (you can't anyway). Instead, when the button is pressed, disable it or hide it (and show your activity indicator). When you start the purchase, add your controller as the delegate. Use the delegate methods to update the UI to enable / show the button (or remove it all together if more appropriate) when you get the callbacks which tell you the purchase is complete / failed.

Fullscreen ad causing keyboard to not appear

My iOS app sometimes displays a Greystripe fullscreen ad on startup. If this ad shows, then when I dismiss it, later I will tap a textfield in a UIWebView but the keyboard won't show up. However, if the Greystripe ad DOESN'T appear, then all is well and the keyboard will show up as expected.
After doing some research I think it has something to do with Greystripe making itself the first responder, but I'm not sure how to fix this.
Edit:
I use adwhirl and so to get the startup ad I do exactly as it says here: http://wiki.greystripe.com/index.php/AdWhirl
The UIWebView is inside another controller that is presented with presentModalViewController:animated: from the main view.
I narrowed the problem down: the problem is caused after initiating Greystripe, which occurs either from the full screen startup ad that I initiate manually or from AdWhirl automatically initiating it to display a 320x50 Greystripe banner.
After hours of debugging I finally figured it out. I use SVProgressHUD to show loading status while my UIWebView is loading. SVProgressHUD.m makes itself the key window, then when it is dismissed, it returns the key window status to the "topmost" window. For some reason Greystripe, unlike all the other ad networks I'm using, makes itself the topmost window. So the problem could be Greystripe making itself too important, or SVProgressHUD miscalculating the topmost window!
To solve this, I had to manually make my view controller which contains my UIWebView the key window every time after dismissing SVProgressHUD:
[SVProgressHUD dismiss];
[self.view.window makeKeyWindow];

Delay navigationController to pop detailView of UITableView

Im looking for some help regarding to put a save like confirmation if some changes where made to a UITextField and UISegmentedControl.
Can I prevent the UINavigationController from pop the view? And then pop based on buttons in a AlertView?
I use the UITextField and UISegmented control to POST data to a webservice.
I perhaps need to use a modalView for this? but wanted first to see if someone have another idea, because I would like to keep navigation clicks down if possible.
Any suggestions for this?
Thanks,
Why not just using a UIAlertView?
EDIT: On second thought, and re-reading your question + comment, I would recommend to use a Modal View with classics OK/Cancel buttons + a UIAlertView(s) for confirmation(s). (UIAlertView "poping" on OK/Cancel is easy to do via UIAlertViewDelegate)
That's what Modal views are for, block UI until some user action has been completed. Like a form. This is how I do all my forms, and how Apple does (just look at the create mail screen for an example, or any form of iOS apps)
Adding a "Magical" action requiring user interaction on the back button of a navigation controller is bad in terms of user experience, if you hit back, you expect the view to pop, nothing else. I would then be surprised if Apple SDK even allows to cancel that event...
You can do what you would like without the need of a modal view.
First, you can use your text field's UITextFieldDelegate to set a flag in your controller when the field content is modified. You can reset this flag when the data is sent out.
Then you could override your UIViewContorller's viewWillDisappear to show an alert to the user in case new data have not been posted at the moment the view is going to disappear and give him the possibility of sending it to the server. This method will be called when you move to a different controller in your navigation UI, and you will not have a chance to "reject" the operation.