###前提・実現したいこと
UILabelの追加/削除を繰り返すと、メモリリークのような動作になりメモリ使用量が増えていきます。
・UILabelの削除時にメモリを開放したい
・そもそも使用量を減らしたい
###発生している問題・エラーメッセージ
上記グラフがUILabelの追加/削除を繰り返した際のメモリ使用量です。
起動直後は43MB程度の使用量でした。
以下グラフに書かれた数字の時点で行った動作です。
0. 180個程度の絵文字を1つずつUILabelに分け、全てのUILabelをviewに追加 → 58MB
0. 1.で追加したUILabelを全てremoveFromSuperview()で削除 → 52MB
0. 1.と2.を繰り返すことでメモリの使用量が増えていく
0. UILabelを全て削除した状態で1分ほど経過しても元のメモリ使用量には戻らず
###該当のソースコード
swift
1import UIKit 2 3class ViewController: UIViewController { 4 let labelFontSize: CGFloat = 20 5 6 // ラベルを追加するコンテナview 7 let labelsContainer = UIView() 8 9 // 絵文字ラベル用 10 let emojiLabelCharacters = "????????????????????☺????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????✨????????????????????????????????????????????????????????????????????✊✌????✋????????????????????????????☝????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????❤????????????????????????????????????????????????????????" 11 12 // テキストラベル用 13 let textLabelCharacters = "あいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよあいうえおかきくけこさしすせそたちつてとなにぬねのはひふへほまみむめもやゆよ" 14 15 override func viewDidLoad() { 16 super.viewDidLoad() 17 18 self.labelsContainer.frame = CGRect(x: 0, y: 0, width: self.labelFontSize * 2, height: self.labelFontSize * 2) 19 self.view.addSubview(self.labelsContainer) 20 21 // view中央にラベルの追加と削除を繰り返し行うボタンを配置 22 let button = UIButton() 23 button.setTitle("ラベル表示/削除", for: .normal) 24 button.setTitleColor(.orange, for: .normal) 25 button.addTarget(self, action: #selector(self.toggleLabels), for: .touchUpInside) 26 self.view.addSubview(button) 27 button.translatesAutoresizingMaskIntoConstraints = false 28 NSLayoutConstraint(item: button, attribute: .centerX, relatedBy: .equal, toItem: self.view, attribute: .centerX, multiplier: 1, constant: 0).isActive = true 29 NSLayoutConstraint(item: button, attribute: .centerY, relatedBy: .equal, toItem: self.view, attribute: .centerY, multiplier: 1, constant: 0).isActive = true 30 NSLayoutConstraint(item: button, attribute: .width, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 150).isActive = true 31 NSLayoutConstraint(item: button, attribute: .height, relatedBy: .equal, toItem: nil, attribute: .notAnAttribute, multiplier: 1, constant: 40).isActive = true 32 } 33 34 @objc func toggleLabels() { 35 // ラベルが追加されていれば取り除く 36 if self.labelsContainer.subviews.count > 0 { 37 for v in self.labelsContainer.subviews { 38 v.removeFromSuperview() 39 } 40 } else { 41 // ラベルが追加されていなければ追加する 42 var characters = self.emojiLabelCharacters 43 var c: Character 44 repeat { 45 // 1文字ずつラベルにして貼り付ける 46 c = characters.remove(at: String.Index(encodedOffset: 0)) 47 let l = UILabel(frame: CGRect(x: 0, y: 0, width: self.labelFontSize * 2, height: self.labelFontSize * 2)) 48 l.text = c.description 49 l.font = .systemFont(ofSize: self.labelFontSize) 50 self.labelsContainer.addSubview(l) 51 l.frame.origin = CGPoint(x: 0, y: 0) 52 } while characters != "" 53 } 54 } 55}
###試したこと
iOS11端末(iPhone6)、シミュレーターで試しましたが、どちらもUILabelの追加/削除でメモリ使用量が増えていきました。
文字サイズに比例してメモリ使用量が変化するため、内部的にはテキストを画像化して扱っているのかと推測しました。
そのため、テキストデータとして描画?のような機能があればメモリ削減できるのではと思いました。
###補足情報(言語/FW/ツール等のバージョンなど)
絵文字が簡単に入力できるkeyboard extensionを作成しているのですが、メモリ制限が30MBなのですぐにmemory warningが発生し、一定時間経過後に落ちてしまいます。
なお、キーボード内の絵文字一覧はUICollectionViewでreusableなcellにUILabelを追加して表示しています。
以上、解決方法がありましたらご教授いただければ幸いです。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2017/11/06 16:52
2017/11/07 00:29