это мой первый пост! Я относительно не знаком с Swift, и у меня нет опыта в области компьютерных наук, поэтому я все еще склонен к множеству проблем с новичками, но до сих пор я смог решить их все, отчасти от просмотра превосходных ответов на StackOverflow. Тем не менее, я столкнулся с чем-то, что действительно сильно меня озадачило, и я потратил целую неделю, пытаясь решить ее без везения.Swift - итерация через символы в строке вызывает утечку памяти
То, что я пытаюсь сделать, это взять текст на китайском языке из 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
}
}
Когда я бегу это на утечках инструменты I получить утечки «Malloc 16 Bytes» и «CFString», причем количество экземпляров каждого из них примерно совпадает с количеством элементов массива (таким образом, количество символов в строке). Когда я смотрю на Дерево вызовов и разворачиваюсь, проблема связана с «sourceTextArray = sourceText.characters.map {String ($ 0)}».
Кстати, это происходит с относительно длинными текстами - с короткими, либо нет проблем, либо Инструменты не обнаруживают его.
Однако, если я создаю массив, разделив строку на слова в соответствии с пробелами, как хотелось бы на таком языке, как английский, утечки нет - поэтому, если я изменю языковую переменную на «английский» в примере кода , он отлично работает (но, конечно, не дает мне массив, который я хочу). Я думал, что, возможно, проблема была в методе «карта», поскольку она использует закрытие, и легко получить утечки с закрытием, но когда я пытаюсь использовать другие способы поместить его в массив символов, например, используя цикл 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
}
нет также никакой утечки. Итак, что-то о комбинации получения строки из текстового поля, передачи ее в функцию, а затем вставки ее в массив символов вызывает утечку.
Я провел бесчисленное количество часов, прочесывая интернет и прочитывая все о ARC в Swift, и я пробовал всевозможные вещи со слабым/неработающим и т. Д., И ничего не работает. Что здесь происходит и как это можно решить?
Edit:
Так что кажется, что это может быть просто проблема с Simulator и/или инструменты.Когда я запускаю его на устройстве и просто отслеживаю использование памяти в отладке xcode, нет увеличения даже при выполнении его 100 раз, поэтому я думаю, что все в порядке ... По-прежнему кажется странным, что это может показать утечку в Инструментах.
Он отлично работает. Я пробовал ваш код с очень длинным текстом - около миллиона китайских символов :) - и никакой утечки! – 3li
class TextProcessing {static let textProcessing = TextProcessing()} ... Я не знаю, является ли это проблемой, но вам, разумеется, не нужно переустанавливать этот класс как переменную класса внутри себя. Создание объекта! –
@ 3li Это странно ... он постоянно течет каждый раз, когда я пробую его с чем-то большим, чем несколько парагафов. Я использую XCode 8.2.1 с Swift 3. Что относительно распределения памяти - даже если он не обнаруживает утечку для вас, увеличивается ли общая память, если вы повторно нажимаете кнопку «Готово»? – Jason210006