質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

Q&A

5回答

28473閲覧

[Swift]メモリ解放の方法

RioNishino

総合スコア36

iOS

iOSとは、Apple製のスマートフォンであるiPhoneやタブレット端末のiPadに搭載しているオペレーションシステム(OS)です。その他にもiPod touch・Apple TVにも搭載されています。

Xcode

Xcodeはソフトウェア開発のための、Appleの統合開発環境です。Mac OSXに付随するかたちで配布されています。

Swift

Swiftは、アップルのiOSおよびOS Xのためのプログラミング言語で、Objective-CやObjective-C++と共存することが意図されています

0グッド

6クリップ

投稿2015/06/08 01:50

編集2015/06/16 01:51

Swiftでメモリを解放する方法を教えてください。

ある処理をクラス化しているのですが、処理が行われるたびにメモリが増えていきます。何度も繰り返していると1GBまでメモリの使用量が増えていき、アプリが落ちてしまいます。

初心者なので詳しくは分かりませんが、生成されたインスタンスが破棄されたままになっているのではと推測しています。

ちなみにこれが起こる処理はふたつあります。
前提としてTableViewでRSSを表示するアプリです。

①ページ遷移先のデザインを別にクラス化しており、セルが選択されるたびにそのクラスのインスタンスが生成される

②表示切り替えボタンを押すと、TableViewの表示方法が変更される。その表示を切り替えるたびに、一度ViewControllerを消して再描画している

この二つのときにメモリの消費が激しく、アプリが落ちてしまいます。
autoreleasepoolを使用してもうまくいきませんでした。

説明が下手で理解しづらくて申し訳ありません。

思い当たる方法があれば、ご教示いただけると光栄です。
よろしくお願いいたします。

追記

ソースコードを追加しました。

// WebviewController.swift class WebviewController: UIViewController, UIWebViewDelegate { override func viewDidLoad() { super.viewDidLoad() let screenwidth = self.view.bounds.size.width let screenheight = self.view.bounds.size.height let urlString = NSURL(string: "http://hogehoge.com") let urlRequest = NSURLRequest(URL: urlString!) var webview = UIWebView() webview.frame = CGRectMake(0, 0, screenwidth, screenheight - 45) webView.delegate = self webView.loadRequest(urlRequest) let toolbar = Toolbar() self.view.addSubview(toolbar.makeToolbar()) }
// Toolbar.swift class ToolBar: UIView { func makeToolvar() -> UIToobar { // Toolbar作成 let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: screenWidth, height: 45.0)) toolbar.backgroundColor = UIColor(red: 245/255, green: 245/255, blue: 245/255, alpha: 1.0) return toolbar } }

上記のWebviewControllerが開くたびに、ToolbarControllerのインスタンスが生成されます。
WebviewControllerを閉じてもToolbarControllerのインスタンスが破棄されていないのか、メモリが増えていって困っています。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

KoichiSugiyama

2015/06/09 14:09

その処理のソースを掲載してもらわないと具体的なアドバイスができません。全部でなくてもいいですので、ソースを掲載することはできませんか?
RioNishino

2015/06/10 01:13

申し訳ありません。 簡単ではありますが、ソースを追記いたしました。
Stripe

2015/06/10 13:55

そのソースコードは内容が変です。正確に書いてください。
RioNishino

2015/06/11 03:34

最初のソースコードが今回の質問の核となる部分だと考えて、追記いたしました。 その他は装飾的な部分なので必要ないと判断しましたが、初心者なので何が必要かどうかの判断は曖昧です。もしよろしければ必要な処理部分があれば教えてください。内容が変なところも教えていただけると光栄です。勉強になるので!
Stripe

2015/06/11 11:56

今回問題としている、ToolbarControllerクラスのコードも書いてください。そこに書いてあるToolBarクラスとは別ものですよね?
RioNishino

2015/06/12 03:32

多分同じだと思います。WebviewControllerとToolbarの二つのクラスしかありません。
Stripe

2015/06/12 10:30

ならば、そのコードはやっぱり変です。コンパイルエラーになって、実行できないはずです。
RioNishino

2015/06/15 07:13

申し訳ありません。ソースコードに誤字がありました。
Stripe

