无法将文本文件读取为所需的数组格式

时间:2019-01-03 03:59:03

标签: swift uitableview parsing uiviewcontroller uisearchcontroller

我正在压缩一个我正在处理的应用程序,该应用程序涉及一个包含许多UIViewControllersUITableViews的大型目录。

我的计划是重写将使用可重复使用的UIViewControllerUITableView的应用程序,该应用程序将在运行时/运行后根据需要从txt文件加载数据。 txt文件将在运行时/运行后读取,而不必先构建所有swift文件。

当前,每次对项目进行更改时,我的应用程序都需要花费几分钟的时间来构建/编译。因此,我希望通过根据需要读取和解析txt文件,能够在几秒钟内构建应用程序。

下面是我尝试使用下面提供的示例文本文件(candyTextFile.txt)读取并生成必要的“糖果”数组。 请参见类MasterViewController中的注释行,以获取错误消息以及我试图将candies数组输出为的代码。

注意,我已将文本文件中的行缩短为三行。我的最终应用程序将包含许多类似的文本文件,每个文本文件会扩展数百行。

我对Swift还是比较陌生,因此如果我在这里缺少一些简单的东西,或者我使用/不使用适当的术语,我深表歉意。

我相信术语CandySearch仅来自项目名称(请参见here)。我不确定为什么在candies数组中输出它。另外,我现在确实看到将我当前的myArray建立为一个类。如何将其转换为数组?

这是我的MasterViewController.swift中相关的代码,

class MasterViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    var candies = [myArray]()
    var evenIndicies = [String]()
    var oddIndicies = [String]()

    override func viewDidLoad() {
        super.viewDidLoad()

        setUpArray()
    }

    private func setUpArray() {
        if let filepath = Bundle.main.path(forResource: "candyTextFile", ofType: "txt") {
            do {
                // let contents = try String(contentsOfFile: "candyTextFile", encoding: String.Encoding.utf8)
                let contents = try String(contentsOfFile: filepath)
                let lines_separatedBy_n : [String] = contents.components(separatedBy: "\n")
                let string = lines_separatedBy_n.map { String($0) }.joined(separator: ", ")
                print("string: \(string)")
                let lines_separatedBy_comma : [String] = string.components(separatedBy: ", ")
                print("lines_separatedBy_comma: \(lines_separatedBy_comma)")

                for (index, element) in lines_separatedBy_comma.enumerated() {
                    if index % 2 == 0 {
                        evenIndicies.append(element)
                        print("evenIndicies: \(evenIndicies)")

                    } else {
                        oddIndicies.append(element)
                        print("oddIndicies: \(oddIndicies)")
                    }
                }
                evenIndicies.remove(at: evenIndicies.count - 1) // the -1 removes the nil element, "", in the array. For some reason, there is a fourth element, "", in the evenIndicies array. Therefore, I remove it by subtracting one index so I get the three indexes. My in project txt file is four lines long where the fourth line is empty. I think this is why it is showing up "" for the fourth index.
                print("evenIndicies outside for-loop: \(evenIndicies)")
                print("oddIndicies outside for-loop: \(oddIndicies)")
                candies = [myArray(category: evenIndicies, name: oddIndicies)]  // 

                print("candies: \(candies)") 
           // This prints as the following:
           // candies: [CandySearch.myArray]

           // HOWEVER, I am trying to get it to print as: 
           // [CandySearch.myArray(category: "Chocolate", name: "Chocolate Bar"), CandySearch.myArray(category: "Chocolate", name: "Chocolate Cookie"), CandySearch.myArray(category: "Hard", name: "Lollipop")]




            } catch let error as NSError {
                print(error.localizedDescription)
            }
        }
    }
}

class myArray {
    let category: [String]
    let name: [String]
    init(category: [String], name: [String]) {
        self.category = category
        self.name = name
    }
}

在我的文本文件candyTextFile.txt中,

Chocolate, Chocolate Bar
Chocolate, Chocolate Cookie
Hard, Lollipop

1 个答案:

答案 0 :(得分:1)

假设您要从文本文件中获取信息并最终获得一系列糖果产品,我将对此进行介绍。目前,您的UnsupportedOperationException类看上去有点像科学怪人一样。它在该类的单个实例内的两个单独的数组中包含所有类别和名称。然后,将其放入名为myArray的数组中。除非我误解了您的要求,否则所有这些看起来都是死路一条。 (也许我是。)但是假设我至少是正确的一半...

