I have an iOS app. Some UIViewControllers have automatically updated content, it means that app can get update (simple JSON) any time (but no more often than about 1 time in half an hour). View controllers have UICollectionView with UIContextMenu for iOS >= 13.0.
Some times arises a situation when the user has called the context menu, but the content of cell and its menu are no longer relevant. UICollectionView already reloaded (with resorting cells), but context menu still shown.
I know when the update happens in my app and I want to dismiss open menu in this moment.
So my question is - how to dismiss context menu programmatically?
Thanks for any help!
Hello Please try this solution.
func tableView(_ tableView: UITableView, willPerformPreviewActionForMenuWith configuration: UIContextMenuConfiguration, animator: UIContextMenuInteractionCommitAnimating) {
animator.preferredCommitStyle = .dismiss
}
Related
I have some views.
A MainViewController with 6 buttons.
Here every button would start a function.
A tableview with 6 cells and each cells open an other ButtonVC. ( FirstButtonVC, Second... )
In every ButtonVC there is a picker.
There is an option in the picker ( it says -- ) which is basically nil so it will disable the button on the main VC.
My problem is that when I set it to this disabled option, or even if i enable a button with the picker, in the MainVC the button's ui won't refresh only after stopping and starting the application again in the simulator.
S my question is:
How can I refresh the MainViewController's ui from the ButtonVC so when the user returns to the MainViewController he can already see the updated ui with the updated buttons?
I hope my question is understandable.
The best way to approach this problem is by solving UI updates in the
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Add you code here
}
Of your MainViewController.
I'd like to set up a UIRefreshControl in my apps' main table view controller to trigger a refresh function to (you probably guessed it by now) refresh it.
Adding it isn't the problem, I'm able to set it up through the storyboard (by enabling refreshing) or in the controller (by using self.refreshControl = UIRefreshControl()).
When it gets triggered by the user it starts refreshing normally, but when I trigger it through self.refreshControl.beginRefreshing() the control isn't displayed in the navigation bar, until I scroll down (like you would normally trigger it)
But that's not even the weirdest part. When it's finally visible to the user there is a constant flicker to it and after a while it's not visible at all.
For the self.refreshControl.endRefreshing() method, the animation is really abrupt any choppy and sometimes the navigation bar doesn't scroll up again (leaving an empty space at the top)
Here is a gif, that should summarise my problem
I use swift 4.2, the application was tested on different simulators (running iOS 12.1) and my iPhone X (running iOS 12.1.2) and the release target is iOS 10.0.
I've already done research on my problem, but no one seems to have the exact issue (at least the flickering) or the solutions don't work for me.
This is how my view controller is set up:
class MyViewController: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.refreshControl = UIRefreshControl()
self.refreshControl?.addTarget(self, action: #selector(reload), for: .valueChanged)
self.refreshControl.beginRefreshing()
}
#objc func reload() {
DispatchQueue(label: "update").async {
sleep(10)
DispatchQueue.main.async {
self.refreshControl?.endRefreshing()
}
}
}
}
Thanks for reading, I really hope someone can help me.
Update
I just discovered that the issue only occurs with a non-translucent navigation bar with large title, so picking a translucent navigation bar instead of the opaque is a solution (sadly not one I would like to live with). Maybe someone has an approach to having a functional refresh control with an opaque navigation bar.
Additionally I submitted a bug report to Apple, because something like that should not happen in the first place, I'll update this post when they get back to me.
Is it possible to disable the dock that pops up in iOS?
This is my View Controller. Notice that it has a draggable view controller in the footer.
But when I try to pull it up quickly, the dock shows up:
Is there any way to disable it?
I think the closest you can get is iOS 11's preferredScreenEdgesDeferringSystemGestures(), which will show an indicator at the bottom but not pull up the dock on the first swipe. For example, in your view controller:
override func preferredScreenEdgesDeferringSystemGestures() -> UIRectEdge {
return [.bottom]
}
In my experience it still eats the swipe gesture, but it still gives the user a second chance to hit the right target.
On iOS <11 however, this behavior can only be obtained by hiding the status bar.
Edit:
Usually when faced with implementing a design choice like this, I try to offer a second, non-interfering gesture as a backup, such as a tap in that area, that has the same effect.
As in iOS 11, you cannot disable the dock in an application, nor in Settings. I'd suggest providing a larger area for swiping up from the bottom.
Normally such conflicts should be avoided, as they degrade user experience: how do you know that the user does not actually want to use the dock?
But if you really want, you can override the preferredScreenEdgesDeferringSystemGestures() method in the root controller to specify which edges should NOT (immediately) trigger system gestures.
e.g.
override func preferredScreenEdgesDeferringSystemGestures() -> UIRectEdge {
return .bottom
}
in viewDidLoad :
viewPager.dataSource = self
--
extension DetailsViewController:ViewPagerDataSource{
func numberOfItems(_ viewPager:ViewPager) -> Int {
return dict!.count
}
func viewAtIndex(_ viewPager:ViewPager, index:Int, view:UIView?) -> UIView {
func viewAtIndex(_ viewPager:ViewPager, index:Int, view:UIView?) -> UIView {
return view
the result is slow , it does not show the animation of transition maybe cuz I return the scrollview view not normal view , and when I swipe to left it shows nothing (swipe backwards) , is there anything better to implement ?
thanks for help.
Your question isn't very clear, and then you post a BUNCH of code, including code that's irrelevant to your question. You should only post the parts that directly relate to your question.
It looks like what you want is a UIPageViewController. That manages an array of view controllers, each of which holds the contents of one page. You can either user it with a page curl animation like iBooks, or a scrolling mode. You want the scrolling mode.
If you search in the Xcode help (or online, it looks like the link to download the app isn't in Xcode 8) on "PhotoScroller" You'll find a demo app that illustrates how it works.
That app is written in Objective-C, but it will at least show you the UI it offers.
In order to use a UIPageViewController you'll have to restructure your detail view controller to manage an array of child view controllers instead of only using a single view controller.
If you want side scrolling AND up and down scrolling among a grid of tiles then you want a collection view instead, but that's more work to set up.
The code below is used to push another view controller onto the navigation stack.
When using instantiateViewControllerWithIdentifier, the segue is noticeably sluggish the first time (~3 seconds) but occurs reasonably fast each subsequent time. Other SO posts suggested ensuring the segue occurs on the main thread, which the code accomplishes, but this didn't fix the problem.
However, using performSegueWithIdentifier causes no delay.
The viewDidLoad code for SendViewController is the same for the first and subsequent pushes.
Tried blanking out viewDidLoad for the destination view controller, but still the lag exists for instantiateViewControllerWithIdentifier but not for performSegueWithIdentifier.
How to fix the delay with instantiateViewControllerWithIdentifier?
No delay:
#IBAction func buttonTapped(sender: UIButton) {
performSegueWithIdentifier(SendSegue, sender: self)
}
Results in delay when showing SendViewController for first time:
#IBAction func buttonTapped(sender: UIButton) {
dispatch_async(dispatch_get_main_queue()) {
let vc = self.storyboard!.instantiateViewControllerWithIdentifier(self.SendViewControllerID) as! SendViewController
self.navigationController!.pushViewController(vc, animated: true)
}
}
This issue could occur in many different scenarios. The best way determine what is causing your specific problem is by profiling with the instruments included in Xcode.
Click and hold the Build button in your xcode window. You will see four options appear, select Profile.
Once the build runs a window with instruments will pop up. Select, Time Profiling from the options.
A new window will appear with various metrics in it. The top left corner will have a red record button. Click the red record button and this will launch the app on your phone.
Proceed to the transition giving you problems. End the recording after the transition occurs by selecting the same button you started the recording with.
Review the "Details" pane in the bottom left corner. You will see a column titled "Running time" that shows the time it took to execute every method in your code (both OS methods and user generated code)
Determine if anything is out of place or occurs that is not intended. Possibly go back and execute the transition again to compare the difference between the two. Clicking the function in the list will take you directly to the code being executed. This can be very helpful.
It is very likely that if a transition takes 3-5 seconds one particular function will be obvious when following these steps. Happy profiling!
WWDC from last year has a great segment on this as well. Def worth checking out here: (open in Safari only) WWDC Profiling Talk
The problem was isolated to the presence of a UITextField in the destination view controller, that is, removing the UITextField removes the lag.
Then it was further isolated to the presence of a custom font.
In other words, using the system font on the UITextField, rather than a custom font, removes the lag. No explanation why, but it works.
After time profiling I realized it was the call to instantiateViewController which I couldn't find anything that could help me with that.
Unfortunately, the only thing that worked was either using a separate storyboard for that view controller and instantiating it from there, or redoing the view controller programmatically.