UIWebView freezes when text is selected - ios

My app, on very rare occasions, freezes when I select text in a UIWebView. Here's how it happens:
Tap and hold to select text
Text gets selected
Whole app freezes, unresponsive to touch, but I can still see operatings running
May freeze for around 10s. After that the UIMenuController appears. If I try to scroll while it is freezing, the scrolling happens after the app is responsive again
If the text is still selected, it freezes again if I scroll. Happens again and again
If I managed to scroll the selected text out of the view, scrolling the rest of the webview is fine, until I scroll the selected text back
If I get out of the UIViewController containing the UIWebView, I can confirm that they are both deallocated. Go back into a new UIViewController with UIWebView and it happens again.
This continues to happen with new instances of UIWebView, and even when I close and resume the app. Only stops if I force a restart of the app.
Does anyone have any clue how I can debug this? I've never seen this in simulator. Only happens very rarely on device.

I suspect you either have set up your view hierarchy improperly, or have modified it on a thread not the main thread. So tell us exactly where the UIWebView resides (super views), and take a good look at code that modifies sub view arrays.
For instance, you don't add the web view to a UINavigationController's sub views directly, but to its view controllers array etc.
All else fails create a demo project that also displays the problem and upload it to DropBox where we can run it ourselves.

Related

SwiftUI Drag and Drop error "NSInternalInconsistencyException"

I have a swiftUI app that implements the native drag and drop apis. Everything works well but I have discovered an edge case that I don't understand how to fix. Essentially the entire view of the app (the size of the device screen) is a drop target. When dragging an object to be dropped, if the user moves the item to the edge of the screen the app will crash throwing the error:
'NSInternalInconsistencyException', reason: UIDragPreviewTarget requires that the container view is in a window, but it is not
I assume this has to do with the drop target and trying to move the drag object out of the app's window, but I don't know what to do to handle this edge case.
Any help would be greatly appreciated
EDIT:
I commented out the .onDrop() modifier and the crash still persists. I can only guess that the generated UIDragPreviewTarget is tracking its location internally but when it is pulled out of the Frame of the app it throws the error
After digging around a bunch more and creating a new simplified project to demonstrate this wasn't a bug in the Drag and Drop implementation in SwiftUI, I think I found the issue.
In my case I have a view that holds the data I need sitting above the view I want to be able to drag that data into. While in the drag process, I wanted the top view to dismiss itself so as to no longer obstruct the lower view. I was flipping this switch in one of two ways.
when starting the drag process on the original piece of data, I started a timer that would give you 1.5 seconds to cancel the drop before it would hide the view.
when entering the lower view's drop target, it would close the top view
Removing both of these actions eliminated the crash.
My assumption at this point is that hiding the original source of the data is tripping up the dragItem's sense of "home" and when you try and drag it off screen it has no where to return back too.

UIView subviews updating visually but interact as though in previous state

I'm creating a UIViewController that houses some of RosyWriter's functionality, which I'm reworking to create a video recorder. The screen contains a title, a clipped-to-bounds subview that contains the AVCaptureVideoPreviewLayer (so the sublayer CALayer of the video content is added into that subview, so I think it's quite deep-nested), and two buttons acting like a toggle button - in the form of Start and Stop buttons placed in the Storyboard for the UIViewController.
The Start button works fine, even though the video's preview layer is on screen and showing the camera. When I start recording, though, I switch the buttons round, making the Start button hidden and the Stop button hidden=false.
The start button works - this is pressed when the video preview is on-screen and updating, but the actual recording (grabbing samples in buffers and writing them to a file - nothing UIKit related as far as I can see) has not started.
When the video recording is active, with the Stop button showing and the Start button hidden, the visible stop button isn't pressable, but the hidden start button can still be pressed.
I've tried moving the Stop button above the UIView containing the video, in case the CALayer or something else stretches outwith the clipped UIView bounds. This doesn't help. The stop button always acts as though it's not enabled - but it is enabled, and nothing appears to overlap the button. The button works fine if the UIView containing the video (which, I'll reiterate, is lower than the broken button) is never shown.
Can anyone think why this'd happen? I immediately thought about setNeedsLayout and setNeedsDisplay and tried just throwing some of those in, because it's almost as though the view had updated with my request to hide or show buttons, but an interaction layer hadn't updated.
Thanks
I now think this is due to my ignorant use (or misuse) of dispatch queues. I'm still not sure how I was able to interact with buttons that aren't showing - perhaps it's because their own state change responds in part, immediately, and the rest can't take place except on the main queue (the visual refresh, for example).
So I solved the problem, in a sense, by forcing a particular asynchronous delegate method to be called on the main queue. This doesn't affect the operation of this particular step in my recording process.

