Xcode Playground 使用简单的 UITableViewController 代码崩溃
Xcode Playground crashes with a simple UITableViewController code
我在 Xcode Playground 中遇到了一个关于 UITableViewController
子类实例的非常奇怪的问题。
我在 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
但是 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.
请注意,此代码在带有 iPhone 模拟器的合法 Xcode 项目中运行良好。是我弄错了还是bug?
我使用的是版本 10.3 (10G8)。
奇怪的错误...
这很好用:
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)
}
}
但这会崩溃:
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)
}
}
仅的区别是崩溃的例子返回了second注册单元格.
如果交换 .register()
语句的顺序,则 "cell2"
可以正常工作,而 "cell1"
会崩溃。
编辑 (编辑 2:我们需要分配 .delegate
和 .dataSource
——可以在 loadView()
或 viewDidLoad()
)
请注意,由于仅注册(和使用)一个单元格按原样工作,因此不应该 设置视图。但是,如果您在 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()
}
}
}
我在 Xcode Playground 中遇到了一个关于 UITableViewController
子类实例的非常奇怪的问题。
我在 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
但是 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.
请注意,此代码在带有 iPhone 模拟器的合法 Xcode 项目中运行良好。是我弄错了还是bug?
我使用的是版本 10.3 (10G8)。
奇怪的错误...
这很好用:
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)
}
}
但这会崩溃:
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)
}
}
仅的区别是崩溃的例子返回了second注册单元格.
如果交换 .register()
语句的顺序,则 "cell2"
可以正常工作,而 "cell1"
会崩溃。
编辑 (编辑 2:我们需要分配 .delegate
和 .dataSource
——可以在 loadView()
或 viewDidLoad()
)
请注意,由于仅注册(和使用)一个单元格按原样工作,因此不应该 设置视图。但是,如果您在 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()
}
}
}