どうも、ささおです。
Enumからランダムに値を取得するExtensionを書いていきます。
こちらの記事を参考にさせていただきました。
[Swift]enumでランダムなケースを返すextension
Contents
実装
Sampling というProtocolを作成し、ExtensionにgetSampleというランダムにEnumのcaseを取得する関数を実装します。
protocol Sampling {} extension Sampling where Self: CaseIterable { static func getSample() -> Self { let all = self.allCases as! [Self] let index = Int.random(in: 0...all.count - 1) return all[index] } }
1行ずつ解説
protocol Sampling {}
Samplingプロトコルを定義しています。
extension Sampling where Self: CaseIterable {
Samplingプロトコルのextensionで、
Self(Samplingプロトコルに準拠しているclassやenum)がCaseIterableにも準拠している場合に使えるextensionであることを書いています。
static func getSample() -> Self {
関数getSampleはSelf(Samplingプロトコルに準拠しているclassやenum)を返すことを定義しています。
let all = self.allCases as! [Self]
このextensionはCaseIterableに準拠している物しか使えないので、
extension内でallCasesを使うことができます。
allCasesはenumの全てのcaseを取得してくれます。
しかし、allCasesで取得できる値の型が Collection で、扱いづらいので、as! [Self] で配列にキャストしてあげます。
let index = Int.random(in: 0 … all.count – 1)
Int.randomでランダム値を生成します。
引数に生成する範囲を指定できます。
このような形式です
Int.random(in: 範囲の始め...終わり)
all.count – 1している理由は、配列は0からはじまるからです。
仮にall.count が 4の場合は0 … 3の間で乱数を生成してほしいので1引いています。
実際に使う
今回はBloodTypeというenumを作成しました。
CaseIterableと、Samplingに準拠させます。
enum BloodType: CaseIterable, Sampling { case a case b case o case ab }
あとは、呼び出すだけです。
print(BloodType.getSample())
全体のコード
public protocol Sampling {} extension Sampling where Self: CaseIterable { static func getSample() -> Self { let all = self.allCases as! [Self] let index = Int.random(in: 0...all.count - 1) return all[index] } } enum BloodType: CaseIterable, Sampling { case a case b case o case ab } print(BloodType.getSample())
参考記事
[Swift]enumでランダムなケースを返すextension