单元格点击上的“在无效索引路径上请求rect”异常

时间:2017-01-11 10:32:23

标签: ios swift uitableview indexpath

我正在使用自动填充功能在搜索栏上工作。有时在自动填充TableView中点击单元格时会出现此错误:

  

***断言失败 - [UITableViewRowData rectForRow:inSection:heightCanBeGuessed:],   /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3505.16/UITableViewRowData.m:1849

     

***因未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'请求为   索引路径无效({length = 2,path = 0 -   3})'

如果我对此行发表评论searchBar.text = cell.textLabel!.text应用不会崩溃。

这是完整的功能代码:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
    {
        let cell: UITableViewCell = tableView.cellForRow(at: indexPath)!
        address = cell.textLabel!.text!
        searchBar.text = cell.textLabel!.text
    }

我该如何解决?

UPD:searchBar.text = cell.textLabel!.text之后看起来崩溃了 我添加了print(searchBar.text!)并将正确的值打印到控制台

UPD2:仅当我在搜索栏中输入内容时,应用程序崩溃,然后点击屏幕上的某个位置以关闭键盘,然后点击其中一个自动填充单元格。

班级代码:

import UIKit
import Alamofire
import SwiftyJSON

class StreetSelectViewController: UIViewController, UITableViewDataSource, UITableViewDelegate, UISearchBarDelegate, UINavigationControllerDelegate
{
    var data: [String] = ["Нет данных"]
    var filtered: [String] = []
    var searchActive : Bool = false

    @IBOutlet weak var cityNameLabel: UILabel!
    @IBOutlet weak var searchBar: UISearchBar!
    @IBOutlet weak var tableView: UITableView!
    @IBOutlet weak var topSpaceConstraint: NSLayoutConstraint!
    @IBOutlet var gradientBackground: GradientView!

    let segueIdentifier = "ShowStreetSelectSegue"

    //background gradient
    override func viewDidLayoutSubviews()
    {
        self.gradientBackground.create()
    }

    override func viewDidLoad()
    {
        super.viewDidLoad()

        //side menu panGestureRecognizer
        if self.revealViewController() != nil
        {
            self.view.addGestureRecognizer(self.revealViewController().panGestureRecognizer())
        }

        tableView.delegate = self
        tableView.dataSource = self
        searchBar.delegate = self
        tableView.tableFooterView = UIView()
        navigationController?.delegate = self

        //search bar settings
        let barImage = UIImage()
        searchBar.setBackgroundImage(barImage, for: .any, barMetrics: .default)
        searchBar.scopeBarBackgroundImage = barImage
        searchBar.tintColor = UIColor.lightGray
        searchBar.setValue("Отмена", forKey:"_cancelButtonText")
        searchBar.showsCancelButton = false

        topSpaceConstraint.constant = self.navigationController!.navigationBar.frame.height + 8

        //network
        let queue = DispatchQueue(label: "com.admin.response-queue", qos: .utility, attributes: [.concurrent])
        URLCache.shared.removeAllCachedResponses()
        Alamofire.request("").validate()
            .responseJSON(
                queue: queue,
                completionHandler: { response in
                    if let JSON = response.result.value
                    {
                        self.data.removeAll()
                        let json = SwiftyJSON.JSON(JSON)
                        print("JSON: \(json)")
                        for (_, object) in json
                        {
                            self.data.append(object.stringValue)
                            print(self.data)
                        }
                    }
                    DispatchQueue.main.async {
                        self.tableView.reloadData()
                    }
            }
        )
    }

    override func didReceiveMemoryWarning() { super.didReceiveMemoryWarning() }

    override func viewWillAppear(_ animated: Bool)
    {
        cityNameLabel.text = cityName
    }

    //MARK: - search bar settings
    func searchBarTextDidBeginEditing(_ searchBar: UISearchBar)
    {
        searchActive = true;
        self.navigationController?.isNavigationBarHidden = true
        topSpaceConstraint.constant = 8
    }

    func searchBarTextDidEndEditing(_ searchBar: UISearchBar)
    {
        searchActive = false;
        self.navigationController?.isNavigationBarHidden = false
    }

    func searchBarCancelButtonClicked(_ searchBar: UISearchBar)
    {
        searchActive = false;
        filtered = data
        tableView.isHidden = false
        tableView.reloadData()
        topSpaceConstraint.constant = 8
    }

    func searchBarSearchButtonClicked(_ searchBar: UISearchBar)
    {    
        if !searchActive
        {
            searchActive = true
            tableView.reloadData()
        }

        self.searchBar.resignFirstResponder()
        address = searchBar.text!
        performSegue(withIdentifier: "ShowSearchResultsSeque", sender: Any?.self)
    }

    func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String)
    {
        filtered = data.filter({ (text) -> Bool in
            let tmp: NSString = text as NSString
            let range = tmp.range(of: searchText, options: NSString.CompareOptions.caseInsensitive)
            return range.location != NSNotFound
        })
        if(filtered.count == 0)
        {
            searchActive = false;
        }
        else
        {
            searchActive = true;
        }

        if searchText.characters.count != 0
        {
            tableView.isHidden = true
        }
        else
        {
            tableView.isHidden = false
        }

        tableView.reloadData()
        topSpaceConstraint.constant = 8
    }

    //MARK: - tableview settings

    func numberOfSections(in tableView: UITableView) -> Int
    {
        return 1
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
    {
        if searchActive
        {
            if filtered.count == 0
            {
                return data.count
            }
            else
            {
                return filtered.count
            }
        }
        else
        {
            return data.count
        }
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
    {
        let cell = self.tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
        if searchActive
        {
            if filtered.count == 0
            {
                cell.textLabel?.text = data.sorted()[indexPath.row]
            }
            else
            {
                cell.textLabel?.text = filtered.sorted()[indexPath.row]
            }
        }
        else
        {
            cell.textLabel?.text = data.sorted()[indexPath.row]
        }
        return cell
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
    {
        let cell: UITableViewCell = self.tableView.cellForRow(at: indexPath)!
        address = cell.textLabel!.text!
        self.searchBar.text = cell.textLabel!.text
        print(searchBar.text!)          
    }

    func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
    {
        cell.backgroundColor = UIColor.clear
        //text color
        cell.textLabel!.textColor = UIColor.white;
        //cell selection color
        let bgColorView = UIView()
        bgColorView.backgroundColor = UIColor.black.withAlphaComponent(0.3)
        cell.selectedBackgroundView = bgColorView
        tableView.backgroundColor = UIColor.clear
    }                 
}

1 个答案:

答案 0 :(得分:1)

为什么您在self.tableView.cellForRow方法中使用didSelectRowAt,您可以在didSelectRowAt方法中使用已过滤的数据源,该方法已在cellForRowAt方法中使用。您可以执行以下操作来实现您的功能。

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath)
    {
        if searchActive
        {
            if filtered.count == 0
            {
                address = data.sorted()[indexPath.row]
            }
            else
            {
                address = filtered.sorted()[indexPath.row]
            }
            self.searchBar.text = address
        }         
    }