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

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

ただいまの
回答率

88.64%

アルバムの画像をファイルサイズ順で取得したい

解決済

回答 1

投稿

  • 評価
  • クリップ 1
  • VIEW 1,038

shoboo

score 7

 前提・実現したいこと

表題の通り、Swiftでアルバムの画像をファイルサイズ順(昇順、降順どちらでも)で取得したいと思っています。

 試したこと

日付など、PHAssetのメタデータとして取得できるものは、下記のようにoptionsを設定することでソートして取得できると思います

photoAssets = []
var options = PHFetchOptions()
options.sortDescriptors = [
    NSSortDescriptor(key: "creationDate", ascending: false)
]

var assets: PHFetchResult = PHAsset.fetchAssetsWithMediaType(.Image, options: options)
assets.enumerateObjectsUsingBlock { (asset, index, stop) -> Void in
    photoAssets.append(asset as PHAsset)
}

しかし、ファイルサイズはメタデータとして持っていないのでsortメソッドなどを使用してソートする必要があるかと思います。
そこで、ファイルサイズを取得する関数を用意しソートを実行しましたが、ファイルサイズの取得が同期的に行えず、ソートが行なえませんでした。

// ソート処理
photoAssets.sort(by: {
    self.getFileSize(phAsset: $0) > self.getFileSize(phAsset: $1)
})

// ファイルサイズの取得
func getFileSize(phAsset: PHAsset) -> Int {
    var fileSize = 0
    var url: URL?
    let semaphore = DispatchSemaphore(value: 0)

    let options: PHContentEditingInputRequestOptions = PHContentEditingInputRequestOptions()
    // 下記のだと、デットロック状態になって処理が止まる
    phAsset.requestContentEditingInput(with: options, completionHandler: { (input, info) in
        if let input = input {
            url = input.fullSizeImageURL
        }
        semaphore.signal()
    })            

    semaphore.wait()
    if let url = url {
        do {
            let attr: NSDictionary = try FileManager.default.attributesOfItem(atPath: url.path) as NSDictionary
            fileSize = Int(attr.fileSize())
        } catch {
        }
    }
    return fileSize
}

そこで

  • 日付のようにoptionsに設定するだけでソートできるようなメソッド?は用意されているのか
  • ファイルサイズを同期的に取得してソートする方法はあるのか?
  • 上記のようなことをしなくても、他の方法でできるよ!

などご教授いただけたらと思います。

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

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

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

    クリップを取り消します

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

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

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

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

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

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

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

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

    質問の評価を下げる

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

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

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

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

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

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

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

    詳細な説明はこちら

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

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

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

回答 1

checkベストアンサー

0

Photosあまり詳しくは無いですが・・・

日付のようにoptionsに設定するだけでソートできるようなメソッド?は用意されているのか

PHAssetがファイルサイズ情報を持っていないので出来ないかと思います。

ファイルサイズを同期的に取得してソートする方法はあるのか?

あまり良い方法ではなさそうですが、requestImageDataで直Dataをリクエストする際にオプションで同期オプションを指定することができるようです。
https://stackoverflow.com/questions/38348771/phasset-get-filesize-ios

ただ、メモリや動作速度などいろんな効率が悪そうです。
(おそらくautoreleasepoolなどを仕込まないとメモリ枯渇死するのではないかと思われます。)

同期にこだわる必要がなければ、

  1. 非同期でファイルサイズを取り、PHAssetとファイルサイズをタプル等で配列に溜める([(asset: PHAsset, filesize: Int)]型とかで)
  2. すべて取り終わったらファイルサイズを元にソートを行い、画面に反映

などとすれば良いのではないかと思いました。

余談ですが、iCloudなどで同期した画像(端末側には実データが無いもの)とかもありますので、ご注意ください。

投稿

  • 回答の評価を上げる

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

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

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

  • 回答の評価を下げる

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

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

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

  • 2018/11/28 17:23

    解答ありがとうございます。

    私も考えた結果、やはりメモリや動作等で問題が起きそうなので
    おっしゃられている通り、非同期でファイルサイズを取得・保持してソートするようにしようと思います。

    > 余談ですが、iCloudなどで同期した画像(端末側には実データが無いもの)とかもありますので、ご注意ください。
    ありがとうございます!
    今回は端末内のみの画像なので問題ありませんが、使用する際には注意したいと思います。

    キャンセル

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

  • ただいまの回答率 88.64%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

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