UIMenuController Editing Menu in UIWebView only appears second time - objective-c

I am finding that in my app in iOS 9, when I long press in a UIWebView, the editing menu that normally appears, only appears the second (and following) times that I long press. The first time I long press in any particular webview no menu at all shows, although the selection handles do appear. The second time I long press in any partiular webview, it behaves as expected.
Another strange symptom is that occasionally (but not every time) as the menu appears, something quickly animates sliding of towards the left of the screen, originating from the menu, but it is too fast to see what it is. It happens even when the edit menu appears as it should. I expect this is related to the issue.
I have only tested in the simulator because I haven't installed iOS 9 on a device yet.
In iOS 8 the same menu works as expected.
Another developer gave me a work around, which may work when you have only one UIWebVeiw on screen. Put this in viewDidAppear (thanks Chen Xian'an):
[[myWebView.scrollView.subviews firstObject] becomeFirstResponder];
[[NSOperationQueue mainQueue] addOperationWithBlock:^{
[self becomeFirstResponder];
}];
However, since I have more than one webView it is not an ideal solution for me. And if I apply it to each webview it only works on the last one I apply it to.
This appears to be a bug, and hopefully Apple will fix it soon, in the meantime, does anyone have any bright ideas as to how I could make this work for more than one webView?

I tried in this way, and I succeeded.
First
You must custom UIWebView and write
- (BOOL)canBecomeFirstResponder {
return YES;
}
Second
You must call this methods before handle your long press
[yourWebView becomeFirstResponder];
I hope it would help..

In my case the problem that was the UIWindow where the UIWebView was apparently not the key window. What i did to solve it was to add a call to [webView.window makeKeyAndVisible] at the webViewDidFinishLoad method.
- (void)webViewDidFinishLoad:(UIWebView *)webView {
// Fix
[webView.window makeKeyAndVisible];
}

Related

UITextField losing firstResponder after view appears

I have a UIPageViewController. One page has a single button, and the other page has a UITextField with a button. When the page scrolls to the view with the field, I'd like it to becomeFirstResponder and open the keyboard. Here's what happens:
I call [self.locationQuery becomeFirstResponder] ViewController's viewDidAppear method. But it never opens the keyboard.
I do the same in viewWillAppear, and it appears briefly, but then is quickly dismissed.
If I'm on the page with the text field, and pull the page partway and let it go (without changing pages), self.locationQuery receives focus just fine.
It seems like something else is grabbing firstResponder status from the field, but I haven't the faintest idea what, and why it would only be happening when the page changed (rather than revealed after a failed page turn). Any ideas?
Update
I created a way to crawl the views to see if any other views were, indeed, taking firstResponder (from an answer to this question: Get the current first responder without using a private API). Results:
When I explicitly give first responder to the text field, the method reports it has first responder status.
When I don't, it returns null.
Now I'm even more confused.
I don't really understand the nature of what was causing my issue, but I was able to fix it by wrapping the call in an async dispatch in viewDidAppear:
dispatch_async(dispatch_get_main_queue(), ^{
MapManualViewController *strongSelf = weakSelf;
[strongSelf.locationQuery becomeFirstResponder];
});
This one stole a few hours from my life. Here is the Swift 3.x implementation.
DispatchQueue.main.async(execute: {() -> Void in
let strongSelf: MapManualViewController = self
strongSelf. textField.becomeFirstResponder()
})
I also put it in viewDidAppear

Double tap UISearchBar with search delegate on iOS 7 causes UISearchBar to disappear

We have a search bar in the table header. When the user taps on it twice quickly on iOS 7, it disappears. Does anyone have any suggestions what we are doing wrong?
After lots of trial and errors, I found that when searchDisplayController ends search, searchbar gets disappear, so I have reinserted the searchbar to table header and it worked for me.
- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller
{
self.searchingFetchedResultsController = nil;
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
[self.tableView insertSubview:self.searchDisplayController.searchBar aboveSubview:self.tableView];
}
return;
}
Hope this helps.
(I posted this same answer to Troubles with UISearchBar \ UISearchDisplayViewController, which seems like a duplicate of this question.)
I encountered the same issue, and noticed that searchDisplayControllerDidEndSearch was being called twice. The first time, the superview of self.searchDisplayController.searchBar is the UITableView, and the second time it's still a UIView.
With Priya's answer, I worry about unintended consequences or unneeded overhead from re-inserting the subview every time the search bar is double-tapped, and I also worry about it breaking with future iOS versions. Fortunately, we can take advantage of the superview strangeness like this:
- (void)searchDisplayControllerDidEndSearch:(UISearchDisplayController *)controller {
if (self.tableView != self.searchDisplayController.searchBar.superview) {
[self.tableView insertSubview:self.searchDisplayController.searchBar aboveSubview:self.tableView];
}
}
If I had to guess what was happening, the UISearchBar is automatically creating a temporary UIView as its superview when it's active – this is the view seen when the search is being performed. While the UISearchBar is being dismissed, the superview gets set back to be the UITableView it had before, unless it gets dismissed so quickly that it was never properly initialized, in which case it cleans up improperly and the UITableView never gets the UISearchBar back as its child.
This solution still isn't ideal, and I think Apple must be doing something different in its own apps because their search bar UX feels a bit better. I think it would be better not to handle the second tap in the first place until the UISearchBar was ready. I tried using the other UISearchBarDelegate methods to do this, but I couldn't find an appropriate hook to override the current behavior.

