#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()
}
}
}