【问题标题】:Swift: Cannot change properties in instantiated view controller [duplicate]Swift:无法更改实例化视图控制器中的属性 [重复]
【发布时间】:2019-05-11 14:13:51
【问题描述】:

我是 Swift 的新手,所以接下来的问题可能是一个非常基本的问题。另外,这是我在 stackoverflow.com 上的第一个!

在实例化视图控制器中设置 UILabel 的文本属性时,我收到“线程 1:致命错误:在展开可选值时意外发现 nil”。

我正在制作一个简单的应用程序来显示我家中的药物清单及其有效期。表格视图控制器显示药物列表,来自一个名为 medArray 的数组,当每一个被点击时,我希望它加载一个包含更多详细信息的详细信息屏幕。

我使用 IB 设置了一个 DetailView 控制器并创建了 3 个 UILabel 的出口连接:

//  DetailView.swift
//  HomeMed
//
//  Created by Joao Boavida on 10/12/2018.
//  Copyright © 2018 Joao Boavida. All rights reserved.
//

import UIKit

class DetailView: UIViewController {

    @IBOutlet var nameLbl: UILabel!
    @IBOutlet var subtextLbl: UILabel!
    @IBOutlet var expdateLbl: UILabel!

}

我认为连接已成功,因为左侧排水沟上的点是实心的。点击表格视图单元格时确实出现错误,该单元格调用以下代码:

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

    let medicine = medArray[indexPath.row]

    if let vc = storyboard?.instantiateViewController(withIdentifier: "DetailView") as? DetailView {

        vc.nameLbl.text = medicine.name

        if let subtext = medicine.subtext {
            vc.subtextLbl.text = subtext
        } else {
            vc.subtextLbl.text = ""
        }

        let ISOdateFormatter = ISO8601DateFormatter()
        ISOdateFormatter.formatOptions = [.withMonth, .withYear, .withDashSeparatorInDate]

        vc.expdateLbl.text = "Exp: \(ISOdateFormatter.string(from: medicine.expiry))"

        navigationController?.pushViewController(vc, animated: true)

    }

}

当我尝试访问 vc.nameLbl.text 时,我得到了错误,由于我不知道的原因,它是 nil。 vc.expdateLbl 和 vc.subtextLbl 也是 nil。

“vc”视图控制器似乎已正确实例化,因为如果我省略配置代码并在创建后推送它,它会显示正常,尽管我在 IB 中设置的标签中有初始文本。只有当我尝试更改这些标签时它才会崩溃。

我尝试建立和重新建立插座连接,但均未成功。谁能帮忙解决这个问题?

非常感谢!

【问题讨论】:

  • 直到 viewDidLoad() 之后才真正设置网点,我会尝试在其生命周期的后期移动文本设置。
  • 您收到此错误的原因是 vc 的网点 not 尚未实例化。你还在使用 segues 吗?
  • vc.nameLbl 尚未初始化。 VC 已加载,但未加载其 IBOutlets。参照。 stackoverflow.com/questions/12523198/… 而是使用String 属性来存储名称,并在vc.myNameStringProperty = medicine.nameviewDidLoad() 中使用self.nameLbl.txt = myNameStringProperty
  • 查看副本时,请参阅此具体答案:stackoverflow.com/a/49818897/1226963
  • 谢谢@rmaddy 和大家,问题解决了!我看过那个帖子,但没有看到那个具体的答案。

标签: ios swift


【解决方案1】:

你在这里设置你的 VC 的网点,对吗?

    vc.nameLbl.text = medicine.name <---

    if let subtext = medicine.subtext {
        vc.subtextLbl.text = subtext <---
    } else {
        vc.subtextLbl.text = "" <---
    }
    ...
    vc.expdateLbl.text = "Exp: \(ISOdateFormatter.string(from: medicine.expiry))" <---

运行上述代码时,出口nameLblsubtextLblexpdateLbl 均为零。它们还没有在那个时间点设置。

viewDidLoad 被调用时,出口已经设置好了。因此,您可以做的是在您的DetailView 中添加三个属性:

var name: String!
var subtext: String!
var expdate: String!

您设置了上述三个属性,而不是设置 outlets:

    vc.name = medicine.name <---

    if let subtext = medicine.subtext {
        vc.subtext = subtext <---
    } else {
        vc.subtext = "" <---
    }
    ...
    vc.expdat = "Exp: \(ISOdateFormatter.string(from: medicine.expiry))" <---

然后,在DetailView 中,将属性分配给viewDidLoad 中标签的text

override func viewDidLoad() {
    nameLbl.text = name
    subtextLbl.text = subtext
    expdateLbl.text = expdate
}

【讨论】:

  • 仅供参考 - 这都包含在我链接的重复答案中。
  • @JoaoB 如果您认为我的回答回答了您的问题,请考虑通过单击该复选标记接受它。
【解决方案2】:

它崩溃是因为您在加载之前尝试访问UILabel。所以,你应该打电话给vc.loadViewIfNeeded()。这将加载所有 UIViewController 视图。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-09-28
    • 1970-01-01
    • 2014-11-07
    • 1970-01-01
    • 1970-01-01
    • 2019-01-23
    • 2017-07-24
    相关资源
    最近更新 更多