2015/06/15 12:19

誤字はそれだけですか?makeToolbar()の戻り値がVoid型になっているので、それをaddSubview()したらエラーになります。
RioNishino

2015/06/16 01:51

何度も申し訳ありません。修正いたしました。
Stripe

2015/06/16 10:32

では次に、問題となっている2つの処理(質問文の中の①②)のコードを書いてください。ちなみに、ToolBarクラスのインスタンスはすぐに破棄されるので、これが原因でメモリは増えません。
RioNishino

2015/06/17 00:09

①の処理はToolbarクラスの件です。ToolBarクラスのインスタンスのせいか分からないですが、メモリが増えているのが現状です。そう考える理由は、ToolBarをクラス化せずにWebviewControllerに直接記述するとメモリが増えないからです。
Stripe

2015/06/17 12:49

隠さずにコードを書いてください。まだまだ、書いていないコードが沢山ありますよね?
RioNishino

2015/06/17 23:55

何も隠してはいないのですが、何が必要なのかがわかないというのが正直なところです。本当にそれに関しては申し訳ありません。何度も正確に書け、隠さずに書け、と言われるということは問題はここには無いということでしょうか? そうすると思い当たるのは、Webviewを表示するときにmodalPresentationStyleでカスタムクラスを利用しています。そのインスタンスが破棄されていないということでしょうか?
guest

回答5

0

このタイプの問題が起きたときの一般的な対処方法で、まずは、トライしてみるのが良いと思います。いくつかに分けて書きます。

[1] 問題の絞り込み
どこがメモリリークの原因になっているかを絞り込んだ方が良いと思います。
まず、下記の2行をコメントアウトし、何度も実行してみて、問題が起きるかを確認してください。

swift

1let toolbar = Toolbar() 2self.view.addSubview(toolbar.makeToolbar())

次に、2行目だけをコメントアウトして、同じ操作をし、問題が起きるかを確認します。
(インスタンス確保が問題か、追加することが問題か、そもそもToolBarクラスが原因かどうかの判別)

[2] 呼び出しタイミングの確認
上記のviewDidLoadが呼ばれるタイミングが意図した通りかを確認します。例えば、実行される度に、WebViewControllerの解放が無く、viewDidLoadが呼ばれていると、呼ばれる度にWebViewControllerが増えていきます。

その場合はWebViewControllerが解放される側の処理に問題があります。つまり、追記して頂いているコード以外の場所です。例えば、WebViewControllerを作って表示するところなど。

[3] ToolBarクラスのスーパークラスについて
コードを拝見すると、ToolBarクラスはUIToolBarを作って返すコードなので、ToolBarクラスがUIViewクラスのサブクラスである必要は無いと思います。予期しない処理が入り込む可能性を防ぐ意味でも、ToolBarクラスを直接配置するのでなければ、スーパークラス無しで良いと思います。

投稿2017/02/13 03:54

studiork

総合スコア110

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

クラス化して使いたいとのことであれば、シングルトンでの設計をオススメします。
シングルトンとは、そのクラスのインスタンスがいつしかないことを保証する設計方法です。
クラス化する部分が、全て共通部分であるのなら、ToolBarのインスタンスは一つにして使い回すということができるはずですよ!

投稿2017/01/29 14:33

black_sleepman

総合スコア220

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

self.view.addSubview(self.webview)
let toolbar = ToolBar()
toolbar.makeToolbar()
self.view.addSubview(toolbar)

この辺のも解放した方がよいかもです。
self.webview.removeFromSuperview();
toolbar.removeFromSuperview();
self.webview = nil;
toolbar.release();
toolbar = nil;

投稿2015/06/17 02:39

MasaakiIrie

総合スコア1021

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ToolBarControllerといいつ、ToolBar(UIViewのサブクラス)しかないので、
実際の所どう動いているのかわかりませんが、WebviewControllerは、
webviewとtoolbarが貼り付けられているviewのコントローラという認識で回答します。

まず、Toolbarがメモリリークを起こしていたからといって使用メモリが1GBになるということはそうそうありません。

おそらくWebViewControllerがメモリリークしているか、WebViewのメモリが上手く開放されていないと考えれます。

