2017-03-04 1 views
-1

Je suis en train de « être un bon citoyen » en gardant View code distinct du ViewController (see this) et je me demande si cela pourrait appliquer aussi au code pour une UIAlertController.pourquoi ce UIAlertController ne parvient-il pas à trouver tout en déballant une valeur optionnelle?

Cependant, la documentation Apple says :

La classe UIAlertController est destinée à être utilisée telle quelle et ne prend pas en charge la sous-classe. La hiérarchie de vue de cette classe est privée et ne doit pas être modifiée.

Malgré cela, je pensais qu'il pourrait encore être possible de sous-classe un UIAlertController - Oui, je me rends compte que UIAlertController est pas un View - donc j'ai essayé l'exemple simple de test ci-dessous .

Le code inclut des vues sous-classées avec des contraintes de disposition. Un UIButton est utilisé pour activer l'alerte (et éventuellement l'action cible deviendra la base d'une fonction qui pourrait être appelée depuis une autre classe).

Les pistes de code, mais dès que le bouton est pressé Xcode va dans le débogage à la ligne suivante

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

avec le message

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

Ai-je fait une erreur? ou est-ce que j'essaie de faire quelque chose d'impossible?

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

Connaissez-vous la différence entre UIView et UIViewController? –

+0

@El Tomato, en principe, je pense, mais ce que je voudrais savoir, c'est pourquoi il est possible de sous-classer UIViews qui apparaissent dans un UIViewController et s'il est possible de réaliser quelque chose de similaire avec UIAlertController – Greg

Répondre

2

Il y a plusieurs problèmes, mais la cause probable de votre accident est cette ligne:

view.self = view 

Ce code n'est pas valide pour plusieurs raisons, mais la raison pour laquelle il plante est que vous essayez d'accéder à une variable (view), que vous avez définie comme une option implicitement déballée (en mettant le "!" À la fin), ne jamais l'initialiser avant d'essayer d'accéder, donc bien sûr c'est nul. L'initialisation minimale minimale serait de remplacer view.self = view par . Je ne comprends pas tout à fait ce que vous voulez faire avec cette variable view, mais en effectuant ma modification suggérée, cela provoquera probablement l'arrêt de ce plantage.

En fin de compte, je ne vois aucun code dans votre extrait pour vous suggérer que vous ne devriez pas utiliser simplement le UIAlertController intégré depuis votre viewController. Encore une fois, c'est un peu difficile de suivre exactement ce que vous espérez accomplir.

+0

le crash s'arrête avec votre initialisation .signaler les modifications à Avertissement: Essayez de présenter sur dont la vue ne se trouve pas dans la hiérarchie des fenêtres! – Greg

+0

@Greg Oui, comme je l'ai mentionné il y a d'autres problèmes avec votre code, et vous pouvez simplement faire le alertController à la place. – creeperspeak