如何在swift3中以其他方法更新UITableviewcell标签?

Posted

技术标签:

【中文标题】如何在swift3中以其他方法更新UITableviewcell标签?【英文标题】:How to update UITableviewcell label in other method in swift3? 【发布时间】:2017-09-29 07:40:42 【问题描述】:

我正在尝试用其他方法更新 UITableviewcell 的标签。我还看到了很多关于 *** 的帖子,对我来说不是工作。我正在使用 Swift 3,我尝试了这个:

    let indexPath = IndexPath.init(row: 0, section: 0)
    let cell : CategoryRow = tableView.cellForRow(at: indexPath) as! CategoryRow

我收到了这个错误:

fatal error: unexpectedly found nil while unwrapping an Optional value

我在其他方法中使用它,我在 24 小时后更新 tableviewcell 标签文本。 代码在这里

var myQuoteArray = ["“If you have time to breathe you have time to meditate. You breathe when you walk. You breathe when you stand. You breathe when you lie down. – Ajahn Amaro”","We are what we repeatedly do. Excellence, therefore, is not an act but a habit. – Aristotle","The best way out is always through. – Robert Frost","“If you have time to breathe you have time to meditate. You breathe when you walk. You breathe when you stand. You breathe when you lie down. – Ajahn Amaro”","We are what we repeatedly do. Excellence, therefore, is not an act but a habit. – Aristotle","The best way out is always through. – Robert Frost"

    ]
func checkLastRetrieval()

   //        let indexPath = IndexPath.init(row: 0, section: 0)
   //        let cell : CategoryRow = tableView.cellForRow(at: indexPath) as? CategoryRow


    let indexPath = IndexPath.init(row: 0, section: 0)
   guard let cell = tableView.cellForRow(at: indexPath) as? CategoryRow else  return 

    print("Getting Error line 320")// This is not printing on console

let userDefaults = UserDefaults.standard

if let lastRetrieval = userDefaults.dictionary(forKey: "lastRetrieval") 
if let lastDate = lastRetrieval["date"] as? NSDate 
if let index = lastRetrieval["index"] as? Int 
if abs(lastDate.timeIntervalSinceNow) > 86400  // seconds in 24 hours
// Time to change the label
var nextIndex = index + 1

// Check to see if next incremented index is out of bounds
if self.myQuoteArray.count <= nextIndex 
// Move index back to zero? Behavior up to you...
nextIndex = 0




cell?.quotationLabel.text = self.myQuoteArray[nextIndex]

let lastRetrieval : [NSObject : AnyObject] = [
"date" as NSObject : NSDate(),
"index" as NSObject : nextIndex as AnyObject
]

userDefaults.set(lastRetrieval, forKey: "lastRetrieval")
userDefaults.synchronize()

// Do nothing, not enough time has elapsed to change labels


 else 

// No dictionary found, show first quote
cell?.quotationLabel.text = self.myQuoteArray.first!

     print("line 357")
// Make new dictionary and save to NSUserDefaults
let lastRetrieval : [NSObject : AnyObject] = [
"date" as NSObject : NSDate(),
"index" as NSObject : 0 as AnyObject
]

userDefaults.set(lastRetrieval, forKey: "lastRetrieval")
userDefaults.synchronize()



并在 ViewDidLoad() 中调用此方法

 override func viewDidLoad() 
    super.viewDidLoad()

     checkLastRetrieval()
    

我该怎么办? 提前致谢

【问题讨论】:

使用 ? 使 CategoryRow 标签可选而不是! 我认为您正在更新单元格,而表格视图中没有单元格。 当您尝试这样做时,此单元格是否可见? Nauman Malik,我已经做到了。但是没有用。 您的表格视图不会在viewDidLoad 中呈现,因此此时屏幕上不会有任何单元格。直到viewDidAppear,单元格才会出现在屏幕上。正如我在下面的评论中所说,正确的做法是更新表格的数据模型,以便在随后加载单元格时显示正确的数据。 【参考方案1】:

如果请求的单元格当前不在屏幕上,则函数cellForRow(at:) 返回nil。由于您在viewDidLoad 中调用您的函数,因此屏幕上将没有单元格。这会导致崩溃,因为您强制向下转换 cellForRow(at:) 的结果。

你不应该使用强制展开或强制向下转换,除非你绝对 确定结果不能是nil 和/或如果是nil,唯一可能的操作是让您的应用崩溃。

通常您不应直接更新单元格。最好更新表格的数据模型,然后调用reloadRows(at:,with:) 并让您的数据源cellForRow(at:) 函数处理更新单元格。

如果您要直接更新单元格,请确保使用带有if letguard let 的条件向下转换,以避免在单元格不可见时发生崩溃。在这种情况下,您仍然需要更新数据模型,以便当单元格出现在屏幕上时单元格数据是正确的。

【讨论】:

感谢 Paulw11,现在我可以正确获取单元格,但我的标签文本仍未更新。 您试图在viewDidLoad 中运行代码的事实让我感到怀疑;如果单元格已经在屏幕上,为什么需要在viewDidLoad 中运行任何东西?我怀疑您正在创建视图控制器的新实例并更新它,而不是更新屏幕上已经存在的实例。您的更新似乎是基于时间的。计时器在哪里运行?当它着火时你会怎么做? 根据 Apple 描述,我不能玩超过 3 分钟的计时器,这就是为什么我将自定义数据存储在字典中,而不是从上次日期检查它而不是更新标签。可能是我做错了吗? 我无法理解的是你为什么要做这一切;您需要做的就是在应用程序加载时将数据加载到表中,并检查当您的应用程序返回前台时是否需要刷新数据。如果是,请重新加载该行。【参考方案2】:

你应该使用guard let声明:

let indexPath = IndexPath(row: 0, section: 0)
guard let cell = tableView.cellForRow(at: indexPath) as? CategoryRow else  return 

如果您的cell 类型不是CategoryRow,您将从该方法返回。尝试找出为什么您的cell 类型不是CategoryRow

【讨论】:

感谢您的回复,我有一个 CategoryRow 单元格,它工作正常,其他元素在 cellForRowAtIndexPath 中正确显示。但它在外面不起作用。 更重要的是,如果单元格当前不在屏幕上,cellForRow(at:) 将返回 nil;您应该按照建议使用if letguard let 对此做好准备。通常,您应该更新数据源,然后重新加载受影响的行,而不是直接更新单元格。 @ChetanLodhi,您在哪里使用此代码(哪种方法)? V.Khambir ......实际上我在其他方法中使用此代码,我在 24 小时后更新标签文本。并且这个方法在 Viewdidload 中被调用。 @ChetanLodhi,可能,此时您在 IndexPath(row: 0, section: 0) 处没有任何单元格。

以上是关于如何在swift3中以其他方法更新UITableviewcell标签?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Swift3 中以秒为单位将字符串更改为分钟?

如何在 Swift3 iOS 中以特定时间在 AVPlayer 中播放视频

在 Swift 中以编程方式访问和更新 stackview 中的 label.text 或其他 UILabel 属性

如何在 Android Studio 中以除 onCreate 之外的其他方法获取应用程序的上下文?

如何在 swift 3 中以编程方式为 barButtonItem 设置操作?

如何在 Swift 3 中以编程方式在 UIImageview 中添加 UITableview