Rutger Huijsmans Rutger Huijsmans - 1 year ago 131
Swift Question

UITextView memory leak when line breaks are present

My whole app freezes up when line breaks are added to the string I want to fill up a UITextView with.

This freezes up the app:

let testStringLineBreaks = "foooooo \n \n barrrrrr"
self.biographyTextView.text = testStringLineBreaks

This doesn't freeze up the app:

let testStringNoLineBreaks = "foooooobarrrrrr"
self.biographyTextView.text = testStringNoLineBreaks

Why? And how do I fix it? I need to be able to use linebreaks on my UITextView as well because this is where users fill in their profile description.

enter image description here

The app uses about 60 MB. However when it gets stuck on the line:

self.biographyTextView.text = testStringLineBreaks

It keeps going up with about 2 mb per second. I killed the app at 183 mb.

It only happens on iOS 8 and not on iOS 9.

import UIKit

class GFTextView: UITextView {
let bottomBorder = CALayer()

@IBInspectable var haveBottomBar:Bool?

required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.textContainer.lineFragmentPadding = 0

func addBottomBar(){
bottomBorder.frame = CGRectMake(0.0, self.frame.size.height - 1, self.frame.size.width, 1.0);
bottomBorder.backgroundColor = UIColor.grayColor().CGColor

override func becomeFirstResponder() -> Bool {
let shouldBecomeFirstResponder = super.becomeFirstResponder()
bottomBorder.backgroundColor = shouldBecomeFirstResponder ? Constant.ui_applicationMainColor.CGColor : Constant.ui_applicationMainColor.CGColor
return shouldBecomeFirstResponder

override func resignFirstResponder() -> Bool {
let shouldResignFirstResponder = super.resignFirstResponder()
bottomBorder.backgroundColor = shouldResignFirstResponder ? UIColor.grayColor().CGColor : Constant.ui_applicationMainColor.CGColor
return shouldResignFirstResponder

override func layoutSubviews() {
if let font = self.font {
self.font = GFFont.fontForDefaultFontName(font.fontName, size: font.pointSize)
} else {
self.font = UIFont.systemFontOfSize(12)
bottomBorder.backgroundColor = UIColor.grayColor().CGColor

Answer Source

Based on the fact that you only get the error from your custom UITextView subclass, the problem is obviously from your implementation.

The most likely cause is your implementation of the layoutSubview function. The only types of things you should do in that overridden function is to adjust frames as needed.

Setting the font is probably causing a recursive call to layoutSubviews or something similar.

Setting the background color should be done in the init function. Setting the font should be done later since it depends on the value of a property that won't be set when init is called. The best place to set the font is in an override of the font property's setter.