My application reads data from MySql server and displays it in a tableview. At the start of the call to the server the application covers the tableView with a view (named "pdView") that has background colour of Light Gray. That view is part of the scene which the tableView is also part of (designed in IB), but is in a hidden state, until just before the call to the server where it becomes visible using
pdView.hidden = false
After the app gets the data and fills the tableview, using
dispatch_async(dispatch_get_main_queue(), { () -> Void in
tableview.reloadData()
})
one can see the data displayed in the tableView, under the gray display.
I then try to hide back the view using
pdView.hidden = true
but it takes the app about 44 seconds for the gray color to disappear. During that time my app behaves normally and I can scroll the table up and down.
I tried putting the code to hide the view inside dispatch_async() but to no avail.
What needs to be done to fix this problem so that the pdView disappear right after it is back to the hidden state?
ALL your UI code needs to be from the main thread. That includes things like changing the state of a view's hidden flag.
Do you have that code wrapped in a call to
dispatch_async(dispatch_get_main_queue()
as well?
It sounds like you are trying to update the UI from a separate thread. You will need to give your pdView.hidden = true some context. You can try
dispatch_async(dispatch_get_main_queue(), { () -> Void in
tableview.reloadData()
self.pdView.hidden = true
})
Note the self in self.pdView.hidden..
Hope that helps.
Related
When WKWebView displays content, it will be white for about 1~2 second. Not a memory problem, I use [self loadHTMLString:string baseURL:baseURL]; show the HTML content, but each time need to wait 1~2 second will be normal display. UIWebview does not have this problem.
Is there any way to solve it? Or optimize this blank time?
Sometimes it takes a while to load a page over the network. The page is white until the data can be loaded. A simple solution is to issue your load() command early. Before it needs to be called. I anticipate the next page, but don't display it until it is needed. When it is needed, it is already loaded, I just need to add it:
viewController.view.addSubview(webView)
I use two different methods, depending on my needs: I either load the view early and change the alpha to 0 so it is invisible:
webView.alpha = 0
Of course, I change it to 1.0 when I want it to display.
Or I remove the web view from the superview (it needs to be a class property so it is retained), like this:
func removeWebView(_: UITapGestureRecognizer) {
print("removewebview tap")
webView.removeFromSuperview()
}
If you follow this approach, you will need to call a method that adds the subview (web view) back, and if you are using auto layout, you need to reapply constraints because they are lost when you remove the web view from the superview. If you do that, don't forget to call .setNeedsLayout() on the parent view.
I have a QR Code Scanner view in which I have an AVCaptureVideoPreviewLayer and a UIButton.
When this view displays, the text within the button does not show. It should display the word 'Cancel'. If I touch the button, or swipe the button - but not tap it, the button text will show at that point.
Does anyone know how I can get the button text to display properly?
Here's what my view hierarchy looks like:
When I first enter the Scanner view, the buttons look like this:
There is no text. The text will show only after I touch the buttons:
One last thing, it seems this is an issue only is iOS 10...
Any suggestions welcome. Thanks!
Yes. You need to add an overlay view.
Main view containing video preview and overlay view.
Overlay view contains buttons.
For each button, you can use these events if you want to animate:
TouchDown
TouchUpInside
TouchOutInside
As the documentation of AVCaptureSession states, startRunning() call blocks the main thread so your UI is not drawn correctly.
The startRunning() method is a blocking call which can take some time,
therefore you should perform session setup on a serial queue so that
the main queue isn't blocked (which keeps the UI responsive). See
AVCam-iOS: Using AVFoundation to Capture Images and Movies for an
implementation example.
If you check Apple's example (Swift 3 and Objective-C), you can easily set a new queue for those actions without blocking your main thread.
This is the example for Swift 2.3 if you need it.
// Swift 2.3
private let sessionQueue = dispatch_queue_create("session queue", nil)
override func viewDidLoad() {
super.viewDidLoad()
dispatch_async(sessionQueue) {
self.configureSession()
}
dispatch_async(dispatch_get_main_queue()) {
self.setupScreen()
}
}
Use layer.insertSublayer(..., above: ...) or layer.insertSublayer(..., below: ...) to control your CALayers
Here's the similar answer link or
a bit more detailed instructions for Swift how to insert image on the top of video stream manual
I've created a config manager to update UI settings without restarting. Most settings you can just force a redraw however it appears to be more limited with the tab bar.
I update the tab bar within my UITabBarController with the following when I receive a config change notification (note: this could be anytime after viewDidLoad):
self.tabBar.backgroundColor = tabBarBackgroundColour
This does update the colour but only after about 5-10 seconds.
I've tried various ways to force an update using setNeedsLayout and setNeedsDisplay on both the tab bar and the view but none of them work.
self.tabBar.setNeedsLayout()
self.tabBar.setNeedsDisplay()
or
self.view.setNeedsLayout()
self.view.setNeedsDisplay()
I've also tried updating the individual tab bar items as I see other people have had similar issues when updating images but to no avail.
Make sure you are updating the background color on the main thread.
DispatchQueue.main.async { [weak self] in
self?.tabBar.backgroundColor = tabBarBackgroundColour
}
I have an app that switch views using a segue when a button is clicked.
The second view loads data from the internet and it can take a couple of seconds.
I would like to know how can i display a loading view/splash screen in the meantime so the view could finish the loading and the app wont appear like it's doing nothing.
Thanks!
Check this library SwiftSpinner. It serves the purpose of your needs. It's really brilliant.
Call the necessary function from the library in the viewDidLoad method of your ViewController which loads the data from the internet. Remove this view in DidFinishLoading method of the NSURLProtocol (It's an optional func declared in that class which detects when the request to that URL is complete). The documentation is given in that library itself.
Sounds like you're looking for an activity indicator. I've used the custom class posted https://stackoverflow.com/a/32661590/3516923 with success. Just a note of warning, in his class he blocks all input while the indicator is in view. If you want to make it so your users can back out before things finish you need to remove UIApplication.sharedApplication().beginIgnoringInteractionEvents() and UIApplication.sharedApplication().endIgnoringInteractionEvents() from the start and stop animating functions.
If what you want is really a splash screen, have a UIImageView underneath the view that you're loading. Set the image to your splash screen image. Set the loading view to hidden=YES before it's shown, then set hidden to NO after it finishes loading. You could even set the opacity of the frontmost view to give you a fading effect.
1.You need to find a kind of indicator, suck like an activity indicator or something else to show the loading UI to the user.
2.Set the user interaction unable, so that the user won`t touchup inside repeatedly.
3.Start the indicator, set the user interaction unable when you load the server data, and stop the indicator animation when you finish, hide the indicator, enabled the user interaction.
In our iOS app, we have a screen with a UINavigationController, three UIBarButtonItem in the rightBarButtonItems, a UIView content view with a UITableView subview.
Every time the app gets to the foreground, VoiceOver places the initial focus on the leftmost UIBarButtonItem. We would like to have the focus on either the topmost cell in the UITableView (initial start) or the cell that the user actively selected before the app went to the background.
We have tried to call UIAccessibilityPostNotification() but this only works if we add a delay and that seems very fragile and will be confusing for the user as focus will start on the UIBarButtonItem and then jump.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, Int64(0.75*Double(NSEC_PER_SEC))), dispatch_get_main_queue()) { () -> Void in
UIAccessibilityPostNotification(UIAccessibilityScreenChangedNotification, self.view)
}
This might work.
As far as I know uiaccessibilitypostnotification works well with the delay, even though it is fragile, you can call the method with 0.5 seconds delay in the view did appear method!!!!
There is also another way you can try. Once the view is loaded, disable the accessibility for the bar buttons, and set the accessibility only for the tableview!!! You need to change the accessibilityElements array and the first element in the array should be the table view, and set isAccessibilityElemnt to NO for the other elements to turn off the accessibility!!!!