gpt4 book ai didi

ios - TableView单元格不断改变顺序

转载 作者:行者123 更新时间:2023-11-30 11:17:40 24 4
gpt4 key购买 nike

我正在制作的计时器应用程序发生了一些奇怪的事情:

每 0.25 秒我更新每个单元格的内容,但有时我会遇到这个奇怪的故障/错误(表格 View 单元格不断改变顺序):

https://streamable.com/tta56

更新计时器的代码:

计时器:

timer = Timer.scheduledTimer(timeInterval: 0.25, target: self, selector: #selector(processTimer), userInfo: nil, repeats: true)

processTimer()函数:

@objc func processTimer() {
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "TimersData")
request.returnsObjectsAsFaults = false

do {
let results = try context.fetch(request)

var i = 0
if results.count > 0 {
for result in results as! [NSManagedObject] {
if let activityIndicator = result.value(forKey: "activity") as? String {
if activityIndicator == "active" {
if let startDate = result.value(forKey: "startDate") as? Date {
var seconds = startDate.timeIntervalSinceNow
seconds = seconds * -1
if let timerSeconds = result.value(forKey: "timerSeconds") as? Int {
if let timerProgress = result.value(forKey: "timerProgress") as? Double {
var newSeconds: Double = timerProgress - seconds
if newSeconds < 0 {
newSeconds = 0
}
result.setValue(newSeconds, forKey: "timerProgress")
let now = Date()
result.setValue(now, forKey: "startDate")
do {
try context.save()
}
catch {
print("error")
}
result.setValue(Date(), forKey: "startDate")
// TEST OUT datesArray[i] = Date()
}
}
else {
result.setValue(Date(), forKey: "startDate")
// TEST OUT datesArray[i] = Date()
}
}
else {
result.setValue(Date(), forKey: "startDate")
}
}
else {
result.setValue(nil, forKey: "startDate")
// TEST OUT datesArray[i] = nil
}
}
i += 1
}
}

}
catch {

}

// tableView.reloadData()
let indexPathsArray = tableView.indexPathsForVisibleRows
for indexPath in indexPathsArray! {

var activity = ""

let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "TimersData")
request.returnsObjectsAsFaults = false

do {
let results = try context.fetch(request)

if results.count > 0 {
if segmentedControl.selectedSegmentIndex == 0 {

let result = (results as! [NSManagedObject])[indexPath.row]
if let activityIndicator = result.value(forKey: "activity") as? String {
activity = activityIndicator
}

var timerString = ""
var hourString = ""
var minuteString = ""
var secondString = ""
if let seconds = result.value(forKey: "timerSeconds") as? Int {
if let secondsLeftDouble = result.value(forKey: "timerProgress") as? Double {
let secondsLeft: Int = Int(floor(1*secondsLeftDouble)/1)
if seconds < 1 {
}
else if seconds >= 5 && seconds < 60 { // ss
timerString = "\(secondsLeft)s"
}
else if seconds >= 60 && seconds < 3600 { // mm:ss
let minute = secondsLeft / 60
minuteString = "\(minute)"
if minute < 10 {

minuteString = "0\(minute)"

}
let second = secondsLeft % 60
var secondString: String = "\(second)"
if second < 10 {

secondString = "0\(second)"

}
timerString = "\(minuteString):\(secondString)"

}
else if seconds >= 3600 && seconds <= 86400 { // hh:mm:ss
let hourString: String = "\(secondsLeft / 3600)"
let minute = (secondsLeft % 3600) / 60
var minuteString: String = "\(minute)"
if minute < 10 {

minuteString = "0\(minute)"

}
let second = (secondsLeft % 3600) % 60
var secondString: String = "\(second)"
if second < 10 {

secondString = "0\(second)"

}
timerString = "\(hourString):\(minuteString):\(secondString)"
}
}
}

var timerTitle = ""
if let title = result.value(forKey: "timerName") as? String {
timerTitle = title
}

let cell = tableView.cellForRow(at: indexPath) as! activeTableViewCell
cell.configureCell(name: timerTitle, time: timerString, activityIndicator: activity, indexPathToSend: indexPath.row)

/* if activity == "active" {
let cell = tableView.cellForRow(at: indexPath) as! activeTableViewCell
cell.configureCell(name: timerTitle, time: timerString)
cell.sendIndexPath(indexPathToSend: indexPath.row)
}
else if activity == "paused" {
let cell = tableView.cellForRow(at: indexPath) as! pausedTableViewCell
cell.configureCell(name: timerTitle, time: timerString)
}
else if activity == "none" {
let cell = tableView.cellForRow(at: indexPath) as! nonactiveTableViewCell
cell.configureCell(name: timerTitle, time: timerString)
}
else {
let cell = tableView.cellForRow(at: indexPath) as! nonactiveTableViewCell
cell.configureCell(name: timerTitle, time: timerString)
} */

}
else {
var i = 0
activeTimersArray = []
for result in results as! [NSManagedObject] {
if let activityIndicator = result.value(forKey: "activity") as? String {
if activityIndicator == "active" {
activeTimersArray.append(i)
}
}
i += 1
}

if indexPath.row < activeTimersArray.count {
let result = (results as! [NSManagedObject])[activeTimersArray[indexPath.row]]

var timerString = ""
var hourString = ""
var minuteString = ""
var secondString = ""
if let seconds = result.value(forKey: "timerSeconds") as? Int {
if let secondsLeftDouble = result.value(forKey: "timerProgress") as? Double {
let secondsLeft: Int = Int(round(secondsLeftDouble))
if seconds < 1 {
}
else if seconds >= 5 && seconds < 60 { // ss
timerString = "\(secondsLeft)s"
}
else if seconds >= 60 && seconds < 3600 { // mm:ss
let minute = secondsLeft / 60
minuteString = "\(minute)"
if minute < 10 {

minuteString = "0\(minute)"

}
let second = secondsLeft % 60
var secondString: String = "\(second)"
if second < 10 {

secondString = "0\(second)"

}
timerString = "\(minuteString):\(secondString)"

}
else if seconds >= 3600 && seconds <= 86400 { // hh:mm:ss
let hourString: String = "\(secondsLeft / 3600)"
let minute = (secondsLeft % 3600) / 60
var minuteString: String = "\(minute)"
if minute < 10 {

minuteString = "0\(minute)"

}
let second = (secondsLeft % 3600) % 60
var secondString: String = "\(second)"
if second < 10 {

secondString = "0\(second)"

}
timerString = "\(hourString):\(minuteString):\(secondString)"
}
}
}

var timerTitle = ""
if let title = result.value(forKey: "timerName") as? String {
timerTitle = title
}

let cell = tableView.cellForRow(at: indexPath) as! activeTableViewCell
cell.configureCell(name: timerTitle, time: timerString, activityIndicator: "active", indexPathToSend: indexPath.row)
}
else {
let cell = tableView.cellForRow(at: indexPath) as! activeTableViewCell
cell.configureCell(name: "Processing", time: "Processing", activityIndicator: "active", indexPathToSend: indexPath.row)
}


}

}
else {
// let cell = tableView.cellForRow(at: indexPath) as! nonactiveTableViewCell
// cell.configureCell(name: "Error", time: "Error")
let cell = tableView.cellForRow(at: indexPath) as! activeTableViewCell
cell.configureCell(name: "Error", time: "Error", activityIndicator: "none", indexPathToSend: indexPath.row)
}
}
catch {
// let cell = tableView.cellForRow(at: indexPath) as! nonactiveTableViewCell
// cell.configureCell(name: "Error", time: "Error")

let cell = tableView.cellForRow(at: indexPath) as! activeTableViewCell
cell.configureCell(name: "Error", time: "Error", activityIndicator: "none", indexPathToSend: indexPath.row)
}
}
}

