简体   繁体   English

在Swift 3中使可重用单元出队非常慢

[英]Dequeuing reusable cell in Swift 3 is incredibly slow

Dequeuing a cell is taking 0.5-1.0 seconds which means that my UITableView takes more than 2-3 full seconds to load even though it only has 4 rows. 使单元出队需要0.5-1.0秒的时间,这意味着即使只有4行,我的UITableView仍需要花费2-3个完整的秒来加载。

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    var cellid = "NumberCell"
    var isnumber = true
    if indexPath.row == 0 {
        cellid = "TextCell"
        isnumber = false
    }

    NSLog("before dequeue \(indexPath)")
    let cell = tableView.dequeueReusableCell(withIdentifier: cellid, for: indexPath) as! TextfieldTableViewCell
    NSLog("dequeued")

    // ...

    return cell
}

The NSLog() statements directly before and after show that the dequeue takes from 07.47 to 08.38 . 之前和之后的NSLog()语句表明出队时间从07.4708.38

2017-07-25 22:07:07.471898-0700 myapp[10209:4507471] before dequeue [0, 0] 2017-07-25 22:07:07.471898-0700 myapp [10209:4507471]在出队[0,0]之前

2017-07-25 22:07:07.679715-0700 myapp[10209:4507471] [MC] System group container for systemgroup.com.apple.configurationprofiles path is /private/var/containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles 2017-07-25 22:07:07.679715-0700 myapp [10209:4507471] [MC] systemgroup.com.apple.configurationprofiles路径的系统组容器为/private/var/containers/Shared/SystemGroup/systemgroup.com.apple .configurationprofiles

2017-07-25 22:07:07.683843-0700 myapp[10209:4507471] [MC] Reading from public effective user settings. 2017-07-25 22:07:07.683843-0700 myapp [10209:4507471] [MC]从公共有效用户设置中读取。

2017-07-25 22:07:08.386960-0700 myapp[10209:4507471] dequeued 2017-07-25 22:07:08.386960-0700 myapp [10209:4507471]出队

The cell is very simple. 该单元非常简单。 It just has a UILabel and a UITextField and the UITextField has an Editing Changed action. 它只有一个UILabel和一个UITextField,而UITextField具有一个Editing Changed动作。 That's it. 而已。

在此处输入图片说明

What the heck could possibly be causing it to take SO long to dequeue a cell? 是什么原因可能导致它花了这么长时间才能出队? Is it those other two system NSLog()s about the System group container? 是关于系统组容器的其他两个系统NSLog()吗?

It makes my app almost unusable because when I try to segue to this view controller the app appears to lock up for 2-4 seconds while it's setting up the 4 rows. 这使我的应用几乎无法使用,因为当我尝试使用此视图控制器时,该应用在设置4行时似乎锁定了2-4秒。

I've made hundreds of UITableViewControllers in Objective-C and I've never had this problem. 我已经在Objective-C中制作了数百个UITableViewController,而我从来没有遇到过这个问题。 Is there something weird about Swift 3 that I'm missing? 我想念的Swift 3有点奇怪吗?

2017-07-25 22:07:07.679715-0700 myapp[10209:4507471] [MC] System group container for systemgroup.com.apple.configurationprofiles path is /private/var/containers/Shared/SystemGroup/systemgroup.com.apple.configurationprofiles 2017-07-25 22:07:07.679715-0700 myapp [10209:4507471] [MC] systemgroup.com.apple.configurationprofiles路径的系统组容器为/private/var/containers/Shared/SystemGroup/systemgroup.com.apple .configurationprofiles

2017-07-25 22:07:07.683843-0700 myapp[10209:4507471] [MC] Reading from public effective user settings. 2017-07-25 22:07:07.683843-0700 myapp [10209:4507471] [MC]从公共有效用户设置中读取。

⚠️ This is a log from OS Level . ⚠️这是来自OS Level的日志。 which delay in dequeuing your UITableCell 哪个延迟将UITableCell出队

You can disable unwanted log in xcode . 您可以禁用xcode不需要的日志。 like below 像下面

