为啥 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)
【问题讨论】:
firstCell
、secondCell
等在哪里分配?
我在 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 两次?
可插拔自定义视图 Nibs (Nib-in-a-Nib):内存泄漏 - 为啥?