Ошибка при выборе двух файлов из выпадающего списка для отображения в UITableView в swift

#ios #swift #xcode #uitableview

#iOS #swift #xcode #uitableview

Вопрос:

У меня есть два tableview в моем viewcontroller и два выпадающих меню, из которых я выбираю csv-файлы для каждого tableview для отображения его содержимого. Я получаю сообщение об ошибке недоступности индекса. После отладки я узнал, имеют ли оба файла одинаковое количество строк, он не показывает никаких ошибок. Как я могу устранить эту ошибку, потому что у меня много файлов csv, которые могут содержать разное количество данных.

 import UIKit
import DropDown
class CompareFilesViewController: UIViewController,UITableViewDelegate, UITableViewDataSource {



@IBOutlet weak var DropDownView: UIView!
@IBOutlet weak var DropDownView2: UIView!
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var tableView2: UITableView!
@IBOutlet weak var selectedFile_lbl: UILabel!
@IBOutlet weak var selectedFile_lbl2: UILabel!

var  filesDropDown = DropDown()
var filesDropDown2 = DropDown()

var files1 = [String]()
var files2 = [String]()

var files1Data = [String]()
var files2Data = [String]()

var refreshControl: UIRefreshControl?

var dropDownFlag = false
var dropDownFlag1 = false

var filename: String?
var filename1: String?

override func viewDidLoad() {
    super.viewDidLoad()
    
   var files = [String]()
    files1Data.append("Select Files from drop down")
    files2Data.append("Select Files from drop down")
    // Do any additional setup after loading the view.
  let fm = FileManager.default
         let path = getDocumentsDirectory()
         
         do{
             
             let items = try fm.contentsOfDirectory(at: path, includingPropertiesForKeys: nil)
             let onlyFileNames = items.filter{ !$0.hasDirectoryPath }
             let onlyFileNamesStr = onlyFileNames.map { $0.lastPathComponent }
             files.append(contentsOf: onlyFileNamesStr)
               //getting different file names 
               for index in 0..<files.count{
                
                if files[0].components(separatedBy: "_")[0] == files[index].components(separatedBy: "_")[0]{
                  print(true)
                    files1.insert(files[index], at: 0)
                }
                else{
                    print(false)
                        files2.insert(files[index], at: 0)
                }
                
                
            }
             print("file names(onlyFileNamesStr)")
            
            
         }
         catch
         {
             print(error)
             
         }

    setDropDown1()
    setDropDown2()
    
    tableView.delegate = self
    tableView.dataSource = self
    tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
    
    tableView2.delegate = self
    tableView2.dataSource = self
    tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell2")
    

}



@IBAction func DropDownViewTapped(_ sender: Any) {
          
    filesDropDown.show()
}

@IBAction func DropDownView2Tapped(_ sender: Any) {
      
    filesDropDown2.show()
}

@IBAction func compareFiles(_ sender: Any) {
   
    files2Data.removeAll()
    files1Data.removeAll()
    files2Data.insert(contentsOf: self.getSelectedFileContent(fileName: filename1!), at: 0)
    files1Data.insert(contentsOf: self.getSelectedFileContent(fileName: filename!), at: 0)
    
    tableView.reloadData()
    tableView2.reloadData()    
}
//for right dropdown
func setDropDown1() {

    
  filesDropDown.textFont = UIFont.systemFont(ofSize: 10)
    filesDropDown.textColor = .blue
    filesDropDown.dataSource = files1
     filesDropDown.anchorView = DropDownView2
    filesDropDown.selectionAction = { index, title in
                     
        self.dropDownFlag = true
                     
                     print("index: (index), title: (title)")
        self.filename = title
        self.selectedFile_lbl2.text = self.filename
                        
        // self.files1Data.insert(contentsOf: self.getSelectedFileContent(fileName: title), at: 0)
        //self.tableView2.reloadData()
                 }
   
}
//for left drop down
func setDropDown2(){
    
    filesDropDown2.textFont = UIFont.systemFont(ofSize: 10)

        filesDropDown2.dataSource = files2
        filesDropDown2.anchorView = DropDownView
    
        filesDropDown2.selectionAction = { index, title in
                          
            self.dropDownFlag1 = true
                          
                          print("index: (index), title: (title)")
            self.filename1 = title
            self.selectedFile_lbl.text =  self.filename1
 
                      }
  
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
      
    var count: Int?
    
    if tableView == self.tableView{
        count = files1Data.count
        print(count as Any)
    }
    if tableView == self.tableView2{
        count = files2Data.count
        print(count as Any)
    }
    print(count as Any)
    return count!
  }
  
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
var cell:UITableViewCell?

