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

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

ただいまの
回答率

90.34%

  • Swift

    7719questions

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

  • Xcode

    4360questions

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

  • iOS

    4197questions

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

  • メモリリーク

    48questions

    メモリリークは、プログラムファイルがメモリの解放に失敗した時に起こります。

Swift 端末内に入っている写真を取得する際アプリが落ちてしまう。

受付中

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 394

kizahashi

score 4

SwiftにてcollectionView をつかったアルバムアプリを作成しております。

PHAsset.fetchAssetにてPHAssetを取得し
PHCachingImageManagerにて画像を表示しています。

画像のサイズが200×200ですとギリギリ表示されるのですが
画像のサイズを400×400などに設定するとほぼ動作しなくなり

Message from debugger: Terminated due to memory issue

[GatekeeperXPC] Connection to assetsd was interrupted or assetsd died

などのメッセージが出てアプリが落ちてしまいます。

今の所以下のようなやり方でスマートアルバム、アルバムを取得しています。

func getPhotos(albumName1: PHAssetCollectionType, albumName2: PHAssetCollectionSubtype){
//        let imgManager = PHImageManager.default()
        let cacheManeger = PHCachingImageManager()
        cacheManeger.allowsCachingHighQualityImages = false

        let requestOptions = PHImageRequestOptions()
        requestOptions.isSynchronous = false
        requestOptions.deliveryMode = .highQualityFormat

        let fetchOptions = PHFetchOptions()
        fetchOptions.sortDescriptors = [NSSortDescriptor(key: "creationDate", ascending: false)]


// アセットコレクションを取得
        let assetCollections = PHAssetCollection.fetchAssetCollections(with: albumName1, subtype: albumName2, options: nil)

        assetCollections.enumerateObjects { assetCollection, index, stop in

            // アセットを取得
              let assets = PHAsset.fetchAssets(in: assetCollection, options: fetchOptions)



            assets.enumerateObjects { asset, index, stop in

                cacheManeger.startCachingImages(for: [asset], targetSize: CGSize(width: 200, height: 200), contentMode: .aspectFill, options: requestOptions)

                cacheManeger.requestImage(for: asset, targetSize: CGSize(width: 200, height: 200), contentMode: .aspectFill, options: requestOptions, resultHandler: { img, _ in
//                    DispatchQueue.global().async {

                    if let img2 = img {
                        // print("画像の取得に成功")

                        if assetCollection.localizedTitle == "\(selectAlbum)"
                        {
                            imageArray.append(img2)
                        }else if assetCollection.assetCollectionType == .smartAlbum{
                            imageArray.append(img2)

                        }
                        photosTotalAmount = [Int](0...imageArray.count)

                        }
                })

            }
        }  
    }

app storeで配信されているアルバムアプリやカメラアプリの写真選択画面などでは、ほぼ全ての画像が高画質で3秒も経たぬうちに読み込まれて表示されています。

なぜそんなに高速なのでしょうかPHImageManager以外の方法、ライブラリなどあるのでしょうか?
いまのやり方ですと写真5000枚程度のカメラロールを取得するのに早くても5秒。遅くて10秒を超えてしまいます。

そのほかにやったこととしては
サブスレッドで画像を取得。
collectionView.reloadDataを一定の枚数取得したら実行。
など試しましたがやはり基本の読み込みスピードからして遅い気がします。

まとめますと、アプリが落ちないように、また写真取得を高速化するにはどこを改善すれば良いでしょうか?

解決法、ヒント等いただけたら幸いです。
よろしくお願いいたします。

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

+1

要件にもよりますが、まずは5000枚端末に入っていても表示するだけが要件であれば、画面に表示出来る枚数+αだけ読み込んだら良いと思います。
5000枚を読み込んだ後に表示をするというロジックであれば、限界が来ることは必然です。
またアプリが落ちる原因として考えるられるのもメモリ不足です。
こちらも同じ理由で画面に表示出来る枚数に限定してロードすることでメモリは足りると思います。
参考になれば、幸いです。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

同じタグがついた質問を見る

  • Swift

    7719questions

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

  • Xcode

    4360questions

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

  • iOS

    4197questions

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

  • メモリリーク

    48questions

    メモリリークは、プログラムファイルがメモリの解放に失敗した時に起こります。