iOS View Controller is only accepting touches in a certain portion of the window

I have a relatively simple dialog/popup style UIViewController that isn't behaving correctly. I have many others just like it (though each with a unique button layout) that work just fine. For some reason that I cannot figure out, this controller is only accepting touches within (approximately) the green shaded area.
Note that none of these colors are the actual colors, just placeholders. Same goes for the text.
Tapping in the "Search..." text field does nothing. Tapping on the "Cancel" button does nothing. No UI reaction whatsoever.
The tableview will scroll just fine (there are over 100 rows) if it's touched inside (approximately) the green region. Touching the tableview below the green results in no response. Same thing for the "Cats" button. It reacts when touched in approximately the top half, but nothing in the bottom half.
I've banged my head against the wall for the requisite "several hours" and am getting nowhere.
It seems that part of your view controller's view is overlapped with some "harmful" view/views. Maybe this view is created programmatically and is not visible in IB. You should start with checking your views hierarchy. Put breakpoint in your view controller's code. Somewhere, where you are sure all views (normal and harmful) are already created and type in debug area
po [self.view recursiveDescription]
you should receive something like
Now try to find harmful views. Temporarily delete some "normal" views could be a good idea.
I found my solution. I have a method that launches a dialog controller given the dialog to launch and the parent (up until this point, always a full-screen view controller). The parent gets darkened and the dialog gets launched on the center of the screen.
This one wasn't working because I was launching it from an existing dialog; I was telling the dialog launcher that the new dialog's parent was the current dialog, not the whole screen. This means that the new dialog (which is bigger than the first one) launches at the correct size, but only accepts input inside the area of the "parent" dialog, which is the smaller one underneath it.
Fix: Launch the new dialog using the current dialog's parent (which is full screen) and it works fine. The green zone on my image is the approximate size of the dialog that was being used as the parent, which is why input was only being accepted in that area.

How to automatically load subviews for testing?

I'm writing an iOS app that has a problem on a view that's about 4 taps deep into the UINavigation stack. It's becoming a pain to have to repeatedly tap tap tap through the simulator to drill down to the UIViewController I need every time I want to run the thing.
Is there a way to automate this?
I tried just instantly calling [self tableView:self.tableView didSelectIndex... manually, however that blows up because data hasn't been loaded into the table yet...
I'd prefer something fast w/o a lot of overhead to it - otherwise it'll take more time to implement the solution than I'd save by not tapping the screen 4 times...
Thanks for any insight you guys can provide.
I do this all the time - in the appDelegate, I just add some code wrapped in a #ifdef that just makes the subview the initial view of the navigation controller. Once you get the subview working you can turn the ifdef off. Using the technique will save you lots of time - in fact I'm using it right now to add functionality to my app in the store.

Copy and Paste sometimes don't appear in my UITextView

I created an app with a UITextView and occasionally it won't show the Select, Copy, Paste menu items when I tap on text. If I double-tap the home button and close the app, then re-open it, I'm able to do it again, which makes me think it's a memory problem (if it doesn't have enough memory, it doesn't show the menu?)
The problem in my case is that I created a UIWindow to cover the main window. I gave that window a windowLevel of UIWindowLevelAlertView / 20, so that it would hover between the main window and alert views. However, occasionally, AlertViews upon releasing key window, would revert the key window to my cover, and not the main window, and that would invalidate the menu controller's ability to properly display itself over the UITextView that was sitting in the main window.

Resources