简体   繁体   English

Xcode Playground使用简单的UITableViewController代码崩溃

[英]Xcode Playground crashes with a simple UITableViewController code

I encountered a very strange problem with a UITableViewController subclass instance in the Xcode Playground. 我在Xcode Playground中的UITableViewController子类实例遇到一个非常奇怪的问题。 I registered two UITableViewCell s programmatically in viewDidLoad , and dequeued cells in cellForRowAt method: 我以编程方式在viewDidLoad注册了两个UITableViewCell ,并在cellForRowAt方法中使单元出队:

import UIKit
import PlaygroundSupport

class ViewController: UITableViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
    tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell1")
    tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell2")
  }

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

  override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    switch indexPath.row {
    case 0:
      return tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath)
    case 1:
      return tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath)
    default:
      fatalError()
    }
  }
}

let vc = ViewController(style: .plain)
PlaygroundPage.current.liveView = vc


But the Playground throws an NSException and shows: 但是Playground抛出NSException并显示:

error: Execution was interrupted, reason: signal SIGABRT.
The process has been left at the point where it was interrupted, use "thread return -x" to return to the state before expression evaluation.

Note that this code works well in a legit Xcode Project with an iPhone simulator. 请注意,此代码在带有iPhone模拟器的合法Xcode项目中效果很好。 Am I making a mistake here, or is it a bug? 我在这里犯错了,还是一个错误?

I'm using Version 10.3 (10G8). 我正在使用版本10.3(10G8)。

Curious bug... 好奇的错误...

This works fine: 这工作正常:

class ViewController: UITableViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell1")
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell2")
    }

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

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        return tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath)
    }
}

But this crashes: 但这崩溃了:

class ViewController: UITableViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell1")
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell2")
    }

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

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        return tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath)
    }
}

The only difference is that the example that crashes is returning the second registered cell. 唯一的区别是发生崩溃的示例返回了第二个已注册的单元格。

If you swap the order of the .register() statements, then "cell2" works and "cell1" crashes. 如果交换.register()语句的顺序,则"cell2"有效, "cell1"崩溃。


EDIT (Edit 2: we need to assign .delegate and .dataSource -- could be done in loadView() or viewDidLoad() ) 编辑 (编辑2:我们需要分配.delegate.dataSource可以在loadView()viewDidLoad()

Note that, since registering (and using) only one cell works as-is, it shouldn't be necessary to set the view. 需要注意的是,由于注册(使用)只有一格的作品原样,它不应该是必要设置视图。 However, if you do set the view in loadView() the code will run in Playground without crashing: 但是,如果您确实在loadView()设置了视图,则代码将在Playground中运行而不会崩溃:

class ViewController: UITableViewController {

    override func loadView() {
        let v = UITableView()
        v.delegate = self
        v.dataSource = self
        self.view = v
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell1")
        tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell2")
    }

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

    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        switch indexPath.row {
        case 0:
            return tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath)
        case 1:
            return tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath)
        default:
            fatalError()
        }
    }
}

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

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