swift - 无法将文本文件读入所需的数组格式

标签 swift uitableview parsing uiviewcontroller uisearchcontroller

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

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

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

下面是我尝试使用下面提供的示例文本文件 (candyTextFile.txt) 来读取和生成必要的“糖果”数组。 请查看类 MasterViewController 中的注释行,了解错误消息和我尝试将糖果数组输出为的代码。

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

我对 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

最佳答案

假设您想要做的是从文本文件中获取信息并最终得到一系列糖果产品,我将尝试一下。目前,您的 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 循环以在每个循环中提取一个糖果的数据(类别和名称),创建一个新的 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 数组应该包含一堆 Candy 对象,因此要将它们列出到控制台,您可以这样做。

for candy in candies {
   print("category: \(String(describing: candy.category)), name: \(String(describing: candy.name))")
}

让我知道我是否仍未达到目标。

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

我看了你链接的 RW 教程。

本教程为 Candy 元素使用了一个 struct,而您(和我)使用的是一个类。我猜你还在学习 Swift 的值和引用类型,所以不要把这里的水弄混了。可以说 struct 在这种情况下可能会更好。 print 也以不同的方式处理它们,并且似乎能够在结构内部查找值,而除非您明确提取属性(如我的 for in print 语句,它只会给您我们所见的类列表。

我还整理了逻辑(它很丑陋,你不应该这样做)所以你至少可以看到它确实有效(在某种程度上)。整个 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]

当我使用时:(从 print 语句中移除强制展开后)

struct Candy {
    let category : String
    let name : String
}

输出是:

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 中,但是上面的代码(和 RW 站点上的代码)创建了单独的 Candy 元素并将它们全部存储到糖果?这是方法上的根本区别。

关于swift - 无法将文本文件读入所需的数组格式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54016169/

相关文章:

java - 使用jsoup逐行读取robot.txt

ios - 发送到 Swift 中的 firebase 云函数后,字典对象数组会发生变化吗?

ios - 再次显示 View Controller 时 AutoLayout 中断

java - 将 Java 中的字符串转换为整数

ios - 禁用 UIScrollView 向特定方向拖动事件并将事件发送到 super

objective-c - tableview - 无法识别的选择器 didSelectRowAtIndexPath

java - 如何使用 DOM API 访问 XML 节点的值

ios - iCarousel 获取用户点击索引

swift - Collada 变形动画混合形状 Maya

ios - “无法识别的选择器已发送到实例”-添加搜索栏时出错