我在stackoverflow上的第一个帖子,对不起,如果不正确
我正在XCode中使用“主/详细视图”模板。这是一个BLT Central应用程序,它会通知BLE设备上发生的事件。 我有一个主视图,使用
更新 public func UpdateView() {
tableView.beginUpdates()
tableView.reloadRows(at: self.tableView.indexPathsForVisibleRows!, with: .none)
tableView.endUpdates()
}
这可以正常工作,并且只要BLE通知,TableView就会实时显示更新
但是,如果要显示细节视图,我还想实时更新。
我通过以下方式在DetailView中链接了标签:
@IBOutlet weak var detailDescription: UILabel!
当MasterView绑定到DetailView时,它更新就很好了
但是,如果我在BLE通知到达时尝试更新Label,则@IBOutlet detailDescription变为nil,因此更新失败(标签未链接)
func UpdateDetail() {
guard let label = detailDescription else {
return; //Label not linked
}
label.text = "New Data"
}
UpdateDetail()函数还用于viewDidLoad()中,在这种情况下,它可以正常工作
真正奇怪的是,如果我在DetailView中添加一个计时器以进行更新
var timer : Timer? = nil
@objc func fireTimer() {
DispatchQueue.main.async {
self.UpdateDetail()
}
}
它工作正常,所以可能与从Detail类外部调用UpdateDetail()函数有关。
我已经检查了是否通过向属性添加didSet来重置detailDescription引用,并且在加载视图时仅对其调用了一次
猜猜我可以使用计时器来解决问题,但是我完全困惑为什么detailItem有时显示为nil,所以非常感谢您进行健全性检查。
更新已回到基本知识_______
因此,我现在回到标准的Apple Master-> Detail视图模板,并添加了一个简单的计时器来更新列表。 ListView可以很好地更新,但是它仍然不会动态更新详细视图。在自己的班级之外。
加载MainView后,我正在使用1秒钟的计时器,列表视图可以很好地更新,但是详细信息不能。
在调试时,它可以很好地进入configureView(),但是在第一个viewDidLoad()之后,detailDescriptionLabel为零
已经尝试了以下所有建议,但是在每种情况下,在初始加载后对标签的弱引用都为零
完全困惑
@objc func doTimer() {
for index in 0..<objects.count {
objects[index]=(objects[index] as! NSDate).addingTimeInterval(1)
}
tableView.beginUpdates()
tableView.reloadRows(at: self.tableView.indexPathsForVisibleRows!, with: .none)
tableView.endUpdates()
DispatchQueue.main.async {
self.detailViewController?.configureView()
}
}
MasterViewController.swift的完整代码,其余与标准模板相同。
import UIKit
class MasterViewController: UITableViewController {
var detailViewController: DetailViewController? = nil
var objects = [Any]()
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
navigationItem.leftBarButtonItem = editButtonItem
let addButton = UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(insertNewObject(_:)))
navigationItem.rightBarButtonItem = addButton
if let split = splitViewController {
let controllers = split.viewControllers
detailViewController = (controllers[controllers.count-1] as! UINavigationController).topViewController as? DetailViewController
}
//Added timer here
_ = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(doTimer), userInfo: nil, repeats: true)
}
//Update data in list
@objc func doTimer() {
for index in 0..<objects.count {
objects[index]=(objects[index] as! NSDate).addingTimeInterval(1)
}
tableView.beginUpdates()
tableView.reloadRows(at: self.tableView.indexPathsForVisibleRows!, with: .none)
tableView.endUpdates()
DispatchQueue.main.async {
self.detailViewController?.configureView()
}
}
override func viewWillAppear(_ animated: Bool) {
clearsSelectionOnViewWillAppear = splitViewController!.isCollapsed
super.viewWillAppear(animated)
}
@objc
func insertNewObject(_ sender: Any) {
objects.insert(NSDate(), at: 0)
let indexPath = IndexPath(row: 0, section: 0)
tableView.insertRows(at: [indexPath], with: .automatic)
}
// MARK: - Segues
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "showDetail" {
if let indexPath = tableView.indexPathForSelectedRow {
let object = objects[indexPath.row] as! NSDate
let controller = (segue.destination as! UINavigationController).topViewController as! DetailViewController
controller.detailItem = object
controller.navigationItem.leftBarButtonItem = splitViewController?.displayModeButtonItem
controller.navigationItem.leftItemsSupplementBackButton = true
}
}
}
// MARK: - Table View
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return objects.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
let object = objects[indexPath.row] as! NSDate
cell.textLabel!.text = object.description
return cell
}
override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
// Return false if you do not want the specified item to be editable.
return true
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
objects.remove(at: indexPath.row)
tableView.deleteRows(at: [indexPath], with: .fade)
} else if editingStyle == .insert {
// Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view.
}
}
}
答案 0 :(得分:0)
我的答案基于所提供的Git存储库。
在MasterViewController中-您正在调用self.detailViewController?.configureView()
,但从未分配明细控制器,并且由于它是nil
,因此无法调用configureView
函数。您可以通过设置prepare(for segue: UIStoryboardSegue, sender: Any?)
self.detailViewController = controller
中进行此操作
这仍然无法帮助您更新标签值。
原因在于,在@objc func doTimer() {
中,您总是将一个新的Date
对象设置(覆盖)到数组中(可能的目的是更新相同引用的值)。因此,您分配给detailViewController的引用是不同的,并且您永远不会在计时器中更新detailItem
。因此,调用configureView
不会做任何更改,因为值保持不变。
答案 1 :(得分:-2)
之所以发生这种情况,是因为您的detailDescription标签“弱var detailDescription”较弱。而每次您编写此代码
guard let label = detailDescription else {
return; //Label not linked
}
label.text = "New Data"
您创建一个新对象并为该对象分配值。因此detailDescription标签对象的原始值不会更改。每次更改其值时,请尝试使用相同的detailDescription对象。