オブジェクトが開放されるタイミングでdeinitという特別なところが呼ばれるので、
そこでWebViewControllerが呼ばれていることを確認してください。

lang

1class WebviewController: UIViewController, UIWebViewDelegate { 2 3 deinit { 4 println("WebviewControllerは正しく解放されました") 5 } 6}

WebView自身が開放されているか確認したい場合は、サブクラス化してdeinitを書くといいです。

また、インスタンスを正しく開放していてもWebViewのコンテンツがおかしかったりして
システム的にメモリリークする場合があります。

その場合は、deinitで空のHTMLを読み込ませてメモリを解放すると解決する場合もあります。

lang

1class WebviewController: UIViewController, UIWebViewDelegate { 2 3 var webview: UIWebView! 4 5 override func viewDidLoad() { 6 super.viewDidLoad() 7 8 let screenwidth = self.view.bounds.size.width 9 let screenheight = self.view.bounds.size.height 10 11 let urlString = NSURL(string: "http://hogehoge.com") 12 let urlRequest = NSURLRequest(URL: urlString!) 13 14 self.webview = UIWebView() 15 self.webview.frame = CGRectMake(0, 0, screenwidth, screenheight - 45) 16 self.webview.delegate = self 17 self.webview.loadRequest(urlRequest) 18 self.view.addSubview(self.webview) 19 20 let toolbar = ToolBar() 21 toolbar.makeToolbar() 22 self.view.addSubview(toolbar) 23 } 24 25 deinit { 26 self.webview.delegate = nil 27 self.webview.stopLoading() 28 self.webview.loadHTMLString("", baseURL: nil) 29 } 30}

投稿2015/06/13 11:32

okenProg

総合スコア153

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

RioNishino

2015/06/15 07:30

回答ありがとうございます。 また、丁寧に解説いただき感謝申し上げます。 色々と勉強になりました。 メモリが1GBまでいくのは、何度もWebviewを読んだ時です。 教えていただいた方法を実行したところ、メモリ消費が大きく抑えられました。 ありがとうございます。 ただ、Webviewを呼ぶたびに20〜30MBほどメモリが上がるのですが、これは正常なことなのでしょうか? それともまだメモリ解放できていないということなのでしょうか?
okenProg

2015/06/15 08:09

WebViewは、キャッシュなどView以外のメモリも確保されるので、WebViewの画面が消えたからといって直ぐにメモリが解放されなかったりします。 ただ、ページを開きなおした場合は、既に確保したメモリが使われるので、トータルのメモリ量はさほど増えないと思います。 もしも、画面を閉じて開いてを繰り返した際に延々と20~30MB増え続けて減ることが無いのであれば、正しく解放されていないと思います。
RioNishino

2015/06/16 01:55

繰り返し画面を開いたり閉じたりしていると、延々とメモリが増え続けます。クラス化せずにUIToolbarを直接WebviewControllerに記述すれば、メモリが増えることはありません。 しかし、他の場所でも使うためクラス化しておきたいのです。 ご回答、ご返信ありがとうございます。 色々と模索してみます。
guest

0

addSubViewしたviewを削除する場合、removeFromSuperview()を呼ぶ必要があるようです。
WebviewControllerを閉じるタイミングで

lang

1 var subviews = self.subviews 2 for subview in subviews { 3 subview.removeFromSuperview() 4 }

のような処理を入れてやる必要があると思います。
また、ToolBarクラス(ToolbarControllerクラス?)が破棄されるタイミングでも同様にaddSubViewされているUIToolbarもremoveFromSuperviewを呼ばないといけないと思います。

投稿2015/06/10 05:53

KoichiSugiyama

総合スコア3041

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

RioNishino

2015/06/12 03:34

回答ありがとうございます。 removeFromSuperview()はインスタンスも破棄されるものなのでしょうか? 試してみたところ、インスタンスが破棄されている様子がありません。
MasaakiIrie

2015/06/17 02:31

ビューのリンクが外れるだけですね。 インスタンスは破棄されないと思いますよ。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

まだベストアンサーが選ばれていません

会員登録して回答してみよう

アカウントをお持ちの方は

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問