    if tableView == self.tableView{
            cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
            cell!.textLabel?.text = files2Data[indexPath.row]//error: index out of range
            cell!.textLabel!.numberOfLines = 0
            // cell!.textLabel?.adjustsFontSizeToFitWidth = true
            cell!.textLabel?.font = UIFont(name: "Arial", size: 10.0)
        }
        if tableView == self.tableView2{
            cell = tableView.dequeueReusableCell(withIdentifier: "Cell2", for: indexPath)
            cell!.textLabel?.text = files1Data[indexPath.row]//error: index out of range
            cell!.textLabel!.numberOfLines = 0
            // cell!.textLabel?.adjustsFontSizeToFitWidth = true
            cell!.textLabel?.font = UIFont(name: "Arial", size: 10.0)
        }

return cell!
}

func getSelectedFileContent(fileName: String) -> [String] {
    var contentsArray = [String]()
    let fm = FileManager.default
    let destURL = getDocumentsDirectory().appendingPathComponent(fileName)
    do {
        if fm.fileExists(atPath: destURL.path) {
                         let contents = try String(contentsOf: destURL)
            contentsArray = contents.components(separatedBy: "n")
            print(contents)
        }
    } catch {
        print("File copy failed.")
    }

 return contentsArray
}

}
  

Я пытался добавить refreshcontroll, но это не работает.
Для выпадающего списка я использовал библиотеку AssistoLab https://github.com/AssistoLab/DropDown.git

Чего я действительно хочу, так это выбрать csv-файлы и отобразить их в tableviews для сравнения при нажатии кнопки
. есть ли лучшее решение, которое я могу использовать? введите описание изображения здесь

Ответ №1:

Вы можете изменить свое условие, как показано ниже :

     if tableView == self.tableView {
    
    if files2Data.count <= indexPath.row {
        // Your code
    }else{
       return UITableViewCell()
    }
  }
  

Та же логика для другой таблицы.

Комментарии:

1. это дает мне эту ошибку Фатальная ошибка: неожиданно найдено nil при развертывании необязательного значения:

2. в какой строке вы получаете эту проблему и какое необязательное значение?

3. при возврате ячейки в функции cellForRowAt

