LoginSignup
0
2

More than 1 year has passed since last update.

NCMBのSwift SDKを使ったランキング機能に日付絞り込み機能を追加する

Last updated at Posted at 2021-09-07

先日、NCMBのSwift SDKを使ってゲームのランキング機能を実装する - Qiitaという記事をアップしましたが、その後こんなツイートを拝見しました。

ランキングを時間軸で絞り込むことで、今月のランキングや先週のランキングなどを実現します。確かに、圧倒的な順位の人が君臨してしまうとやる気をなくしそうですが、週間ランキングなどがあれば順位変動が激しくて良さそうです。

ということで、Swift SDKを使ったランキング機能にも、過去30日と7日間でランキングを絞り込めるようにしてみました。この実装はNCMBのSwift SDKを使ってゲームのランキング機能を実装する - Qiitaを前提としています。また、コードはGitHub - NCMBMania/Swift_Ranking_Demo: Swift SDKを使って実装したランキング機能のデモですにアップしてあります。

ScreenShot_ 2021-09-07 15.18.36.png

変更点について

まずEnumで時間のレンジを定義しています。

enum RankingRange {
    case All, Month, Week
}

そしてボタンを追加して、それぞれレンジを引数に送るようにします。

Button("過去30日", action: {
    getRanking(range: RankingRange.Month)
})
Button("過去7日", action: {
    getRanking(range: RankingRange.Week)
})
if rankings.count > 0 {
    List {
        ForEach(Array(rankings.enumerated()), id: \.offset) { i, ranking in
            Text(listString(index: i, ranking: ranking))
        }
    }
}
func listString(index: Int, ranking: NCMBObject) -> String {
    let displayName: String = ranking["displayName"] ?? ""
    let score: Int = ranking["score"] ?? 0
    return "\(index + 1)\(displayName)さん (\(score)点)"
}

ランキングの取得

ランキングの取得時には、指定されたレンジに応じて日時オブジェクトを作成しています。

func getRanking(range: RankingRange = .All) {
    var date: Date?
    let calendar = Calendar.current
    let today = Date()

    switch range {
    case .Month:
        date = calendar.date(byAdding: .day, value: -30, to: today)
        break
    case .Week:
        date = calendar.date(byAdding: .day, value: -7, to: today)
        break
    default:
        break
    }
    // 下に続く

そして、日付が指定されている場合のみ greaterThanOrEqualTo を使って指定された日付以降のデータだけを対象とする絞り込みを行っています。

    // ランキングデータ検索用のクエリオブジェクトを作成
    var query = NCMBQuery.getQuery(className: "Ranking")
    // 並び順はスコアの高い順です
    query.order = ["-score"]
    // 100件のデータを取得します
    query.limit = 100
    // 日付が指定されていれば、その日以降のデータに限定する
    if date != nil {
        query.where(field: "createDate", greaterThanOrEqualTo: date!)
    }
    // 検索実行
    let results = query.find()
    switch results {
    case let .success(ary):
        // 検索成功したら、それをrankingsに適用します
        rankings = ary
    case .failure(_): break
    }
}

表示時の注意

ランキングの内容が変わるので、 rankings.indice だとうまく反映されませんでした(最初に10件表示していると、次に2件に変わった時にも最初にi = 10になってしまう)。そこで、以下のようにForEachの内容を変えています。

// 元
List {
  ForEach(rankings.indices) { i in
      Text(listString(index: i))
  }
}

// 変更後
List {
    ForEach(Array(rankings.enumerated()), id: \.offset) { i, ranking in
        Text(listString(index: i, ranking: ranking))
    }
}

これに伴ってlistStringも多少変わっています。

// ランキングの順位、ゲームユーザ名、スコアを返します
func listString(index: Int, ranking: NCMBObject) -> String {
    let displayName: String = ranking["displayName"] ?? ""
    let score: Int = ranking["score"] ?? 0
    return "\(index + 1)\(displayName)さん (\(score)点)"
}

まとめ

NCMBの以上、以下と言った検索のオペランドを使うことで、指定日以降のランキングを作ったり、先月だけのランキングを作ると言ったことも簡単に実現できます。ぜひSwiftを使ったゲーム開発に活かしてください。

ドキュメント : 開発者向けドキュメント | ニフクラ mobile backend

0
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
2