NSTextStorage
클래스를 정의하여 Apple의 TextKit을 사용하는 사용자 정의 UITextView
이 있지만, 사용자 정의 텍스트보기, 텍스트 저장소 (아래 구현 됨) 및 서브 클래스를 사용할 때 20.0KB보다 큰 파일을 열어보십시오. 응용 프로그램이 메모리 누수로 인해 충돌합니다 : "Message from debugger: Terminated due to memory issue
".하위 클래스 NSTextStorage로 인해 심각한 메모리 문제가 발생합니다.
이상하게도 사용자 정의 BMTextStorage
을 표준 크기 인 NSTextStorage
으로 바꾸면 메모리 누수없이 즉시 텍스트가로드되고 < RAM이 30MB 사용됩니다. 이 원인은 무엇입니까?
TextView.swift
class TextView : UITextView {
required init(frame: CGRect) {
// If I replace the following line with simply
// "let textStorage = NSTextStorage()"
// I can open any file of any size and not have a memory leak
// issue, using only about 20-30MB of RAM. If I ran this code
// as is, it can open most files less than 20KB but will
// crash otherwise.
let textStorage = BMTextStorage()
let layoutManager = NSLayoutManager()
layoutManager.allowsNonContiguousLayout = true
let textContainer = NSTextContainer(size: CGSizeMake(.max, .max))
textContainer.widthTracksTextView = true
textContainer.heightTracksTextView = true
textContainer.exclusionPaths = [UIBezierPath(rect: CGRectMake(0.0, 0.0, 40.0, .max))]
layoutManager.addTextContainer(textContainer)
textStorage.addLayoutManager(layoutManager)
super.init(frame: frame, textContainer: textContainer)
textStorage.delegate = self
layoutManager.delegate = self
}
}
BMTextStorage.swift
typealias PropertyList = [String : AnyObject]
class BMTextStorage : NSTextStorage {
override var string: String {
return storage.string
}
private var storage = NSMutableAttributedString()
override func attributesAtIndex(location: Int, effectiveRange range: NSRangePointer) -> PropertyList {
return storage.attributesAtIndex(location, effectiveRange: range)
}
override func replaceCharactersInRange(range: NSRange, withString str: String) {
storage.replaceCharactersInRange(range, withString: str)
edited([.EditedAttributes, .EditedCharacters], range: range, changeInLength: str.length - range.length)
}
override func setAttributes(attrs: PropertyList?, range: NSRange) {
storage.setAttributes(attrs, range: range)
edited([.EditedAttributes], range: range, changeInLength: 0)
}
override func processEditing() {
super.processEditing()
}
}
재정의 한 네 가지 방법 중 하나로 좁힐 수 있습니까? (그리고'processEditing()'은 아무 것도하지 않기 때문에 모두 삭제할 수 있습니다.) – NRitH
@NRitH 추상 클래스에 의해 오버라이드 (override) 될 필요가 있기 때문에 쉽게 범위를 좁힐 수 없습니다. 그리고 네,'processEditing()'을 생략하면 문제가 변하지 않습니다. 제가 생각한 중단 점을 시도했지만, 큰 파일의 경우 특히 충돌하기 전에 영원히 반복됩니다. –