Swift - 遍历字符串中的字符会导致内存泄漏

时间:2016-12-24 16:19:15

标签: ios swift memory-leaks

这是我的第一篇文章!我对Swift比较陌生,并且没有计算机科学背景,所以我仍然容易出现很多新手问题 - 但到目前为止我已经能够解决所有这些问题,部分原因是因为浏览了很好的答案在StackOverflow上。然而,我遇到了一些让我很难过的东西,而且我花了整整一周的时间试图解决它而没有运气。

我要做的是从UITextView获取中文文本,然后将其转换为单个汉字数组,然后用于各种处理和分析。但是,这会导致泄漏。

在这个重现同样泄漏的大大简化的例子中,有一个TextView和一个Button;当用户按下按钮时,调用函数makeArray,它将文本转换为一个字符数组(实际上是单个字符的字符串,因为我需要它作为我将用它做的一些事情的字符串)。包含此函数的类TextProcessing被用作单例(是的,我知道显然单例应该是坏的,原因我不完全理解,但由于涉及代码其他部分的各种原因,它在那里工作得最好)是这个类的单个实例),并将UITextView中的文本传递给它,然后将其转换为数组,如下所示:

class ViewController: UIViewController {
    @IBOutlet weak var textBox: UITextView!
    @IBOutlet weak var doneButton: UIButton!

    @IBAction func pressDoneButton(_ sender: Any) {
        let textToAnalyze = textBox.text!
        TextProcessing.textProcessing.makeArray(textToAnalyze)
    }
}

class TextProcessing {
    static let textProcessing = TextProcessing()

    private let language = "Chinese"
    private var sourceTextArray: [String]!

    func makeArray (_ sourceText: String) {
        if language == "Chinese" {
            sourceTextArray = sourceText.characters.map { String($0) }
        } else if language == "English" {
            sourceTextArray = sourceText.components(separatedBy: " ")
        }
        // then do some stuff with this array
    }
}

当我在Leaks Instruments上运行时,我得到“Malloc 16 Bytes”和“CFString”的泄漏,每个实例的数量与数组元素的数量大致相同(因此,串)。当我查看调用树并向下钻取时,问题行是“sourceTextArray = sourceText.characters.map {String($ 0)}”。

顺便说一句,这种情况发生在相对较长的文本中 - 短文本,或者没有问题或者仪器没有检测到它。

但是,如果我根据空格将字符串分成单词来构建数组,就像我想要的英语语言一样,那就没有泄漏 - 所以如果我在示例代码中将语言变量更改为“English”,它工作正常(但当然不给我我想要的数组)。我认为可能问题出在“map”方法中,因为它使用了一个闭包,并且很容易泄漏闭包,但是当我尝试其他方法将它放入一个字符数组时,例如使用for循环和以这种方式迭代每个字符,它仍然有同样的问题。

如果不是从UITextView获取文本,而是执行此操作:

class ViewController: UIViewController {
    @IBOutlet weak var textBox: UITextView!
    @IBOutlet weak var doneButton: UIButton!

    @IBAction func pressDoneButton(_ sender: Any) {
        let textToAnalyze = "blah blah put a long string of Chinese text here"
        TextProcessing.textProcessing.makeArray(textToAnalyze)
    }
}

没问题。同样,如果在makeArray函数中,如果我忽略sourceText而是执行此操作:

func makeArray (_ sourceText: String) {
    if language == "Chinese" {
        let anotherText = "blah blah some text here"
        sourceTextArray = anotherText.characters.map { String($0) }
    }
    // then do some stuff with this array
}

也没有泄漏。因此,关于从文本框中获取字符串,将其传递给函数,然后将其放入字符数组中的组合导致泄漏。

我花了无数个小时在互联网上搜索关于Swift的ARC的一切,我尝试过各种各样的弱/无主等的东西,似乎没什么用。这里发生了什么以及如何解决这个问题?

修改

所以看起来这可能只是Simulator和/或Instruments的一个问题。当我在设备上运行它,并且只监视xcode调试中的内存使用情况时,即使进行100次以上也没有增加,所以我猜它没关系......但是它仍然显示它会在仪器中显示漏洞。

2 个答案:

答案 0 :(得分:1)

这是仪器错误(存在很多问题)。你的代码没问题。

答案 1 :(得分:0)

我刚刚提交了一个错误报告(FB7684067)。

以下简单的macOS命令行应用程序将在几分钟内增长到超过1GB:

import Foundation
let line = "124;5678;90123"
while true {
    let fields = line.components(separatedBy: ";")
    assert(fields[1] == "5678")
}