您想要一系列糖果,所以让我们创建一个新类来容纳一个糖果。

candies

这与您已经拥有的类似,但是当实例化class Candy { let category: String! let name: String! init(category: String, name: String) { self.category = category self.name = name } } 的实例时,它将保存单个糖果的详细信息。注释类名称按惯例以大写字母开头。

您最终希望得到一系列糖果,所以让我们更改Candy数组的定义。

candies

剩下的就是更改您的var candies: [Candy] = [] 循环以在每个循环中提取一个糖果的数据(类别和名称),创建一个新的for in实例并填充它,然后再将其添加到{{1 }}。

Candy

您没有在代码中进行任何检查来处理文本文件中的任何错误/格式错误,因此,我假定您可以肯定它由无松散的数据对组成,等等。看到您出于某种原因删除了candies的最后一个元素。我不知道为什么,所以我没有处理。

现在,您的for (index, element) in lines_separatedBy_comma.enumerated() { var newCategory = "" var newName = "" if index % 2 == 0 { newCategory = element } else { newName = element } let newCandy = Candy(category: newCategory, name: newName) candies.append(newCandy) } 数组应该包含一堆evenIndices对象,因此要将它们列出到控制台中,您可以执行以下操作。

candies

让我知道我是否仍然缺少商标。

编辑************************************************** **********编辑

我看了您链接的RW教程。

本教程对Candy元素使用了for candy in candies { print("category: \(String(describing: candy.category)), name: \(String(describing: candy.name))") } ,而您(和我)已经使用了一个类。我猜您仍在学习Swift的值和引用类型,因此不会在这里进一步混淆。在这种情况下,只需说一个struct可能会更好。 Candy也会以不同的方式处理它们,并且似乎能够在结构内部查找值,而除非您显式提取属性(如我的struct打印语句,否则它只是为您提供了一个类列表)已经看过了。

我还对逻辑进行了排序(这很丑陋,您不应该这样处理),这样您至少可以看到它确实有效(遵循某种方式)。整个print方法:

for in

当我使用时:

setupArray

输出为:

private func setupArray() {
     if let filepath = Bundle.main.path(forResource: "candyTextFile", ofType: "txt") {
         do {
             let contents = try String(contentsOfFile: filepath)
             let lines_separatedBy_n : [String] = contents.components(separatedBy: "\n")
             let string = lines_separatedBy_n.map { String($0) }.joined(separator: ", ")
             var lines_separatedBy_comma : [String] = string.components(separatedBy: ", ")

             // I've put this in to remove the last bit of the file that was causing the count to be one too high.
             // I'm guessing that's why you had something similar previously?
             lines_separatedBy_comma.removeLast()

             for (index, element) in lines_separatedBy_comma.enumerated() {
                 if index % 2 == 0 {
                     let newCategory = element
                     let newName = lines_separatedBy_comma[index + 1]
                     let newCandy = Candy(category: newCategory, name: newName)
                     candies.append(newCandy)
                 }
             }
             for candy in candies {
                 print("category: \(candy.category!), name: \(candy.name!)")
             }
             print("\ncandies: \(candies)")
         } catch let error as NSError {
             print(error.localizedDescription)
         }
     }
 }

当我使用时:(从打印语句中移除展开的力之后)

class Candy {
    let category: String!
    let name: String!

    init(category: String, name: String) {
        self.category = category
        self.name = name
    }
}

输出为:

category: Chocolate, name: Chocolate Bar
category: Chocolate, name: Chocolate Cookie
category: Hard, name: Lollipop

candies: [FileTest.Candy, FileTest.Candy, FileTest.Candy]

您是否可以看到原始代码将所有内容都放在一个struct Candy { let category : String let name : String } 中,但是上面的代码(在RW站点上)创建了单独的category: Chocolate, name: Chocolate Bar category: Chocolate, name: Chocolate Cookie category: Hard, name: Lollipop candies: [FileTest.Candy(category: "Chocolate", name: "Chocolate Bar"), FileTest.Candy(category: "Chocolate", name: "Chocolate Cookie"), FileTest.Candy(category: "Hard", name: "Lollipop")] 元素并将它们全部存储到myArray中?这是方法上的根本区别。