2017-03-04 5 views
-1

私はViewController別にViewコード(see this)を維持し、これもUIAlertController.なぜこのUIAlertControllerはオプションの値をアンラップしている間にnilを見つけられないのですか?

しかし、アップルのドキュメントsays用のコードに適用できる場合、私は思ったんだけどにより「は善良な市民こと」しようとしています:

UIAlertControllerクラスは、そのまま使用することを目的としており、サブクラス化をサポートしていません。このクラスのビュー階層はプライベートであり、変更することはできません。これにもかかわらず

、私はまだUIAlertControllerをサブクラス化することは可能かもしれないと思った - はい、私はUIAlertControllerViewではないことを実感 - 私はの下に簡単なテスト例を試してみました。

コードには、レイアウトの制約があるサブクラス化されたビューが含まれています。 A UIButtonがアラートをアクティブにするために使用されます(そして、最終的にターゲットアクションは別のクラスから呼び出すことができる関数の基礎になります)。

コードが実行されますが、できるだけ早くボタンが押されているXcodeのは次の行

fatal error: unexpectedly found nil while unwrapping an Optional value 
    (lldb) 

は私がミスをしてきたメッセージと

self.view.present(alert, animated: true, completion: nil) 

でデバッグに入りますか?私は何か不可能なことをしようとしていますか?

ViewController.swift

import UIKit 

    class ViewController: UIViewController { 

    var launch: TestView { 
    return view as! TestView 
    } 

    override func viewDidLoad() { 
     super.viewDidLoad() 
    } 

    override func loadView() { 
     let contentView      = TestView(frame: .zero) 
     view        = contentView 
    } 
} 

TestView.swift

import UIKit 

class TestView: UIView { 

    var view:ViewController! 

    override init(frame: CGRect) { 
     super.init(frame: frame) 
     view.self = view 

     addBehavior() 
    } 

    convenience init() { 
     self.init(frame: CGRect.zero) 

    } 

    required init(coder aDecoder: NSCoder) { 
     fatalError("This class does not support NSCoding") 
    } 

    func addBehavior() { 

     let spacer: UIView    = UIView (frame: .zero) 
     spacer.backgroundColor   = UIColor.white 

     let view: UIView    = UIView (frame: .zero) 
     view.backgroundColor   = UIColor.lightGray 
     view.alpha      = 0.5 

     let button: UIButton   = UIButton(frame: .zero) 
     button.backgroundColor   = UIColor.blue 
     button.setTitleColor(UIColor.white, for: UIControlState.normal) 
     button.setTitle("test", for: .normal) 
     button.addTarget(self, action: #selector(showExcessNotesAlert), for: .touchUpInside) 

     let stackView     = UIStackView(arrangedSubviews: [spacer, view, button]) 
     stackView.axis     = .vertical 
     stackView.spacing    = 5 
     stackView.translatesAutoresizingMaskIntoConstraints = false 

     addSubview(stackView) 

     let views      = ["stackView": stackView] 

     var layoutConstraints   = [NSLayoutConstraint]() 
     layoutConstraints += NSLayoutConstraint.constraints(withVisualFormat: "|-[stackView]-|", options: [], metrics: nil, views: views) 
     layoutConstraints.append(spacer.heightAnchor.constraint(equalToConstant: 30)) 
     layoutConstraints.append(view.heightAnchor.constraint(equalToConstant: 450)) 
     layoutConstraints.append(button.heightAnchor.constraint(equalToConstant: 50)) 
     NSLayoutConstraint.activate(layoutConstraints) 

     backgroundColor     = .white 
    } 

    func showExcessNotesAlert(_ sender: UIButton) { 

     let alert   = UIAlertController(title: "Alert", message: "Grow a brain", preferredStyle: .alert) 
     let defaultAction = UIAlertAction(title: "OK", style: .default, handler: nil) 
     alert.addAction(defaultAction) 
     self.view.present(alert, animated: true, completion: nil) 
    } 
} 
+0

あなたはUIViewとUIViewControllerの違いを知っていますか? –

+0

@El Tomato、原則として私はそうだと思いますが、UIViewControllerに表示されるUIViewをサブクラス化することができ、UIAlertControllerと同様のものを実現することができるかどうかについては、 – Greg

答えて

2

あり、ここでいくつかの問題がありますが、あなたのクラッシュの可能性の高い原因は、この行です:

view.self = view 

それはいくつかの理由で有効なコードではありませんが、クラッシュする理由は、暗黙的にアンラップされたオプションとして定義された変数(view)にアクセスしようとしていることですアクセスしようとする前にそれを初期化することはありませんので、もちろんそれはゼロです。最低初期化は、view.self = viewself.view = UIViewController()に置き換えることです。そのview変数で何をしたいのかよく分かりませんが、提案された変更を行うとクラッシュが停止する可能性があります。

最終的には、あなたのviewController内から組み込みのUIAlertControllerを使用するだけでなく、あなたのスニペットにコードが表示されることはありません。繰り返しますが、あなたが達成したいと思っているものを正確に追跡するのは少し難しいです。

+0

あなたの初期化で停止します。警告:ウインドウの階層にビューがないに表示しようとしました! – Greg

+0

@Gregはい、あなたのコードには他にも問題がありますが、代わりにalertControllerを実行したいと思うかもしれません。 – creeperspeak

関連する問題