2016-12-24 22 views
3

これは私の最初の投稿です!私はSwiftには比較的新しいですし、コンピュータサイエンスのバックグラウンドを持っていないので、まだ初心者の問題がたくさんありがちですが、これまでのところすべて解決できました。 StackOverflowで。しかし、私は本当に私を困らせている何かを見つけました。そして、私は一週間も過ごすことなく、それを解決しようと努力しました。スウィフト - 文字列の文字を繰り返してメモリリークが発生する

私がしようとしているのは、中国語のテキストをUITextViewから取り出し、これを個々の中国語の文字列に変換してから、さまざまな処理と分析に使用します。しかし、これはリークを引き起こす。

同じリークを再現するこの非常に単純化された例では、TextViewとButtonがあります。ユーザーがボタンを押すと、関数makeArrayが呼び出され、文字列(実際には1文字の文字列)に変換されます。文字列は文字列でなければなりません。この関数を含むクラス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 
    } 
} 

私はリークの楽器でこれを実行すると、私は"Malloc 16 Bytes"と "CFString"のリークを取得します。各インスタンスの数は配列要素の数とほぼ同じです(したがって文字列の文字数)。私がコールツリーを見てドリルダウンするとき、問題の行は "sourceTextArray = sourceText.characters.map {String($ 0)}"です。

ところで、これは比較的長い文章で起こります。短い文章では問題ありません。また、インストゥルメントはそれを検出しません。

しかし、英語のような言語のように、文字列をスペースで区切って配列を作成すると、リークはありません。したがって、例のコードでlanguage変数を "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に関するすべてを読んで何時間も費やしてきました。私は弱い/無残なものであらゆる種類のものを試しましたが、何も動作しないようです。ここで何が起こっているのですが、どうすればこの問題を解決できますか?

編集:

だから、これは単なるシミュレータおよび/または楽器に問題があるかもしれないことが表示されます。私はそれをデバイス上で実行し、xcodeデバッグでのメモリ使用量を監視するだけで、100回以上実行しても増加はないので、それはOKだと思います...しかし、それでもインストゥルメントではリークを示すのは変です。

+0

正常に動作します。私はあなたのコードを非常に長いテキストで試しました - 約100万の漢字:) - そして漏れはありません! – 3li

+0

class TextProcessing {static let textProcessing = TextProcessing()} ...これが問題であるかどうかはわかりませんが、このクラスをクラスの内部変数として再インスタンス化する必要はありません。オブジェクトの開始! –

+0

@ 3liそれは奇妙です...私はいくつかのパラガープより長く何かを試すたびに一貫してそれが漏れます。私はSwift 3でXCode 8.2.1を使用しています。メモリ割り当てはどうですか?あなたがリークを検出しなくても、完了ボタンを繰り返し押すと合計メモリが増加し続けますか? – Jason210006

答えて

1

これは楽器のバグです(多くの問題があります)。あなたのコードはOKです。

+0

ええと、私は完全にはわかりません。 Allocationsでリーク音源を実行すると、Leaks Instrumentのバグになる可能性があります。ボタンを繰り返し押すと、全体のメモリーが順調に増加します。たとえインストゥルメントでも、シミュレータだけで実行していないときでも、ボタンを繰り返し押すとトータルメモリーが上がったり上がったりします...明らかに何かがうまくいきません。 – Jason210006

+0

OK、もう少しテストした後、あなたが正しいかもしれないようです。問題は、私はデバイスではなくSimulatorでテストしていたことでした。私がデバイス上でテストすると、Leaksの計測器は同じリークを示していますが、割り当てはメモリが順調に上昇していることを示していますが、デバイス上で実行してxcodeデバッグの統計情報のメモリを見ると、私がそれを100回以上しても、記憶に残っています。 (シミュレータでは、xcodeでも毎回メモリが上がっています)だから、この組み合わせ(xcode +デバイス)は最も正確で、それでいいですか?奇妙な.. – Jason210006

+0

それは変です。しかし、楽器は重いツールであり、バグがなくてもそれを書くのは非常に難しいです。また、Xcodeにも多くの問題が含まれています:) –

関連する問題