TableView数据源代码:

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {

var noRows = 0

let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "TimersData")
request.returnsObjectsAsFaults = false

do {
let results = try context.fetch(request)

if segmentedControl.selectedSegmentIndex == 0 {
noRows = results.count
}
else {
for result in results as! [NSManagedObject] {
if let activityIndicator = result.value(forKey: "activity") as? String {
if activityIndicator == "active" {
noRows += 1
}
}
}
}

}
catch {

}

return noRows
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var activity = ""

let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let request = NSFetchRequest<NSFetchRequestResult>(entityName: "TimersData")
request.returnsObjectsAsFaults = false

do {
let results = try context.fetch(request)

if results.count > 0 {
if segmentedControl.selectedSegmentIndex == 0 {

let result = (results as! [NSManagedObject])[indexPath.row]
if let activityIndicator = result.value(forKey: "activity") as? String {
activity = activityIndicator
}

var timerString = ""
var hourString = ""
var minuteString = ""
var secondString = ""
if let seconds = result.value(forKey: "timerSeconds") as? Int {
if let secondsLeftDouble = result.value(forKey: "timerProgress") as? Double {
let secondsLeft: Int = Int(round(secondsLeftDouble))
if seconds < 1 {
}
else if seconds >= 5 && seconds < 60 { // ss
timerString = "\(secondsLeft)s"
}
else if seconds >= 60 && seconds < 3600 { // mm:ss
let minute = secondsLeft / 60
minuteString = "\(minute)"
if minute < 10 {

minuteString = "0\(minute)"

}
let second = secondsLeft % 60
var secondString: String = "\(second)"
if second < 10 {

secondString = "0\(second)"

}
timerString = "\(minuteString):\(secondString)"

}
else if seconds >= 3600 && seconds <= 86400 { // hh:mm:ss
let hourString: String = "\(secondsLeft / 3600)"
let minute = (secondsLeft % 3600) / 60
var minuteString: String = "\(minute)"
if minute < 10 {

minuteString = "0\(minute)"

}
let second = (secondsLeft % 3600) % 60
var secondString: String = "\(second)"
if second < 10 {

secondString = "0\(second)"

}
timerString = "\(hourString):\(minuteString):\(secondString)"
}
}
}

var timerTitle = ""
if let title = result.value(forKey: "timerName") as? String {
timerTitle = title
}

let cell = tableView.dequeueReusableCell(withIdentifier: "active", for: indexPath) as! activeTableViewCell
cell.configureCell(name: timerTitle, time: timerString, activityIndicator: activity, indexPathToSend: indexPath.row)
return cell

/* if activity == "active" {
let cell = tableView.dequeueReusableCell(withIdentifier: "active", for: indexPath) as! activeTableViewCell
cell.configureCell(name: timerTitle, time: timerString)
return cell
}
else if activity == "paused" {
let cell = tableView.dequeueReusableCell(withIdentifier: "paused", for: indexPath) as! pausedTableViewCell
cell.configureCell(name: timerTitle, time: timerString)
return cell
}
else if activity == "none" {
let cell = tableView.dequeueReusableCell(withIdentifier: "inactive", for: indexPath) as! nonactiveTableViewCell
cell.configureCell(name: timerTitle, time: timerString)
return cell
}
else {
let cell = tableView.dequeueReusableCell(withIdentifier: "inactive", for: indexPath) as! nonactiveTableViewCell
cell.configureCell(name: timerTitle, time: timerString)
return cell
} */

}
else {
var i = 0
activeTimersArray = []
for result in results as! [NSManagedObject] {
if let activityIndicator = result.value(forKey: "activity") as? String {
if activityIndicator == "active" {
activeTimersArray.append(i)
}
}
i += 1
}

if indexPath.row < activeTimersArray.count {
let result = (results as! [NSManagedObject])[activeTimersArray[indexPath.row]]

var timerString = ""
var hourString = ""
var minuteString = ""
var secondString = ""
if let seconds = result.value(forKey: "timerSeconds") as? Int {
if let secondsLeftDouble = result.value(forKey: "timerProgress") as? Double {
let secondsLeft: Int = Int(round(secondsLeftDouble))
if seconds < 1 {
}
else if seconds >= 5 && seconds < 60 { // ss
timerString = "\(secondsLeft)s"
}
else if seconds >= 60 && seconds < 3600 { // mm:ss
let minute = secondsLeft / 60
minuteString = "\(minute)"
if minute < 10 {

minuteString = "0\(minute)"

}
let second = secondsLeft % 60
var secondString: String = "\(second)"
if second < 10 {

secondString = "0\(second)"

}
timerString = "\(minuteString):\(secondString)"

}
else if seconds >= 3600 && seconds <= 86400 { // hh:mm:ss
let hourString: String = "\(secondsLeft / 3600)"
let minute = (secondsLeft % 3600) / 60
var minuteString: String = "\(minute)"
if minute < 10 {

minuteString = "0\(minute)"

}
let second = (secondsLeft % 3600) % 60
var secondString: String = "\(second)"
if second < 10 {

secondString = "0\(second)"

}
timerString = "\(hourString):\(minuteString):\(secondString)"
}
}
}

var timerTitle = ""
if let title = result.value(forKey: "timerName") as? String {
timerTitle = title
}

let cell = tableView.dequeueReusableCell(withIdentifier: "active", for: indexPath) as! activeTableViewCell
cell.configureCell(name: timerTitle, time: timerString, activityIndicator: "active", indexPathToSend: indexPath.row)
return cell
}
else {
let cell = tableView.dequeueReusableCell(withIdentifier: "active", for: indexPath) as! activeTableViewCell
cell.configureCell(name: "Processing", time: "Processing", activityIndicator: "active", indexPathToSend: indexPath.row)
return cell
}


}

}
else {
/* let cell = tableView.dequeueReusableCell(withIdentifier: "inactive", for: indexPath) as! nonactiveTableViewCell
cell.configureCell(name: "Error", time: "Error")
return cell */

let cell = tableView.dequeueReusableCell(withIdentifier: "active", for: indexPath) as! activeTableViewCell
cell.configureCell(name: "Error", time: "Error", activityIndicator: "none", indexPathToSend: indexPath.row)
return cell
}
}
catch {
/* let cell = tableView.dequeueReusableCell(withIdentifier: "inactive", for: indexPath) as! nonactiveTableViewCell
cell.configureCell(name: "Error", time: "Error")
return cell */

let cell = tableView.dequeueReusableCell(withIdentifier: "active", for: indexPath) as! activeTableViewCell
cell.configureCell(name: "Error", time: "Error", activityIndicator: "none", indexPathToSend: indexPath.row)
return cell
}

}

忽略任何评论 - 它们只是我试图解决其他问题。

最佳答案

出于性能原因,核心数据无序保存记录。

如果您想要特定的顺序,则需要应用适当的排序描述符

let request = NSFetchRequest<NSFetchRequestResult>(entityName: "TimersData")
request.sortDescriptors = [NSSortDescriptor(key:"startDate", ascending: true)]

startDate 替换为所需的属性名称。

对于每秒 4 次以及每次调用 cellForRow 时获取 Core Data 对象的可疑必要性没有任何评论😉

关于ios - TableView单元格不断改变顺序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51593151/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com