開発メモ

開発関係のメモをいろいろと。たぶん。

シャッフルに対応

動作を確認した環境

環境 情報
Xcode 6.3.2 (6D2105)
iOS 8.3
Swift 1.2
Date 2015/6/7

シャッフルに対応

完全に忘れてたシャッフル関係の処理に対応。

シャッフルする前とあとの両方のプレイリストを管理するのも面倒なので、そもそものプレイリストを作成する部分でシャッフルに対応。MPMusicPlayerControllerの管理クラスでは、シャッフル関係のフラグだけを保存するようにしてみた。

class MusicPlayerAdmin: SK4MusicPlayerAdmin {

    /// プレイリストを更新
    func updatePlaylist() {
        let query = MPMediaQuery.songsQuery()

        // クラウドにあるアイテムを除外
        let num = NSNumber(bool: false)
        let pre = MPMediaPropertyPredicate(value: num, forProperty: MPMediaItemPropertyIsCloudItem)
        query.addFilterPredicate(pre)

        if var all_ar = query.items as? [MPMediaItem] {

            // 再生回数と曲名でソート
            all_ar.sort() { s0, s1 in
                if s0.playCount == s1.playCount {

                    // FIXME: 間違ってはいないが正しくもない

                    return s0.title < s1.title

                } else {
                    return s0.playCount < s1.playCount
                }
            }

            // 最大で100件取り出し
            let no = min(100, all_ar.count)
            var ar = [MPMediaItem](all_ar[0..<no])

            // 必要ならプレイリストをシャッフル
            if shuffleFlag {
                shufflePlaylist(&ar)
            }

            playlist = ar
        }
    }

    /// プレイリストをシャッフル
    func shufflePlaylist(inout array: [MPMediaItem]) {
        let max = array.count
        for no in (0...max*2) {
            let i = no % max
            let j = Int(arc4random_uniform(UInt32(max)))
            if i != j {
                swap(&array[i], &array[j])
            }
        }
    }

    ※関係ない部分は省略
}

単純に、フラグがtrueなら配列をシャッフルするようにしてるだけ。

shufflePlaylist()でやってるのは、配列をシャッフルする処理の定番的な処理。さり気なく実行回数が多いのは、単純に好みの問題。本当は、Genericsでどんな配列でも使えるようにするべき。

ユーザーが状態を切り替える部分はこんな感じ。

class ViewController: UIViewController {

    @IBAction func onShuffle(sender: AnyObject) {

        // シャッフルのフラグを反転
        let flag = g_musicPlayer.shuffleFlag
        g_musicPlayer.shuffleFlag = !flag

        // プレイリストを更新
        g_musicPlayer.updatePlaylist()

        // 画面を更新
        updateOperation()
    }

    ※関係ない部分は省略
}

プレイリストの更新を呼んでる以外は、リピートの処理と同じ。もちろん、画面の更新もリピートと同じ事をやってるだけ。実際に動かしてみるとこんな感じになる。

シャッフルする前。

f:id:see_ku:20150607124754p:plain

シャッフルした後。

f:id:see_ku:20150607124805p:plain

元々、プレイリストを作成する基準が再生回数なので、シャッフルの有効/無効がわかりにくすぎる問題が・・・

終わりに

ミュージックプレイヤーとして、基本的な機能はひと通りそろったんじゃないかな?

あとは、もう少し凝ったGUIを用意して、プレイリストを作成する部分を独自のものにすれば、オリジナルのミュージックプレイヤーが完成するはず。たぶん

ソースコード

最終的なソースコードはこちら。

See_Ku / MusicPlayerTips — Bitbucket
https://bitbucket.org/See_Ku/musicplayertips

https://itunes.apple.com/jp/app/four-album-shuffle-arubamu/id866046150?mt=8&uo=4&at=10l8JW&ct=hatenablog