致命错误:追加数组时数组索引超出范围

Posted

技术标签:

【中文标题】致命错误:追加数组时数组索引超出范围【英文标题】:Fatal error: Array index out of range when appending array 【发布时间】:2019-05-28 21:08:22 【问题描述】:

我目前有一个要附加选项的数组。它们显示在一个包含 3 个部分的表格中。前 2 部分各有 1 行,但第三部分的行数可变,具体取决于附加到数组的内容。我基本上采用了初始数组的第三个组件(allAlbums[0].markscheme)并将其分解以在数组中创建多个新项目。

但是,当我尝试对此进行模拟时,我在 'cell.textData?.text = section[indexPath.row] as! 上得到了一个致命数组! String',我不知道为什么?

final class CaseViewController: UIViewController, UITableViewDelegate, UITableViewDataSource 

@IBOutlet var titleText: UILabel!
@IBOutlet var tableView: UITableView!

private var allAlbums = [Case]()

let kHeaderSectionTag: Int = 6900;

var expandedSectionHeaderNumber: Int = -1
var expandedSectionHeader: UITableViewHeaderFooterView!
var sectionItems: Array<Any> = []
var sectionNames: Array<Any> = []
var markschemeRows: Array<Any> = []

override func viewDidLoad() 
    super.viewDidLoad()

    allAlbums = LibraryAPI.shared.getCases()

    // Filter the main array to match a single case
    allAlbums = allAlbums.filter  $0.title == title

    // Get data to fill in to table
    sectionNames = [ "Trainee Information", "Patient Information", "Examiner Information" ];
    sectionItems = [ [allAlbums[0].doctor], [allAlbums[0].patient], [allAlbums[0].markscheme]]

    let text = allAlbums[0].markscheme
    markschemeRows = text.components(separatedBy: " ")

    sectionItems.append(contentsOf: markschemeRows)

    // Autoresize rows
    tableView.rowHeight = UITableView.automaticDimension
    tableView.estimatedRowHeight = 500

    // Remove excess row seperators
    tableView.tableFooterView = UIView()
    tableView.separatorColor = UIColor.clear

    titleText.text = title




func numberOfSections(in tableView: UITableView) -> Int 
    return 3


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    if (self.expandedSectionHeaderNumber == section) 

        // Header section
        let header = self.sectionNames[section] as! String

        // If markscheme, create the markscheme format
        if (header == "Examiner Information")
        
            print(self.markschemeRows.count)
            return self.markschemeRows.count
        
        else
        
            let arrayOfItems = self.sectionItems[section] as! NSArray
            print(arrayOfItems.count)
            return arrayOfItems.count
        


     else 
        return 0;
    



func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? 
    if (self.sectionNames.count != 0) 
        return self.sectionNames[section] as? String
    
    return ""


func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat 
    return 44.0;


func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat
    return 0;