1- From Xcode menu open: Product > Scheme > Edit Scheme 1-从Xcode菜单中打开:“ Product > Scheme > Edit Scheme

2- On your Environment Variables set OS_ACTIVITY_MODE in the value set disable 2-在环境变量上,将OS_ACTIVITY_MODE设置为disable的值

在此处输入图片说明

You will face this problem only when you are debugging the app . 仅在调试应用程序时,您才会遇到此问题。 this will run fine on real device . 这将在真实设备上正常运行。

I finally figured out the problem and it was entirely my fault. 我终于找到了问题所在,这完全是我的错。 I was accidentally requesting first responder on every field. 我无意间在每个领域都要求第一响应者。

For convenience, I had overridden setSelected(_:animated:) so that if I touched the row that row's textfield would become first responder (just in case I tried to tap on a field and missed). 为了方便起见,我重写了setSelected(_:animated:)以便如果我触摸该行,则该行的文本字段将成为第一响应者(以防万一我试图轻按一个字段并错过了它)。 The problem was that I forgot to put an if statement around the becomeFirstResponder() call. 问题是我忘了在becomeFirstResponder()调用周围放一个if语句。

Bad code: 错误代码:

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    self.textfield.becomeFirstResponder()
}

After dequeuing a cell it would set it to selected=false by default which would cause it to try to become first responder. 使单元出队后,默认情况下会将其设置为selected = false,这将导致它尝试成为第一响应者。 It was a dumb mistake on my part. 我这是一个愚蠢的错误。

Here's what I intended to do: 这是我打算做的:

override func setSelected(_ selected: Bool, animated: Bool) {
    super.setSelected(selected, animated: animated)

    if selected {
        self.textfield.becomeFirstResponder()
    }
}

I don't think there is any problem with this piece of code. 我认为这段代码没有任何问题。 And I don't think the dequeue code really lasts for so long unless you're missing some important issues in your code. 而且我认为出dequeue代码不会持续这么长时间,除非您在代码中遗漏了一些重要的问题。 If your table view is as simple as you said, that wouldn't take so long. 如果您的表格视图像您说的那样简单,那将不需要很长时间。 But to debug that, you must consider these points: 但是要进行调试,必须考虑以下几点:

  • NSLog is not a trustworthy timer for checking dequeue 's duration. NSLog不是用于检查dequeue持续时间的可靠计时器。 You should use the code below to calculate the time accurately: 您应该使用下面的代码来准确计算时间:

    let start = CACurrentMediaTime() 让开始= CACurrentMediaTime()
    let cell = tableView.dequeueReusableCell(withIdentifier: cellid, for: indexPath) as! 让cell = tableView.dequeueReusableCell(withIdentifier:cellid,for:indexPath)为! TextfieldTableViewCell TextfieldTableViewCell
    let finish = CACurrentMediaTime() 让我们完成= CACurrentMediaTime()
    print("dequeue time:(finish - start)") 打印(“出队时间:(完成-开始)”)

  • If the dequeue time is acceptable, your performance issue is not caused by it. 如果出dequeue时间可以接受,则您的性能问题不是由它引起的。

  • If the dequeue time is still not acceptable. 如果出dequeue时间仍然不可接受。 One reason makes sense is that you have only four rows of your tableview and none of them are higher than the tableview, so tableview is not going to use the cell from the buffer but going to create a cell from the bottom up. 一个有道理的原因是,您的表视图只有四行,而且没有一行高于表视图,因此表视图不会使用缓冲区中的单元格,而是会从下往上创建一个单元格。 And this operation is far more time-consuming than using the cell from the buffer. 而且此操作比使用缓冲区中的单元要花费更多的时间。 But this process is inevitable because every app using tableview will encounter it. 但是这个过程是不可避免的,因为每个使用tableview的应用程序都会遇到它。 Therefore, you should consider if your simulator(Assumed you're using a simulator) is too slow to run your app. 因此,您应该考虑模拟器(假设您使用的是模拟器)是否太慢而无法运行您的应用程序。 Because the speed between simulator and real iPhone is quite different. 因为模拟器和真实iPhone之间的速度差异很大。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM