web-dev-qa-db-ja.com

切り離されたViewControllerでのViewControllerの表示

ボタンとアクションを備えたsideViewControllerがあり、このボタンをクリックすると新しいビューコントローラーが表示されます。

class sideViewController: UIViewController {
    @IBOutlet var buttonVC1 : UIButton!
    @IBAction func goToVC1 () {
        var VC1 = self.storyboard.instantiateViewControllerWithIdentifier("ViewController") as ViewController
        presentViewController(VC1, animated:true, completion: nil)
    }
}

私はこれをメインビューコントローラーで使用します:

class ViewController: UIViewController {
    var menu : sideViewController!
    override func viewDidLoad() {
        super.viewDidLoad()
        menu = self.storyboard.instantiateViewControllerWithIdentifier("menu") as      sideViewController
        menu.view.frame = CGRect(x: 0, y: 0, width: 160, height: 480)
        view.addSubview(menu.view)
}

このボタンをクリックすると、問題は次のようになります。「切り離されたViewControllerでViewControllerを表示することはお勧めしません」

これを修正するにはどうすればよいですか?

13
Yury Alexandrov

私は自分でこれと同じ警告に遭遇しました、そして私が電話をしていたときに私がそれを受け取っていることに気づきました

self.presentViewController

ビュー階層を介してUIWindowに接続されていないビューコントローラーで呼び出していました。ビューがビュースタック上にあることがわかるまで、presentViewControllerの呼び出しを遅らせるために行うことを変更する必要があります。これは、ViewDidLoadまたはViewDidAppearで実行されるか、バックグラウンド状態から来ている場合は、アプリがアクティブ状態になるまで待機します。

9
bolnad

これを使用して、メインスレッドにいることを確認します

dispatch_async(dispatch_get_main_queue(), { () -> Void in
        self.presentViewController(VC1, animated: true, completion: nil)
    })
4

問題

iOSは、メインビューの後に表示された他のビュー(切り離されたビュー)が何かを提示していると不平を言っています。それは明らかにそれを提示することができますが、そうすることは良い習慣ではないのでお勧めできません。

解決

デリゲート/プロトコルパターンはこの問題を解決するのに適しています。このパターンを使用すると、アクションはSideVC内でトリガーされますが、このトリガーはMainVCに送信され、そこで実行されます。

したがって、アクションはMainVCによってトリガーされるため、iOSの観点からは、すべて安全で健全です。

コード

SideVC:

protocol SideVCDelegate: class {
  func sideVCGoToVC1()
}

class sideVC: UIViewController {
  weak var delegate: SideVCDelegate?

  @IBOutlet var buttonVC1: UIButton!

  @IBAction func goToVC1 () {
    delegate.sideVCGoToVC1()
  }

MainVC

class MainVC: UIViewController, SideVCDelegate {
  var menu: sideVC!

  override func viewDidLoad() {
    super.viewDidLoad()
    menu = self.storyboard?.instantiateViewControllerWithIdentifier("menu") as sideViewController
    menu.delegate = self
    menu.view.frame = CGRect(x: 0, y: 0, width: 160, height: 480)
    view.addSubview(menu.view)
  }

  // MARK: - SideViewControllerDelegate
  func sideViewControllerGoToVC1() {
    menu.view.removeFromSuperview()
    var VC1 = self.storyboard?.instantiateViewControllerWithIdentifier("ViewController") as ViewController
    presentViewController(VC1, animated:true, completion: nil)
  }
}

注意

あなたが尋ねた質問は別として、以下の行はやや曖昧に見えます。

var VC1 = self.storyboard?.instantiateViewControllerWithIdentifier("ViewController") as ViewController
menu.view.frame = CGRect(x: 0, y: 0, width: 160, height: 480)

Interface Builder内で設計したときにフレームを持つストーリーボードからビューコントローラーを取得していますが、後で変更しています。ビューのフレームが作成されたら、それを試してみるのは良い習慣ではありません。

何か他のことをするつもりだったかもしれませんが、おそらくそれは問題のあるコードです。

2
Ron Fessler

ここでこれはあなたを助けるかもしれません。これでエラーが修正されました

let time = dispatch_time(DISPATCH_TIME_NOW, Int64(0.001 * Double(NSEC_PER_SEC)))

dispatch_after(time, dispatch_get_main_queue(), { () -> Void in
   self.performSegueWithIdentifier("SegueName", sender: self)
})

幸運を..

0