在一个屏幕中具有多个视图控制器是非常好的。因此,我建议您创建三个视图控制器,每个表视图一个。每个表视图都有自己的数据源。然后使用自定义容器视图控制器,如下所述:https://developer.apple.com/documentation/uikit/view_controllers/creating_a_custom_container_view_controller
问题:加载View时发生致命错误。我知道问题是因为在尝试加载表视图时没有可用数据。但是,由于我在一个UI中使用了多个TableView,因此必须在CellForRowAt中强制返回单元格。
是否有更好的方法为每个TableView设置不同的数据?
感谢您的帮助!
import UIKit
class NewCustomTaskVC: UIViewController {
@IBAction func CancelPressed (_ sender: Any) {
dismiss(animated: true, completion: nil)
}
@IBOutlet weak var taskTypeSelectionBtn: UIButton!
@IBOutlet weak var FrameSelectionBtn: UIButton!
@IBOutlet weak var AssignSelectionBtn: UIButton!
@IBAction func SelecttaskTypePressed(_ sender: Any) {
if tableViewTaskType.isHidden {
self.tableViewTaskType.isHidden = false
self.tableViewTaskType.rowHeight = 43.5
} else {
self.tableViewTaskType.isHidden = true
}
}
@IBAction func SelectFramePressed(_ sender: Any) {
if tableViewFrame.isHidden {
self.tableViewFrame.isHidden = false
} else {
self.tableViewFrame.isHidden = true
}
}
@IBAction func SelectAssignToPressed(_ sender: Any) {
if tableViewAssignTo.isHidden {
self.tableViewAssignTo.isHidden = false
} else {
self.tableViewAssignTo.isHidden = true
}
}
@IBOutlet weak var tableViewTaskType: UITableView!
@IBOutlet weak var tableViewFrame: UITableView!
@IBOutlet weak var tableViewAssignTo: UITableView!
var cellID = ""
var array = ["String", "Test", "Next","Test 2", "Test 3"]
override func viewDidLoad() {
super.viewDidLoad()
getData()
tableViewTaskType.isHidden = true
tableViewFrame.isHidden = true
tableViewAssignTo.isHidden = true
tableViewTaskType.delegate = self
tableViewFrame.delegate = self
tableViewAssignTo.delegate = self
tableViewTaskType.dataSource = self
tableViewFrame.dataSource = self
tableViewAssignTo.dataSource = self
self.tableViewTaskType.register(UITableViewCell.self, forCellReuseIdentifier: "cell1")
self.tableViewFrame.register(UITableViewCell.self, forCellReuseIdentifier: "cell2")
self.tableViewAssignTo.register(UITableViewCell.self, forCellReuseIdentifier: "cell3")
}
func getData () {
//dispatchGroup.enter()
var count = 0
APICallBack.getFramesData(completion: { success in
if success == true {
print("frames success")
count += 1
} })
APICallBack.getTaskTypeData { success in
if success == true {
print("task success")
count += 1
}
}
APICallBack.GETUserData(completion: { success in
if success == true {
print("user success")
count += 1
} })
if count == 3{
DispatchQueue.main.async {
self.tableViewTaskType.reloadData()
self.tableViewAssignTo.reloadData()
self.tableViewFrame.reloadData()
print("ALL COMPLETE")
}
}
}
}
extension NewCustomTaskVC : UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var count = 1
switch tableView {
case tableViewTaskType:
count = TaskTypeData.typeModel.count
case tableViewFrame:
count = FramesData.framesModel.count
case tableViewAssignTo:
count = CustomerData.customerModel.count
default:
print("none")
return count
}
//return 5
return count
}
**PROBLEM IS HERE
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell:UITableViewCell?
if tableView == self.tableViewTaskType{
cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath)
cell!.textLabel!.text = TaskTypeData.typeModel[indexPath.row].TaskTypeName
// cell!.textLabel?.text = array[indexPath.row]
}
if tableView == tableViewFrame{
cell = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath)
cell!.textLabel!.text = FramesData.framesModel[indexPath.row].FrameName
// cell!.textLabel?.text = array[indexPath.row]
}
if tableView == self.tableViewAssignTo {
cell = tableView.dequeueReusableCell(withIdentifier: "cell3", for: indexPath)
cell!.textLabel!.text = UserData.userModel[indexPath.row].UserFirst
// cell.textLabel?.text = array[indexPath.row]
}
// let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath)
// cell.textLabel?.text = array[indexPath.row]
return cell!
}
** TO HERE!
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let item = array[indexPath.row]
print(item)
tableViewTaskType.isHidden = true
}
}
我的UI视图:
如果不强行得到的错误:
我假设您要在数据源数组为空时显示一个空的“占位符”单元格。您需要在cellForRow
函数中明确检查该条件。
就协调来自多个API端点的提取,您可以使用DispatchGroup
-一些注释代码表明您可能已经尝试过此操作。
override func viewDidLoad() {
super.viewDidLoad()
tableViewTaskType.isHidden = true
tableViewFrame.isHidden = true
tableViewAssignTo.isHidden = true
tableViewTaskType.delegate = self
tableViewFrame.delegate = self
tableViewAssignTo.delegate = self
tableViewTaskType.dataSource = self
tableViewFrame.dataSource = self
tableViewAssignTo.dataSource = self
self.tableViewTaskType.register(UITableViewCell.self, forCellReuseIdentifier: "cell1")
self.tableViewFrame.register(UITableViewCell.self, forCellReuseIdentifier: "cell2")
self.tableViewAssignTo.register(UITableViewCell.self, forCellReuseIdentifier: "cell3")
getData()
}
func getData () {
let dispatchGroup = DispatchGroup()
dispatchGroup.enter()
APICallBack.getFramesData(completion: { success in
if success == true {
print("frames success")
}
dispatchGroup.leave()
})
APICallBack.getTaskTypeData { success in
if success == true {
print("task success")
}
dispatchGroup.leave()
}
APICallBack.GETUserData(completion: { success in
if success == true {
print("user success")
}
dispatchGroup.leave()
})
dispatchGroup.notify {
self.tableViewTaskType.reloadData()
self.tableViewAssignTo.reloadData()
self.tableViewFrame.reloadData()
print("ALL COMPLETE")
}
}
extension NewCustomTaskVC : UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch tableView {
case tableViewTaskType:
return max(1,TaskTypeData.typeModel.count)
case tableViewFrame:
return max(1,FramesData.framesModel.count)
case tableViewAssignTo:
return max(1,CustomerData.customerModel.count)
default:
fatalError("Unexpected table view")
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch tableView {
case self.tableViewTaskType:
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath)
if !TaskTypeData.typeModel.isEmpty {
cell.textLabel!.text = TaskTypeData.typeModel[indexPath.row].TaskTypeName
}
return cell
case tableViewFrame:
let cell = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath)
if !FramesData.framesModel.isEmpty {
cell!.textLabel!.text = FramesData.framesModel[indexPath.row].FrameName
}
return cell
case self.tableViewAssignTo:
let cell = tableView.dequeueReusableCell(withIdentifier: "cell3", for: indexPath)
if !UserData.userModel.isEmpty {
cell!.textLabel!.text = UserData.userModel[indexPath.row].UserFirst
}
return cell
default:
fatalError("Unexpected Tableview")
}
}
您可以在返回数据时将tableView.dataSource和tableView.delegate设置为self
您的代码有多个问题。1)您在表视图注册单元格之前调用获取数据。因此,如果您的API立即加载数据,则表视图将调用dataSource方法
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
但自从
self.tableViewTaskType.register(UITableViewCell.self, forCellReuseIdentifier: "cell1")
self.tableViewFrame.register(UITableViewCell.self, forCellReuseIdentifier: "cell2")
self.tableViewAssignTo.register(UITableViewCell.self, forCellReuseIdentifier: "cell3")
在viewDidLoad的末尾调用,当您在cellForAtIndexPath方法中将单元格出队时,将会崩溃。
解决方案是将getData调用移至viewDidLoad方法的末尾。
2)如果要一次显示所有表数据(API完成加载getFramesData,getTaskTypeData和GETUserData时),则需要同步此回调。您可以使用DispatchGroup进行此操作。
func getData () { let apiDispatchGroup = DispatchGroup() APICallBack.getFramesData { success in apiDispatchGroup.leave() } apiDispatchGroup.enter() APICallBack.getTaskTypeData { success in apiDispatchGroup.leave() } apiDispatchGroup.enter() APICallBack.GETUserData { success in apiDispatchGroup.leave() } apiDispatchGroup.enter() apiDispatchGroup.notify(queue: DispatchQueue.main) { self.tableViewTaskType.reloadData() self.tableViewAssignTo.reloadData() self.tableViewFrame.reloadData() } }
3)对于多个UITableView使用一个dataSOurce类并不是一个好主意,因为dataSource成为上帝对象。更好的方法是使用一个包含三个子UITableViewController的ContainerViewController,并在从API加载数据后将数据传递给子类。]
在一个屏幕中具有多个视图控制器是非常好的。因此,我建议您创建三个视图控制器,每个表视图一个。每个表视图都有自己的数据源。然后使用自定义容器视图控制器,如下所述:https://developer.apple.com/documentation/uikit/view_controllers/creating_a_custom_container_view_controller
尝试通过这种方式重新加载TableView数据,
func getData () {
//dispatchGroup.enter()
var count = 0
APICallBack.getFramesData(completion: { success in
if success == true {
print("frames success")
count += 1
self.reloadTableViewsIfNeeded(count)
} })
APICallBack.getTaskTypeData { success in
if success == true {
print("task success")
count += 1
self.reloadTableViewsIfNeeded(count)
}
}
APICallBack.GETUserData(completion: { success in
if success == true {
print("user success")
count += 1
self.reloadTableViewsIfNeeded(count)
} })
}
func reloadTableViewsIfNeeded (_ conunt: Int) {
if count == 3{
DispatchQueue.main.async {
self.tableViewTaskType.reloadData()
self.tableViewAssignTo.reloadData()
self.tableViewFrame.reloadData()
print("ALL COMPLETE")
}
}
}
通过使用此方法,您将获得一个事件,在获取所有数据后将重新加载表视图。
让我知道是否有帮助。
享受并分享...
您总是可以返回默认的非样式UITableViewCell。同时停止强行展开。如果要让或让让,则应始终保持警惕。
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell:UITableViewCell?
...
return UITableViewCell()
}
在一个屏幕中具有多个视图控制器是非常好的。因此,我建议您创建三个视图控制器,每个表视图一个。每个表视图都有自己的数据源。然后使用自定义容器视图控制器,如下所述:https://developer.apple.com/documentation/uikit/view_controllers/creating_a_custom_container_view_controller
尝试通过这种方式重新加载TableView数据,
您总是可以返回默认的非样式UITableViewCell。同时停止强行展开。如果要让或让让,则应始终保持警惕。