Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

performSegueWithIdentifier very slow when segue is modal

I have a simple table view where I handle the select action on the table view. This action follows a segue.

If the segue is a push segue, the next view shows immediately. If the segue is a modal segue, the next view either:

  • takes 6 seconds or so to display
  • shows immediately if I tap again (second tap)

I tried looking around for some ideas, but none seem applicable to my situation. In particular:

  • I'm performing the segue on the main UI thread
  • My view is very simple (so there's no issue in viewDidLoad). Plus the fact that it shows up near instantaneous when the segue is push indicates that there is no problem loading the target view
  • I tried passing nil to the sender; same effect.

Does anyone have any ideas on this?

like image 887
tng Avatar asked Feb 13 '15 21:02

tng


People also ask

What is a modal segue?

A modal Segue is just one VC presenting another VC modally. The VCs don't have to be part of a navigation controller and the VC being presented modally is generally considered to be a "child" of the presenting (parent) VC. The modally presented VC is usually sans any navigation bars or tab bars.

How to segue between view controllers?

To create a segue between view controllers in the same storyboard file, Control-click an appropriate element in the first view controller and drag to the target view controller. The starting point of a segue must be a view or object with a defined action, such as a control, bar button item, or gesture recognizer.

What is the main purpose of using segues?

Segues are visual connectors between view controllers in your storyboards, shown as lines between the two controllers. They allow you to present one view controller from another, optionally using adaptive presentation so iPads behave one way while iPhones behave another.


3 Answers

Trust me and try this. I have run into this problem a few times.

In Swift 2:

dispatch_async(dispatch_get_main_queue(),{
    self.performSegue(withIdentifier:mysegueIdentifier,sender: self)
})

or for Swift 3:

DispatchQueue.main.async {
    self.performSegue(withIdentifier: mysegueIdentifier,sender: self)
}

As discussed here and here.

like image 120
boidkan Avatar answered Oct 22 '22 06:10

boidkan


It seems (to me...) that this problem happens only when the cell selectionType is not .none.

You may change it to any other option (at the storyboard Attribute inspector, set the Selection field) and it will work fine (working for me...). The cons is that it messing up the cell UI.

You can call the segue in DispatchQueue.main.async{} block at the didSelect delegate function of UITableViewDelegate as people mention before.

I used the first solution and added at the cell itself -

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(false, animated: false)
}

This will make the cell 'highlight' at the tap, but it will return to its usual UI immediately and it fine for me...

like image 7
Yedidya Reiss Avatar answered Oct 22 '22 06:10

Yedidya Reiss


There seem to be various situations when performing a segue will not work properly. For example, if you call performSegue from the action handler of an unwind segue, you will run into various issues, even though you are on the main thread. On my current project, I am calling performSegue from the didSelectRowAt method of a table view. This is one of the most basic segues there is and of course I am on the main thread, yet I was seeing the exact symptoms that the OP described.

I do not know why this happens in some cases and not others, but I have found that deferring the performSegue call using async fixes any potential issues. This used to seem like a hack and made me nervous, but at this point I have several mature projects using this approach and it now seems like the "right" way to do a manual segue.

Here is the Swift 3 version of the code (see the other posts for Swift 2 and Obj-C versions):

DispatchQueue.main.async {
    self.performSegue(withIdentifier: "theIdentifier", sender: theSender)
}
like image 4
phatmann Avatar answered Oct 22 '22 05:10

phatmann