Swift: 初始化 UITableViewCells 时出现 NSRangeException
Swift: NSRangeException when initializing UITableViewCells
我在尝试让 UITableView 正常运行时遇到了一些小问题。这是错误的样子:
* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty NSArray'
我已将问题缩小到这个特定的代码片段:(第 2 行)
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(String(TestCell), forIndexPath: indexPath)
return cell
}
完整 Swift 文件:
class ViewController: UITableViewController {
let closeHeight: CGFloat = 91
let openHeight: CGFloat = 166
var itemHeight = [CGFloat](count: 4, repeatedValue: 91.0)
override func viewDidLoad() {
super.viewDidLoad()
tableView.registerClass(TestCell.self, forCellReuseIdentifier: String(TestCell))
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemHeight.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(String(TestCell), forIndexPath: indexPath)
return cell
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return itemHeight[indexPath.row]
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath) as! FoldingCell
var duration = 0.0
if itemHeight[indexPath.row] == closeHeight { // open cell
itemHeight[indexPath.row] = openHeight
cell.selectedAnimation(true, animated: true, completion: nil)
duration = 0.5
} else {// close cell
itemHeight[indexPath.row] = closeHeight
cell.selectedAnimation(false, animated: true, completion: nil)
duration = 1.1
}
UIView.animateWithDuration(duration, delay: 0, options: .CurveEaseOut, animations: { () -> Void in
tableView.beginUpdates()
tableView.endUpdates()
}, completion: nil)
}
}
编辑 1:
class TestCell: FoldingCell {
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
containerView = createContainerView()
foregroundView = createForegroundView()
// super class method configure views
commonInit()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func animationDuration(itemIndex: NSInteger, type: AnimationType) -> NSTimeInterval {
// durations count equal it itemCount
let durations = [0.33, 0.26, 0.26] // timing animation for each view
return durations[itemIndex]
}
}
extension TestCell{
func createForegroundView() -> RotatedView{
let foregroundView = RotatedView(frame: .zero)
foregroundView.backgroundColor = UIColor.blackColor()
foregroundView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(foregroundView)
foregroundView.topAnchor.constraintEqualToAnchor(foregroundView.superview?.topAnchor, constant: 25)
foregroundView.leftAnchor.constraintEqualToAnchor(foregroundView.superview?.leftAnchor, constant: 25)
foregroundView.widthAnchor.constraintEqualToAnchor(foregroundView.superview?.widthAnchor, constant: -50)
foregroundView.heightAnchor.constraintEqualToConstant(100)
let topConstraint = foregroundView.constraints[0]
topConstraint.identifier = "ForegroundViewTop"
foregroundView.layoutIfNeeded()
return foregroundView
}
func createContainerView() -> UIView {
let containerView = UIView(frame: .zero)
containerView.backgroundColor = UIColor.grayColor()
containerView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(containerView)
containerView.topAnchor.constraintEqualToAnchor(containerView.superview?.topAnchor, constant: 25)
containerView.leftAnchor.constraintEqualToAnchor(containerView.superview?.leftAnchor, constant: 25)
containerView.widthAnchor.constraintEqualToAnchor(containerView.superview?.widthAnchor, constant: -50)
containerView.heightAnchor.constraintEqualToConstant(100)
let topConstraint = containerView.constraints[0]
topConstraint.identifier = "ContainerViewTop"
containerView.layoutIfNeeded()
return containerView
}
}
仅供参考:
我没有使用默认的 Interface Builder,我已经在 TestCell.swift[=37 中编写了所有与 GUI 相关的代码=] 文件.
对可能导致此问题的原因有任何想法吗?
谢谢!
我敢打赌问题来自:
let topConstraint = containerView.constraints[0]
检查约束大小可以很容易地证明...:)
您在创建约束时忘记调用 active 方法,这不会将它们添加到约束列表中
即:
containerView.heightAnchor.constraintEqualToConstant(100).active = true
我在尝试让 UITableView 正常运行时遇到了一些小问题。这是错误的样子:
* Terminating app due to uncaught exception 'NSRangeException', reason: '* -[__NSArray0 objectAtIndex:]: index 0 beyond bounds for empty NSArray'
我已将问题缩小到这个特定的代码片段:(第 2 行)
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(String(TestCell), forIndexPath: indexPath)
return cell
}
完整 Swift 文件:
class ViewController: UITableViewController {
let closeHeight: CGFloat = 91
let openHeight: CGFloat = 166
var itemHeight = [CGFloat](count: 4, repeatedValue: 91.0)
override func viewDidLoad() {
super.viewDidLoad()
tableView.registerClass(TestCell.self, forCellReuseIdentifier: String(TestCell))
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return itemHeight.count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(String(TestCell), forIndexPath: indexPath)
return cell
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return itemHeight[indexPath.row]
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
let cell = tableView.cellForRowAtIndexPath(indexPath) as! FoldingCell
var duration = 0.0
if itemHeight[indexPath.row] == closeHeight { // open cell
itemHeight[indexPath.row] = openHeight
cell.selectedAnimation(true, animated: true, completion: nil)
duration = 0.5
} else {// close cell
itemHeight[indexPath.row] = closeHeight
cell.selectedAnimation(false, animated: true, completion: nil)
duration = 1.1
}
UIView.animateWithDuration(duration, delay: 0, options: .CurveEaseOut, animations: { () -> Void in
tableView.beginUpdates()
tableView.endUpdates()
}, completion: nil)
}
}
编辑 1:
class TestCell: FoldingCell {
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
containerView = createContainerView()
foregroundView = createForegroundView()
// super class method configure views
commonInit()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func animationDuration(itemIndex: NSInteger, type: AnimationType) -> NSTimeInterval {
// durations count equal it itemCount
let durations = [0.33, 0.26, 0.26] // timing animation for each view
return durations[itemIndex]
}
}
extension TestCell{
func createForegroundView() -> RotatedView{
let foregroundView = RotatedView(frame: .zero)
foregroundView.backgroundColor = UIColor.blackColor()
foregroundView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(foregroundView)
foregroundView.topAnchor.constraintEqualToAnchor(foregroundView.superview?.topAnchor, constant: 25)
foregroundView.leftAnchor.constraintEqualToAnchor(foregroundView.superview?.leftAnchor, constant: 25)
foregroundView.widthAnchor.constraintEqualToAnchor(foregroundView.superview?.widthAnchor, constant: -50)
foregroundView.heightAnchor.constraintEqualToConstant(100)
let topConstraint = foregroundView.constraints[0]
topConstraint.identifier = "ForegroundViewTop"
foregroundView.layoutIfNeeded()
return foregroundView
}
func createContainerView() -> UIView {
let containerView = UIView(frame: .zero)
containerView.backgroundColor = UIColor.grayColor()
containerView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(containerView)
containerView.topAnchor.constraintEqualToAnchor(containerView.superview?.topAnchor, constant: 25)
containerView.leftAnchor.constraintEqualToAnchor(containerView.superview?.leftAnchor, constant: 25)
containerView.widthAnchor.constraintEqualToAnchor(containerView.superview?.widthAnchor, constant: -50)
containerView.heightAnchor.constraintEqualToConstant(100)
let topConstraint = containerView.constraints[0]
topConstraint.identifier = "ContainerViewTop"
containerView.layoutIfNeeded()
return containerView
}
}
仅供参考:
我没有使用默认的 Interface Builder,我已经在 TestCell.swift[=37 中编写了所有与 GUI 相关的代码=] 文件.
对可能导致此问题的原因有任何想法吗?
谢谢!
我敢打赌问题来自:
let topConstraint = containerView.constraints[0]
检查约束大小可以很容易地证明...:)
您在创建约束时忘记调用 active 方法,这不会将它们添加到约束列表中
即:
containerView.heightAnchor.constraintEqualToConstant(100).active = true