4. хорошо.. это потому, что вы возвращаете ячейку! Вместо этого вы можете вернуть ячейку из операторов if, как показано ниже, если files2Data.count <= indexPath.row { // Ваш код возвращает ячейку }else{ return UITableViewCell() }

5. о, хорошо, я делал по-другому.

Ответ №2:

Я не знаю почему, но после рефакторинга моего кода он работает так, как я хотел. я только что добавил две кнопки для отображения обоих файлов после выбора из выпадающего меню.

 import UIKit
import DropDown
class DemoViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {


@IBOutlet weak var topDropDownView: UIView!
@IBOutlet weak var bottomDropDownView: UIView!

@IBOutlet weak var selectFile_lbl1: UILabel!
@IBOutlet weak var selectFile_lbl2: UILabel!

@IBOutlet weak var tableView1: UITableView!
@IBOutlet weak var tableView2: UITableView!

var data1 = [String]()
var data2 = [String]()

var topDropDown = DropDown()
var bottomDropDown = DropDown()

var files1 = [String]()
var files2 = [String]()

var filename1 = ""
var filename2 = ""

override func viewDidLoad() {
    super.viewDidLoad()
    
    getFileNames()
    
    setDropDown1()
    setDropDown2()
    
    tableView1.delegate = self
    tableView2.delegate = self
    tableView1.dataSource = self
    tableView2.dataSource = self
    
     tableView1.register(UITableViewCell.self, forCellReuseIdentifier: "cell1")
     tableView2.register(UITableViewCell.self, forCellReuseIdentifier: "cell2")

}


/*
// MARK: - Navigation

// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    // Get the new view controller using segue.destination.
    // Pass the selected object to the new view controller.
}
*/
@IBAction func button1(_ sender: Any) {
    data1.removeAll()
    data1.append(contentsOf: getSelectedFileContent(fileName: filename1))
    tableView1.reloadData()
    
   }
@IBAction func button2(_ sender: Any) {
    data2.removeAll()
    data2.append(contentsOf: getSelectedFileContent(fileName: filename2))
           tableView2.reloadData()
}

 func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var count: Int?

      if tableView == self.tableView1{
          count = data1.count
        print(count as Any)
      }
      if tableView == self.tableView2{
          count = data2.count
        print(count as Any)
      }
print(count as Any)
      return count!
 }
 
 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
     var cell:UITableViewCell?
     
         if tableView == self.tableView1{
                 cell = tableView.dequeueReusableCell(withIdentifier: "cell1", for: indexPath)
                 cell!.textLabel?.text = data1[indexPath.row]
                 cell!.textLabel!.numberOfLines = 0
                 // cell!.textLabel?.adjustsFontSizeToFitWidth = true
                 cell!.textLabel?.font = UIFont(name: "Arial", size: 10.0)
             }
             if tableView == self.tableView2{
                 cell = tableView.dequeueReusableCell(withIdentifier: "cell2", for: indexPath)
                 cell!.textLabel?.text = data2[indexPath.row]
                 cell!.textLabel!.numberOfLines = 0
                 // cell!.textLabel?.adjustsFontSizeToFitWidth = true
                 cell!.textLabel?.font = UIFont(name: "Arial", size: 10.0)
             }
     
     return cell!
 }

 
    func getSelectedFileContent(fileName: String) -> [String] {
        var contentsArray = [String]()
        let fm = FileManager.default
        let destURL = getDocumentsDirectory().appendingPathComponent(fileName)
        do {
            if fm.fileExists(atPath: destURL.path) {
                             let contents = try String(contentsOf: destURL)
                contentsArray = contents.components(separatedBy: "n")
                print(contents)
            }
        } catch {
            print("File copy failed.")
        }

     return contentsArray
    }


@IBAction func topDropDownView_tapped(_ sender: Any) {
    topDropDown.show()
}

@IBAction func bottomDropDownView_tapped(_ sender: Any) {
    bottomDropDown.show()
}

func getFileNames(){
    
    var files = [String]()
    let fm = FileManager.default
    let path = getDocumentsDirectory()
    
    do{
        let items = try fm.contentsOfDirectory(at: path, includingPropertiesForKeys: nil)
        let onlyFileNames = items.filter{ !$0.hasDirectoryPath }
        let onlyFileNamesStr = onlyFileNames.map { $0.lastPathComponent }
        
        files.append(contentsOf: onlyFileNamesStr)
        
        for index in 0..<files.count{
            
            if files[0].components(separatedBy: "_")[0] == files[index].components(separatedBy: "_")[0]{
                print(true)
                files1.insert(files[index], at: 0)
            }
            else{
                print(false)
                files2.insert(files[index], at: 0)
            }
        }
        print("file names(onlyFileNamesStr)")
    }
    catch
    {
        print(error)
        
    }
}

//for right dropdown
func setDropDown1() {

    
  topDropDown.textFont = UIFont.systemFont(ofSize: 10)
    topDropDown.textColor = .blue
    topDropDown.dataSource = files1
     topDropDown.anchorView = topDropDownView
    topDropDown.selectionAction = { index, title in
                        
        print("index: (index), title: (title)")
        self.filename1 = title
        self.selectFile_lbl1.text = self.filename1
                        
        // self.files1Data.insert(contentsOf: self.getSelectedFileContent(fileName: title), at: 0)
        //self.tableView2.reloadData()
                 }
   
}
//for left drop down
func setDropDown2(){
    
    bottomDropDown.textFont = UIFont.systemFont(ofSize: 10)

        bottomDropDown.dataSource = files2
        bottomDropDown.anchorView = bottomDropDownView
    
        bottomDropDown.selectionAction = { index, title in
                          
            
                          
                          print("index: (index), title: (title)")
            self.filename2 = title
            self.selectFile_lbl2.text =  self.filename2
            //self.files2Data.insert(contentsOf: self.getSelectedFileContent(fileName: title), at: 0)
           // self.tableView2.reloadData()
                      }
  
}
  

}