func tableView(_ tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) 
    //recast your view as a UITableViewHeaderFooterView
    let header: UITableViewHeaderFooterView = view as! UITableViewHeaderFooterView
    header.contentView.backgroundColor = UIColor.darkGray
    header.textLabel?.textColor = UIColor.white

    if let viewWithTag = self.view.viewWithTag(kHeaderSectionTag + section) 
        viewWithTag.removeFromSuperview()
    
    let headerFrame = self.view.frame.size
    let theImageView = UIImageView(frame: CGRect(x: headerFrame.width - 32, y: 13, width: 18, height: 18));
    theImageView.image = UIImage(named: "Chevron-Dn-Wht")
    theImageView.tag = kHeaderSectionTag + section
    header.addSubview(theImageView)

    // make headers touchable
    header.tag = section
    let headerTapGesture = UITapGestureRecognizer()
    headerTapGesture.addTarget(self, action: #selector(CaseViewController.sectionHeaderWasTouched(_:)))
    header.addGestureRecognizer(headerTapGesture)


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! CustomTableCell
    let section = self.sectionItems[indexPath.section] as! NSArray

    cell.textLabel?.textColor = UIColor.black

    cell.textData?.text = section[indexPath.row] as! String

    return cell


func tableView(_ tableView: UITableView, didDeselectRowAt indexPath: IndexPath) 
    tableView.deselectRow(at: indexPath, animated: true)


// MARK: - Expand / Collapse Methods

@objc func sectionHeaderWasTouched(_ sender: UITapGestureRecognizer) 
    let headerView = sender.view as! UITableViewHeaderFooterView
    let section    = headerView.tag
    let eImageView = headerView.viewWithTag(kHeaderSectionTag + section) as? UIImageView

    if (self.expandedSectionHeaderNumber == -1) 
        self.expandedSectionHeaderNumber = section
        tableViewExpandSection(section, imageView: eImageView!)
     else 
        if (self.expandedSectionHeaderNumber == section) 
            tableViewCollapeSection(section, imageView: eImageView!)
         else 
            let cImageView = self.view.viewWithTag(kHeaderSectionTag + self.expandedSectionHeaderNumber) as? UIImageView
            tableViewCollapeSection(self.expandedSectionHeaderNumber, imageView: cImageView!)
            tableViewExpandSection(section, imageView: eImageView!)
        
    


func tableViewCollapeSection(_ section: Int, imageView: UIImageView) 
    let sectionData = self.sectionItems[section] as! NSArray

    self.expandedSectionHeaderNumber = -1;
    if (sectionData.count == 0) 
        return;
     else 
        UIView.animate(withDuration: 0.4, animations: 
            imageView.transform = CGAffineTransform(rotationAngle: (0.0 * CGFloat(Double.pi)) / 180.0)
        )
        var indexesPath = [IndexPath]()
        for i in 0 ..< sectionData.count 
            let index = IndexPath(row: i, section: section)
            indexesPath.append(index)
        
        self.tableView!.beginUpdates()
        self.tableView!.deleteRows(at: indexesPath, with: UITableView.RowAnimation.fade)
        self.tableView!.endUpdates()
    


func tableViewExpandSection(_ section: Int, imageView: UIImageView) 
    let sectionData = self.sectionItems[section] as! NSArray

    if (sectionData.count == 0) 
        self.expandedSectionHeaderNumber = -1;
        return;
     else 
        UIView.animate(withDuration: 0.4, animations: 
            imageView.transform = CGAffineTransform(rotationAngle: (180.0 * CGFloat(Double.pi)) / 180.0)
        )
        var indexesPath = [IndexPath]()

        // Header section
        let header = self.sectionNames[section] as! String

        // If markscheme, create the markscheme format
        if (header == "Examiner Information")
        
            for i in 0 ..< markschemeRows.count 
                let index = IndexPath(row: i, section: section)
                indexesPath.append(index)
            
        
        else
        
            for i in 0 ..< sectionData.count 
                let index = IndexPath(row: i, section: section)
                indexesPath.append(index)
            
        
        self.expandedSectionHeaderNumber = section
        self.tableView!.beginUpdates()
        self.tableView!.insertRows(at: indexesPath, with: UITableView.RowAnimation.fade)
        self.tableView!.endUpdates()
    

【问题讨论】:

【参考方案1】:

错误很明显。

numberOfRows 中,您为第 2 部分返回 markschemeRows.count,这是该行中分隔项目的数量

markschemeRows = text.components(separatedBy: " ")

那么你还必须从markschemeRows而不是section[indexPath.row]中的cellForRow获取项目

var markschemeRows = [String]()

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCell(withIdentifier: "tableCell", for: indexPath) as! CustomTableCell
    let section = self.sectionItems[indexPath.section] as! NSArray

    cell.textLabel?.textColor = UIColor.black
    if indexPath.section == 2 
        cell.textData?.text = markschemeRows[indexPath.row]
     else 
        cell.textData?.text = section[indexPath.row] as! String
    

    return cell

您的代码相当繁琐。例如sectionNamesmarkschemeRows 显然是[String]。为什么将数组声明为[Any]?这是斯威夫特。 注意类型。并且根本不要在 Swift 中使用像 NSArray 这样的 Foundation 集合类型。再次注意类型

【讨论】:

太棒了!谢谢!抱歉,我只是在学习,所以我正在整理代码 - 感谢您指出这一点:)

以上是关于致命错误:追加数组时数组索引超出范围的主要内容,如果未能解决你的问题,请参考以下文章

Swift 致命错误:数组索引超出范围

致命错误:数组索引超出范围。刷新时迅速

SwiftUI - 致命错误:从数组中删除元素时索引超出范围

致命错误:在Swift中访问10个元素的数组时,数组索引超出范围

线程 1:致命错误:索引超出范围。没有快速从数组中获取值,控制台显示它们不是空数组

从数组中删除 - 致命错误:索引超出范围 - SwiftUI 绑定