我似乎无法让我的自定义UITableView类作为另一个UITableView中存在的UITextField的inputView正常工作。
请参阅下面的屏幕截图。我有MainTableViewController,它包含两个部分:Section-1和Section-2。每个部分只包含一个单元格。每个单元格都有一个UITextField。第1节是关注的领域。它包含一个UITextField,其自定义UITableView作为其inputView。我命名了这个自定义的UITableView InputTableView并实现了UITableViewDataSource协议。
class InputTableView: UITableView, UITableViewDataSource
目标是让InputTableView像选项选择器一样。用户将单击InputTableView中的单元格,该选择将填充specialTextField
。
单击单元格时,InputView按预期显示。 Test Title
是UITableView部分标题。 Section 0 Row 0
是单元格内容。
这是InputTableView类中的numberOfRowsInSection
:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("tableView numberOfRowsInSection")
return 1
}
如果我返回大于1的任何内容,应用程序将崩溃并出现如下错误:
TableViewControllerTest [721:126633] *由于终止应用程序 未捕获的异常'NSRangeException',原因:'* - [__ NSSingleObjectArrayI objectAtIndex:]:索引1超出边界[0 .. 0]' ***首先抛出调用堆栈:(0x18db211b8 0x18c55855c 0x18db12420 0x19417c7bc 0x193ee7a40 0x193d1f9d4 0x193af5c20 0x193ab5478 0x193ab48c8 0x193ab4654 0x193ab4488 0x193d12e74 0x193d125a4 0x193d124a0 0x193a54550 0x193d35120 0x193d34aac 0x193a5399c 0x193a52fcc 0x1939d3090 0x1939f6c58 0x1939d22c4 0x18e57ad10 0x1939d2138 0x1939de018 0x1939dd904 0x1943b2298 0x1943b37f8 0x1943ac3c8 0x1943b37c8 0x1943a8488 0x1943b331c 0x1943abe38 0x193a9d240 0x1a1d15e98 0x1939fca78 0x193a5ab4c 0x193a5aebc 0x193add0b4 0x193b84128 0x193b83630 0x193f9ef80 0x193fa2688 0x193b6973c 0x193a080f0 0x193f92680 0x193f921e0 0x193f9149c 0x193a0630c 0x1939d6da0 0x1a1cb21e8 0x1941c075c 0x1941ba130 0x18daceb5c 0x18dace4a4 0x18dacc0a4 0x18d9fa2b8 0x18f4ae198 0x193a417fc 0x193a3c534 0x1000191f4 0x18c9dd5b8)libc ++ abi.dylib: 以NSException(lldb)
类型的未捕获异常终止
1)如果我向MainTableViewController添加另一行(将1行添加到Section-1总共2行),则numberOfRowsInSection可以返回2并运行正常。如果我添加另一行总共3行,那么该函数可以返回3并运行正常。任何更大的东西,它再次崩溃。我认为这些是有点相关的。但是,如果这两个项目甚至不属于同一个类,怎么可能呢?
2)如果我注释掉行inputTableView.delegate = self
,那么代码会再次运行而不会崩溃。我可以设置numberOfRowsInSection来返回任何数字(我试过5并且它有效)。但是,因为现在没有设置委托,所以我无法对用户交互做任何事情。
我的完整代码:
//
// MainTableViewController.swift
// TableViewControllerTest
//
// Created by Zion Perez on 1/29/17.
// Copyright © 2017 Zion Perez. All rights reserved.
//
import UIKit
class InputTableView: UITableView, UITableViewDataSource {
func setupTableView(){
self.dataSource = self
}
// MARK: - TableView DataSource
// https://developer.apple.com/reference/uikit/uitableviewdatasource
func numberOfSections(in tableView: UITableView) -> Int {
print("numberOfSections")
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("tableView numberOfRowsInSection")
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("tableView cellForRowAt: " + indexPath.description)
let id = "BasicCell"
var cell: UITableViewCell? = tableView.dequeueReusableCell(withIdentifier: id)
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: id)
}
cell?.textLabel?.text = "Section \(indexPath.section) Row \(indexPath.row)"
return cell!
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
print("tableView titleForHeaderInSection")
return "Test Title"
}
}
class MainTableViewController: UITableViewController {
@IBOutlet weak var specialTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let frame = CGRect(x: self.view.frame.minX, y: self.view.frame.minY, width: self.view.frame.width, height: 200.0)
let inputTableView = InputTableView(frame: frame)
inputTableView.setupTableView()
inputTableView.delegate = self
specialTextField.inputView = inputTableView
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - TableViewDelegate
// https://developer.apple.com/reference/uikit/uitableviewdelegate
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("selected row at " + indexPath.description)
}
override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
print("deselected row at " + indexPath.description)
}
}
我的代码也在Github上: https://github.com/starkindustries/TableViewControllerTest
我研究过的其他资料来源: UITableView crashes when number of rows >1
编辑(已解决的注释):
Muescha的回答帮助我解决了我的问题。作为参考,可以在下面的github链接(delegateRefactor分支)中找到代码的固定版本。带有问题的原始代码位于上面的github链接(主分支)。
https://github.com/starkindustries/TableViewControllerTest/tree/delegateRefactor
答案 0 :(得分:1)
您还需要在UITableViewDelegate
上添加InputTableView
。
为什么呢?因为您之前在ViewController
中已经拥有它(您应该将其命名为TableViewController
或MainTableViewController
,以便其他人有一个不是普通视图控制器的提示。)
但您已在Interface Builder中绘制了2个部分,每个部分有1个单元格。此单元格由隐藏的UITableViewDataSource
和隐藏的UITableViewDelegate
填充。如果我在表视图中单击并在界面生成器中查看传出连接但在那里没有类文件。
我认为当UITableViewDelegate
的{{1}}设置为InputTableView
时,它们会在其他请求中崩溃。在崩溃堆栈跟踪中,还有一个MainTableViewController
调用最后一次调用之一(这就是为什么:比你发布的更多错误和堆栈跟踪问题:最好找出错误 - 非常好你发布你的示例项目到github。否则主要故事板中的单元格设置将被隐藏给审阅者)
但是第一部分的主表上只有一个单元格。这就是为什么它与2个细胞坠毁。它试图获得单元格2的高度,但只有0 ... 0索引,这意味着= 1个单元格。
难点在于,heightForRowAt
的{{1}}和UITableViewDataSource
隐藏在某个地方并自动启动了一些方法。 (这就是为什么我个人不喜欢界面构建器和故事板,并通过代码完成所有操作)
这里的证明截图:
代码更改:
UITableViewDelegate
已移至MainTableViewController
协议self.delegate = self
已添加到InputTableView
这是代码:
UITableViewDelegate
答案 1 :(得分:0)
也许问题是因为UITableViewController子类... 它只需要一个表视图。只需将输入视图的委托分配给它自己,然后使用自定义委托将选定的索引或所需信息发送回表视图控制器。
答案 2 :(得分:0)
我认为你应该直接在ViewController中处理InputTableView的那些dataSource方法。
import UIKit
class InputTableView: UITableView, UITableViewDataSource {
func setupTableView(){
self.dataSource = self
}
// MARK: - TableView DataSource
// https://developer.apple.com/reference/uikit/uitableviewdatasource
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
print("tableView cellForRowAt: " + indexPath.description)
let id = "BasicCell"
var cell: UITableViewCell? = tableView.dequeueReusableCell(withIdentifier: id)
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: id)
}
cell?.textLabel?.text = "Section \(indexPath.section) Row \(indexPath.row)"
return cell!
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
print("tableView titleForHeaderInSection")
return "Test Title"
}
}
class ViewController: UITableViewController {
@IBOutlet weak var specialTextField: UITextField!
var inputTableView: InputTableView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let frame = CGRect(x: self.view.frame.minX, y: self.view.frame.minY, width: self.view.frame.width, height: 200.0)
inputTableView = InputTableView(frame: frame)
inputTableView.setupTableView()
inputTableView.delegate = self
specialTextField.inputView = inputTableView
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - TableViewDelegate
// https://developer.apple.com/reference/uikit/uitableviewdelegate
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("selected row at " + indexPath.description)
}
override func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) {
print("deselected row at " + indexPath.description)
}
func numberOfSections(in tableView: UITableView) -> Int {
if tableView == inputTableView {
print("numberOfSections")
return 1
} else {
deal with your other tableView
}
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == inputTableView {
print("numberOfRowsInSection ")
return 1
} else {
deal with your other tableView
}
}
}