【问题标题】:why does this UIAlertController fail to find nil while unwrapping an Optional value?为什么这个 UIAlertController 在展开 Optional 值时找不到 nil ?
【发布时间】:2017-03-04 22:54:22
【问题描述】:

我试图通过将View 代码与ViewController (see this) 分开来“成为一个好公民”,我想知道这是否也适用于代码对于UIAlertController.

然而苹果文档says:

UIAlertController 类旨在按原样使用,不支持子类化。此类的视图层次结构是私有的,不得修改。

尽管如此,我认为仍然可以继承 UIAlertController - 是的,我意识到 UIAlertController 不是 View - 所以我尝试了简单的测试示例下面

代码包括具有布局约束的子类视图。 UIButton 用于激活警报(最终目标操作将成为可以从另一个类调用的函数的基础)。

代码运行,但只要按下按钮,Xcode 就会在以下行进行调试

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

与消息

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

我做错了吗?还是我在尝试做一些不可能的事情?

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)
    }
}

【问题讨论】:

  • 你知道UIView和UIViewController的区别吗?
  • @El Tomato,原则上,我认为是这样,但我想知道为什么可以对出现在 UIViewController 中的 UIView 进行子类化,以及是否可以使用 UIAlertController 实现类似的功能

标签: ios swift uiview uiviewcontroller subclass


【解决方案1】:

这里有几个问题,但你崩溃的可能原因是这行:

view.self   = view

这不是有效的代码有几个原因,但它崩溃的原因是你试图访问一个变量(view),你已经将它定义为一个隐式展开的可选(通过将“!”放在end),但您在尝试访问之前从未初始化它,所以它当然是 nil。最低限度的初始化是将view.self = view 替换为self.view = UIViewController()。我不完全理解你想用那个 view 变量做什么,但是做出我建议的更改可能会导致崩溃停止。

最终,我在您的 sn-p 中没有看到任何代码建议您不应该只使用 viewController 中的内置 UIAlertController。同样,要准确地遵循您希望实现的目标有点困难。

【讨论】:

  • 崩溃随着您的初始化而停止。报告对警告的更改:尝试在 上显示 ,其视图不在窗口层次结构中!
  • @Greg 是的,正如我提到的,您的代码还有其他问题,您可能只想改用 alertController。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-09-23
  • 1970-01-01
相关资源
最近更新 更多