How do I find out whether my UIActivityIndicatorView is working if the page loads too quickly for it to show up in the first place?

I've set a delegate method that starts animating a UIActivityIndicatorView when a UIWebView starts loading and stops animating it when the UIWebView stops loading. NSLogging shows that both delegate methods are being called (i.e., webViewDidStartLoading and webViewDidFinishLoading).
- (void)webViewDidStartLoad:(UIWebView *)webView{
//start animating
[self.indicator startAnimating];
}
-(void)webViewDidFinishLoad:(UIWebView *)webView{
//finish animating
[self.indicator stopAnimating];
}
The problem is that the page finishes loading before the UIActivityIndicatorView shows up. This means that either a) everything is working fine and my connection is quick enough that the UIActivityIndicatorView doesn't need to show up or b) not everything is working fine.
But how do I tell whether it's a) or b)? Is there a way to slow down my connection artificially?
Tunnel the traffic through a slow proxy, so you will have time to see if the indicator shows up.
One way to do that would be to install Charles Proxy, which has a throttling feature. (And is very convienient for other http-network debugging as well).
The equivalent tool on Windows is Fiddler.
I would comment out your call to stopAnimating and see if your activity indicator view is still spinning. If it is then you know its your request that is super quick.
Or change the URL to load a webpage that you know takes a long time to load and see if you notice any difference.
In my app I simply didn't turn off/stop the activity indicator when loading was done and that showed me it was working then I went back and put in the stop. So if it was replacing a button it will still be showing or if it was in an alertview it will still be up on screen.

iOS Developement: App Crashes on Reopen

My app is almost finish but when i am testing it, on first use everything is working well and smooth. But, after closing it from the home button and reopen it when i click my back it;s crashing.
in my back button i only have this code:
[view1 removeFromSuperview];
[view2 removeFromSuperview];
[self view3];
what could be the problem??
Why are you removing views from superview when you push the back button.
also what do you think will happen by saying
[self view3]; ?
I would suggest if you've added views in the viewDidLoad method
that you should remove them using the viewdidUnload method and not in the back button method. As if you try an remove a view that has already been release, your app will crash.
If you're attempting something different then you need to show more code.

iOS 5.1 + UISplitViewController in PortraitMode + UIActionSheet in MasterController = Assertion failure

I have an app based on a UISplitViewController that shows an ActionSheet in the MasterViewController of the Split. Before iOS 5.1, I had no problems presenting the action sheet in the popover presented by the split, but now, apparently there is something wrong with the new "slide-in" way to show the MasterController.
The thing is that when I'm trying to present the ActionSheet, using any [actionSheet show..] method, the app crashes with the following error (The exact Assertion is the following).
*** Assertion failure in -[UIActionSheet presentSheetInPopoverView:], /SourceCache/UIKit_Sim/UIKit-1914.84/UIActionSheet.m:1816
sharedlibrary apply-load-rules all
Error in re-setting breakpoint 1:
Catchpoint 2 (throw)Error in re-setting breakpoint 1:
Error in re-setting breakpoint 1:
Current language: auto; currently objective-c
I google this for a while, but no substantial answers.. some people say it can be a bug in the
new SplitViewController...
Ideas?
Thank you in advance!
UPDATE: I posted a possible generic workaround, check it out. If it works for you, leave a comment.... If its ok, I will mark it as correct in a couple of days
Based on the above, and with massive respect to the Apple engineer who helped me at WWDC, here is the solution which not only works around this bug, but also points the popover at the right button.
if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation]))
{
[actionSheet showFromBarButtonItem:self.actionSheetBarButtonItem animated:YES];
}
else
{
CGRect windowsRect = [self.navigationController.toolbar convertRect:self.actionSheetBarButtonItem.customView.frame toView:self.view.window];
[actionSheet showFromRect:windowsRect inView:self.view.window animated:YES];
}
I have this same problem too.
One workaround which prevents the crash at least is to show your UIActionSheet like this:
if (UIInterfaceOrientationIsLandscape([[UIApplication sharedApplication] statusBarOrientation])) {
[self.actionSheet showFromBarButtonItem:sender animated:YES];
} else {
[self.actionSheet showInView:self.view.window];
}
So in portrait mode, the action sheet is displayed in the center of the window. Not ideal, but at least it doesn't crash. And when in landscape mode, it behaves as normal.
Just as omz commented, it seems this issue has been solved in iOS 5.1.1 by apple.
So I decide to just add it to known issue section of change log for my app, and the workaround is to suggest the users to upgrade to iOS 5.1.1.
Another option to keep the popover affect of pointing at a particular option, you can actually do the following:
1. Create your own UIPopover
2. Create your own UIViewController inside of the UIPopover.
3. Display the UIActionSheet inside the newly created UIViewController.
4. SetPopoverContentSize from the UIActionSheet's Size.
5. Lastly, Wire your UIActionsheet's Clicked method to dismiss the popover.
Takes a little more code, but gives you the same functionality you had before for the most part, and has a cool little slide-in effect for the UIActionsheet.
I think the following is a generic solution based on Tap Form's answer:
CGRect windowsRect = [actionSheetContainerView convertRect:viewToPresentActionSheet.frame toView:actionSheetContainer.window];
[actionSheet showFromRect:windowsRect inView:actionSheetContainer.window animated:YES];
This will resent the actionSheet in the window, but pointing the right direction