web-dev-qa-db-ja.com

セグエがモーダルの場合、performSegueWithIdentifierは非常に遅い

テーブルビューで選択アクションを処理する単純なテーブルビューがあります。このアクションはセグエに続きます。

セグエがPushセグエの場合、次のビューがすぐに表示されます。セグエがmodalセグエの場合、次のビューは次のいずれかです。

  • 表示するには6秒ほどかかります
  • もう一度タップするとすぐに表示されます(2回目のタップ)

いくつかのアイデアを探してみましたが、私の状況に当てはまるものはありません。特に:

  • メインUIスレッドでセグエを実行しています
  • 私の見解は非常に単純です(したがって、viewDidLoadに問題はありません)。さらに、セグエがPushのときにほぼ瞬時に表示されるという事実は、ターゲットビューの読み込みに問題がないことを示しています。
  • nilsenderに渡そうとしました。同じ効果。

誰もこれに関するアイデアを持っていますか?

44
tng

私を信じてこれを試してください。私はこの問題に何度か遭遇しました。

In Swift 2:

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

またはSwift 3:

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

前述のとおり、 here および here

89
boidkan

(私には...)この問題は、セルselectionType.noneではない場合にのみ発生するようです。

それを他のオプションに変更することができます(ストーリーボードAttribute inspectorで、Selectionフィールドを設定します)、それはうまく動作します(私のために働いています...)。短所は、セルUIを台無しにすることです。

前に述べたように、didSelectUITableViewDelegateデリゲート関数のDispatchQueue.main.async{}ブロックでセグエを呼び出すことができます。

最初のソリューションを使用し、セル自体に追加しました-

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

これにより、タップ時にセルが「強調表示」されますが、すぐに通常のUIに戻り、私にとってはうまくいきます...

5
Yedidya Reiss

セグエの実行が適切に機能しない場合、さまざまな状況があるようです。たとえば、アンワインドセグエのアクションハンドラからperformSegueを呼び出すと、メインスレッドにいる場合でもさまざまな問題が発生します。現在のプロジェクトでは、Table ViewのperformSegueメソッドからdidSelectRowAtを呼び出しています。これは最も基本的なセグエの1つであり、もちろん私はメインスレッドにいますが、OPが説明した正確な症状を見ていました。

他の人ではなく、なぜこれが起こるのかはわかりませんが、performSegueを使用してasync呼び出しを延期すると、潜在的な問題が修正されることがわかりました。これはハックのように見えて緊張しましたが、この時点でこのアプローチを使用したいくつかの成熟したプロジェクトがあり、手動のセグエを行う「正しい」方法のように見えます。

Swift 3バージョンのコードです(Swift 2およびObj-Cバージョンに関する他の投稿を参照):

DispatchQueue.main.async {
    self.performSegue(withIdentifier: "theIdentifier", sender: theSender)
}
3
phatmann

受け入れられたソリューションは私のために働いた。 Swift 2.0以下のために更新されたコード:

dispatch_async(dispatch_get_main_queue(),{
     self.performSegueWithIdentifier(mysegueIdentifier, sender:self)
})
2
instAustralia

これがSwiftでプログラム的にモーダル遷移を作成できることを願っています:

       let myStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
        let modalViewController = myStoryboard.instantiateViewControllerWithIdentifier("myModalViewController") as! myModalViewController
        modalViewController.modalTransitionStyle = UIModalTransitionStyle.CoverVertical
        let navController = UINavigationController(rootViewController: accountManager)
        dispatch_async(dispatch_get_main_queue(),{
            self.presentViewController(navController, animated: true, completion: nil)
        })
1
Dasoga

サブクラス化によってコードを整理する開発者向けに、共有したい非常に簡単なソリューションになりました(Swift 4):

import UIKit

class ABCViewController: UIViewController {

  // ... Other useful methods like overriding deinit and didReceiveMemoryWarning

  // Performs a segue on the main thread to ensure it will 
  // transition once a UI-slot is available
  func performSegueOnMainThread(with identifier: String, sender: Any?) {
    DispatchQueue.main.async {
      self.performSegue(with: identifier, sender: sender)
    }
  }
}

次に、実装から単に呼び出します。

myViewController.performSegueOnMainThread(with: "ShowDetailsSegue", sender: self)
1
Hans Knöchel

私にとっては、次のビューで「クリア」な色のビューが多すぎたため、セグエがアニメーション化されたとき、このために遅れているように見えました。 View ControllerのUI階層を調べて、明確な色を探し、それらを黒一色または白一色に置き換え、アルファが1であることを確認しました(そうでない場合は必要ありません)。遅延がなくなり、モーダルプレゼンテーションがスムーズになりました。

0
Joshua Hart