tableView.dequeueReusableCellWithIdentifier()导致应用程序挂起

时间:2015-09-15 19:02:02

标签: ios swift uitableview swift2 ios9

原始帖子

我们最近将我们的应用程序转换为Swift 2.0和iOS9。我看到的一个奇怪的问题是调用tableView.dequeueReusableCellWithIdentifier()会导致应用程序在模拟器中挂起。

<小时/> 代码

func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    //hangs on the line below
    let headersection: HeaderSectionCell = tableView.dequeueReusableCellWithIdentifier("SectionHeader") as! HeaderSectionCell 

    ...

    return headersection
}

标题单元格

class HeaderSectionCell: UITableViewCell {

    @IBOutlet var labelOne: UITextView!
    @IBOutlet var labelTwo: UITextView!
    @IBOutlet var textView: UITextView!

}

模拟器CPU使用率为100%

CPU Pegging

<小时/> 在Xcode中点击暂停后,它显示它挂在这个Swift函数上。

Pausing while hanging shows us here

<小时/> 以下是iOS在循环中循环的一些例程。

enter image description here

enter image description here

最后,我们的Swift调用dequeueReusableCellWithIdentifier() enter image description here

这个特殊的悬挂实例来自函数tableView(tableView: UITableView, viewForHeaderInSection section: Int),但我们也在tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath)的调用中挂起了同样的问题。

我已尝试在故事板编辑器中使用单元格属性,但没有什么能与其他正常工作的视图区别开来。

修改

看来,在调用dequeReusableCellWithIdentifier()之下,Foundation和libobjc.A.dylib之间存在无限循环。我最终确保在任何其他框架之前导入Foundation,并将违规的UITableViewCell抽象到自己的类中(正在被重用)。有问题的原始呼叫现在正在运行,但还有另一个仍然在我正在努力解决的Swift封面下循环。

在无限循环中点击暂停会使我进入相同的汇编堆栈位置:

暂停后的堆栈跟踪:

libobjc.A.dylib`objc_msgSend:
    0x107f6a800 <+0>:   testq  %rdi, %rdi
    0x107f6a803 <+3>:   jle    0x107f6a850               ; <+80>
    0x107f6a805 <+5>:   movq   (%rdi), %r11
    0x107f6a808 <+8>:   movq   %rsi, %r10
    0x107f6a80b <+11>:  andl   0x18(%r11), %r10d
    0x107f6a80f <+15>:  shlq   $0x4, %r10
    0x107f6a813 <+19>:  addq   0x10(%r11), %r10
    0x107f6a817 <+23>:  cmpq   (%r10), %rsi
    0x107f6a81a <+26>:  jne    0x107f6a820               ; <+32>
->  0x107f6a81c <+28>:  jmpq   *0x8(%r10)

另一个暂停后的堆栈跟踪:

Foundation`-[NSLocalizableString length]:
    0x1071c5cbc <+0>:  pushq  %rbp
    0x1071c5cbd <+1>:  movq   %rsp, %rbp
->  0x1071c5cc0 <+4>:  movq   0x80461(%rip), %rax       ; NSLocalizableString._developmentLanguageString
    0x1071c5cc7 <+11>: movq   (%rdi,%rax), %rdi
    0x1071c5ccb <+15>: movq   0x7436e(%rip), %rsi       ; "length"
    0x1071c5cd2 <+22>: popq   %rbp
    0x1071c5cd3 <+23>: jmpq   *0x8ea77(%rip)            ; (void *)0x0000000107f6a800: objc_msgSend

它只是在这两个较低级别的例程之间来回循环,消耗了100%的模拟器CPU。

4 个答案:

答案 0 :(得分:13)

这是一个字符串本地化问题。 UITableViewCell包含UITextField,其Text属性的值为非空值,并未在UITextView的Localization属性中检查英语。

检查English解决了问题。

多么痛苦!去图,为什么不能无限循环而不是抛出可理解的错误?

答案 1 :(得分:5)

我的解决方案与styler1972相似。

就我而言,我正在将Swift 1.2的Swift / Objective-C项目组合升级到Swift 2.0。在升级到Swift 2.0之前,应用程序在iOS 9上正常运行。升级到Swift 2.0后,当从表视图单元附件推送到视图控制器时,应用程序将进入无限循环。在模拟器中运行应用程序,然后在无限循环中捕获它时,我离开了[NSLocalizableString length](这导致我发布了这篇文章)。

我的解决方法是执行以下操作。

  • 从en.lproj目录中删除Main.storyboard文件。
  • 删除en.lproj目录,包括InfoPlist.strings文件。
  • 将Main.storyboard放在根项目目录中。
  • 更新项目以反映上述更改。
  • 在信息/本地化下的项目设置中,删除所有设置。
  • 清理构建目录(为了更好地衡量)。
  • 清理构建(为了更好的措施)。
  • 构建并运行。

不再发生无限循环。

答案 2 :(得分:3)

请务必备份项目文件以便稍后恢复本地化文件。

  • 在项目设置,本地化中,删除除项目开发语言之外的所有本地化(对我来说是英语)。
  • 清洁并运行。此时您不应再看到错误。
  • 添加您上面删除的本地化,并从备份中恢复本地化。

答案 3 :(得分:0)

使用dequeueReusableHeaderFooterViewWithIdentifier代替dequeueReusableCellWithIdentifier

您正试图在viewForHeaderInSection中加载单元格,这也是不正确的。

<强>编辑:

class HeaderSectionView: UITableViewHeaderFooterView {

@IBOutlet var labelOne: UITextView!
@IBOutlet var labelTwo: UITextView!
@IBOutlet var textView: UITextView!

}

func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
    //hangs on the line below
    let headersection: HeaderSectionView = tableView.dequeueReusableHeaderFooterViewWithIdentifier("SectionHeader") as! HeaderSectionView

    ...

    return headersection
}

不要忘记将HeaderSectionView注册为

tableView.registerNib(UINib(nibName: "HeaderSectionView", bundle:nil), forHeaderFooterViewReuseIdentifier: "SectionHeader")