【问题标题】:CSVImporter starts importing after viewdidload [Swift]CSVImporter 在 vi​​ewdidload [Swift] 后开始导入
【发布时间】:2017-08-09 05:03:59
【问题描述】:

我想从 .csv 文件导入数据,所以我使用了 CSVImporter https://github.com/Flinesoft/CSVImporter。它运行良好,但它在函数 viewDidLoad 的其他部分执行之前开始导入。

以下代码只是一个测试,但我需要一个解决方案来确保 CSVImporter 在其他 viewDidLoad 代码执行之前完成导入,或者一个在 viewDidLoad 之后自动启动的函数。

这是我的代码:

var Vokabeln: [[String]]?


var i = 0


override func viewDidLoad() {
    super.viewDidLoad()


    let path = "/Users/---CENSORED---/Documents/TestLöschen/TestLöschen/Vokabeln.csv"
    let importer = CSVImporter<[String]>(path: path, delimiter: ";")
    importer.startImportingRecords { $0 }.onFinish { importedRecords in
        for record in importedRecords {
            self.Vokabeln?[self.i][0] = record[0]
            self.Vokabeln?[self.i][1] = record[1]
            self.Vokabeln?[self.i][2] = record[2]
            print("Begin1")
            print(record[0])
            print(record[1])
            print(record[2])
            print("End1")
            self.i += 1
        }
    }

    print("Begin2")
    print(Vokabeln?[0][0])
    print(Vokabeln?[0][1])
    print(Vokabeln?[0][2])
    print(Vokabeln?[1][0])
    print(Vokabeln?[1][1])
    print(Vokabeln?[1][2])
    print("End2")
}

所以首先它打印“Begin2”,然后 6 次打印 nil。然后,当函数 viewDidLoad 完成时,它会打印“Begin1”,然后是正确的变量和“End1”

有人可以帮我吗? 谢谢。

【问题讨论】:

  • "CSVImporter 默认异步工作,因此不会阻塞主线程。"阅读有关您的库的文档。不要阻塞主线程。在 onFinish{} 闭包上调用其余方法。或阅读部分Import Synchronously
  • @Larme 我已经同步了,但他仍然打印 nil。

标签: swift csv csv-import


【解决方案1】:

startImportingRecords 异步工作,只需将打印Vokabeln 的代码放在重复循环后的完成处理程序中即可。

首先你需要初始化数组,否则不会追加任何内容。并且不要将数组声明为可选,变量名应该以小写字母开头。

var vokabeln = [[String]]()

如果要更新 UI,例如将代码包装在调度块中

importer.startImportingRecords { $0 }.onFinish { importedRecords in
    for record in importedRecords {
        self.vokabeln[self.i][0] = record[0]
        self.vokabeln[self.i][1] = record[1]
        self.vokabeln[self.i][2] = record[2]
        print("Begin1")
        print(record[0])
        print(record[1])
        print(record[2])
        print("End1")
        self.i += 1
    }
    DispatchQueue.main.async {
        print("Begin2")
        print(self.vokabeln[0][0])
        print(self.vokabeln[0][1])
        print(self.vokabeln[0][2])
        print(self.vokabeln[1][0])
        print(self.vokabeln[1][1])
        print(self.vokabeln[1][2])
        print("End2")
   }
}

但是还有另一个问题。如果您将数组声明为[[String]],则外部和内部数组都是空的,并且您不能使用索引下标分配值。我推荐这种语法

for record in importedRecords {
    self.vokabeln.append(record) // this appends the whole record array
    print("Begin1")
    print(record)
    print("End1")
}

PS:考虑使用更合适的文本格式,如 JSON 或属性列表。

【讨论】:

  • 因为您要将它用于具体的非可选数据。如果无法接收/转换数据,则数组只是空的。这比可选绑定更容易使用,您可以省略所有问号。不应将可选选项用作 I-don't-care 的不在场证明。
  • 什么是调度块?带有打印的代码只是一个例子。真正的代码要大得多。
  • 推荐在主线程上执行大括号内的代码,例如更新用户界面。如果不涉及 UI 或没有其他环境需要主线程,则不需要它。
  • 当我尝试初始化没有问号的变量时,它会给出错误“类视图控制器没有初始化器”
  • 再一次,[[String]]——无论是可选的还是非可选的——都是空的。 没有索引 0,无论是在内部还是在外部数组中。您需要 insertappend 对象才能使用索引下标。同样var Test: [[String]] 再次 初始化 数组,您只是声明 它,数组是nil。另一个不使用可选项的论点。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-03-28
  • 1970-01-01
  • 2014-06-17
  • 1970-01-01
  • 1970-01-01
  • 2012-09-20
  • 2016-11-10
相关资源
最近更新 更多