为啥 nib 文件中的 UITableViewCell(加载并添加到堆栈)在 viewDidAppear 中为零,但在 viewDidLoad 中没问题?

Posted

技术标签:

【中文标题】为啥 nib 文件中的 UITableViewCell(加载并添加到堆栈)在 viewDidAppear 中为零,但在 viewDidLoad 中没问题?【英文标题】:Why UITableViewCell in nib file(which load and added to stack) is nil in viewDidAppear but its ok in viewDidLoad?为什么 nib 文件中的 UITableViewCell(加载并添加到堆栈)在 viewDidAppear 中为零,但在 viewDidLoad 中没问题? 【发布时间】:2017-08-12 11:50:43 【问题描述】:

我的 ViewController 中有一个堆栈,我想加载一个 nib 文件(其中包含一个表格视图)并将其添加到堆栈中。当我将它添加到viewDidLoad 时,没有问题,但是当我将它放入viewDidAppear 应用程序崩溃并出现此错误:

fatal error: unexpectedly found nil while unwrapping an Optional value

有一些UITableViewCell,我根据行在cellForRowAt 函数中返回它们。似乎 nib 文件在加载并添加到 viewDidAppear 时为零!

这是我的代码:

class MyOrdersViewController: UIViewController 

@IBOutlet weak var stack: UIStackView!
override func viewDidLoad() 
    super.viewDidLoad()
    //setCards()


override func viewDidAppear(_ animated: Bool) 
    super.viewDidAppear(animated)
    setCards()



func setCards()
        let orderCard = NibLoader.loadViewFromNib(name: "MyOrdersView", selfInstance: self, nibType: MyOrdersView.self) as! MyOrdersView   
        stack.addArrangedSubview(orderCard)




class MyOrdersView: UIView,UITableViewDelegate,UITableViewDataSource 

@IBOutlet weak var tableView: UITableView!

@IBOutlet weak var seprator: UITableViewCell!

@IBOutlet weak var date: UILabel!
@IBOutlet weak var firstCell: UITableViewCell!
@IBOutlet weak var code: UILabel!

@IBOutlet weak var secondCell: UITableViewCell!
@IBOutlet weak var price: UILabel!

@IBOutlet weak var thirdCell: UITableViewCell!
@IBOutlet weak var orderStep: UILabel!

@IBOutlet weak var payModel: UILabel!
@IBOutlet weak var cancelBtn: UIButton!
@IBOutlet weak var fourthCell: UITableViewCell!

override func awakeFromNib() 
    tableView.delegate = self
    tableView.dataSource = self
    UIFunctions.setBordersStyle(view: cancelBtn, radius: 5, width: 1, color: UIColor.red)


func setValue(order:Order)
    self.date.text = order.order_date
    self.code.text = String(describing: order.order_code ?? 0)


// MARK: - Table view data source

func numberOfSections(in tableView: UITableView) -> Int 
    return 1


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return 5


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 

    var cell=UITableViewCell()

    switch indexPath.row 
    case 0:
        cell = seprator
    case 1:
        cell = firstCell
        cell.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0)
    case 2:
        cell = secondCell
        cell.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0)
    case 3:
        cell = thirdCell
        cell.separatorInset = UIEdgeInsetsMake(0, 0, 0, 0)
    case 4:
        cell = fourthCell
    default:
        break
    

    return cell


func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat 

    var height = 0
    switch indexPath.row 
    case 0:
        height = 25
    case 4:
        height = 70
    default:
        height = 50
    

    return CGFloat(height)


【问题讨论】:

firstCellsecondCell 等在哪里分配? 我在 nib 文件中创建它们(从对象库中拖动 tableview 单元格) 【参考方案1】:

原因似乎是因为viewDidLoad是第一个方法 在视图生命周期中调用,在此处添加 nib 引用确保 绘制视图(您的表格)时,它们可用于 定位于cellForRow

但是如果你把相同的代码放在viewDidAppear 中,视图已经 到那个时候加载,你的表视图还没有被引用 引用自Nib。因此出现 nil 错误。

This link 详细讨论了各种视图生命周期方法及其调用顺序。

【讨论】:

那么如何在运行时将视图(包含 tableview)添加到堆栈中? 是的,我向服务器发送请求,它返回一个项目列表(和数组数组) 我不明白服务器调用是在哪里进行的,但是如果您只想在从服务器收到响应后更新表视图,它应该可以工作..您只需更新最初会的数组包含 0 个元素并显示空表,然后将显示来自服务器的数据响应.. 只需将 NibLoader.loadViewFromNib 保留在 viewDidLoad 中,其余的应该处理 这只是我放在那里的一个示例代码。我只是想表明我不能在 viewDidLoad 之外的任何地方调用 setCards 函数,我不知道我应该调用多少次 setCards。它在服务器响应后确定(在 viewDidLoad 中调用请求但在收到响应后我不能调用 setCards 函数) 理想情况下应该只调用一次,因为它只是为您设置视图。如果您想更新该视图中的数据(在您的情况下为表格视图),您应该更新表格视图中使用的数组并重新加载表格。

以上是关于为啥 nib 文件中的 UITableViewCell(加载并添加到堆栈)在 viewDidAppear 中为零,但在 viewDidLoad 中没问题?的主要内容,如果未能解决你的问题,请参考以下文章

为啥我必须在自定义 NIB / XIB 中连接 IBOutlet 两次?

在这个项目中,为啥我无法访问从 nib 加载的视图属性?

为啥“loadNibNamed”方法返回数组?

可插拔自定义视图 Nibs (Nib-in-a-Nib):内存泄漏 - 为啥?

为啥从 Nib 加载的 UITextField 的默认字体太小?

为啥这个 NIB 视图在返回之前没有发布?