Swiftでアプリ開発を学んでいると、「enum」という言葉に出会うことがあります。この記事では、Swiftのenumについて、プログラミング初心者の方にもわかりやすく解説します。
目次
Swiftのenumとは?
enumは「列挙型(れっきょがた)」の略で、関連する選択肢のグループを定義するためのデータ型です。
例えば、曜日を表現する場合、7つの選択肢しかありません。このような「限定された選択肢」を扱うときにenumが活躍します。
enum Weekday {
case monday
case tuesday
case wednesday
case thursday
case friday
case saturday
case sunday
}
なぜenumを使うのか?
enumを使わない場合、文字列や数値で状態を表現することになります。
// enumを使わない場合(推奨されない)
let status = "success" // タイプミスのリスクがある
if status == "succes" { // スペルミス!でもエラーにならない
print("成功")
}
enumを使えば、このような問題を防げます。
// enumを使う場合(推奨)
enum Status {
case success
case failure
}
let status = Status.success
if status == Status.succes { // コンパイルエラーになる
print("成功")
}
enumの基本的な書き方
enumは以下のような構文で定義します。
enum 列挙型名 {
case 選択肢1
case 選択肢2
case 選択肢3
}
// または1行で書くこともできる
enum 列挙型名 {
case 選択肢1, 選択肢2, 選択肢3
}
実際の例を見てみましょう。
enum Direction {
case north, south, east, west
}
// 使用例
var currentDirection = Direction.north
currentDirection = .south // 型が明確な場合は省略記法が使える
print(currentDirection) // south
enumとswitch文の組み合わせ
enumはswitch文と相性が抜群です。すべてのcaseを網羅しないとコンパイルエラーになるため、安全なコードが書けます。
enum TrafficLight {
case red, yellow, green
}
let light = TrafficLight.red
switch light {
case .red:
print("止まれ")
case .yellow:
print("注意")
case .green:
print("進め")
}
// すべてのcaseを処理しているのでOK
もし1つでもcaseが抜けていると、コンパイルエラーになります。
enumの便利な機能
1. 生の値(Raw Values)
enumの各caseに、整数や文字列などの「生の値」を関連付けることができます。
enum Planet: Int {
case mercury = 1
case venus = 2
case earth = 3
case mars = 4
}
print(Planet.earth.rawValue) // 3
// 生の値から列挙型を作成
if let planet = Planet(rawValue: 2) {
print(planet) // venus
}
文字列の生の値も使えます。
enum ErrorCode: String {
case notFound = "404"
case serverError = "500"
case unauthorized = "401"
}
print(ErrorCode.notFound.rawValue) // "404"
2. 関連値(Associated Values)
各caseに異なる型の値を関連付けることができます。これがSwiftのenumの強力な機能です。
enum Barcode {
case upc(Int, Int, Int, Int)
case qrCode(String)
}
// 使用例
var productBarcode = Barcode.upc(8, 85909, 51226, 3)
productBarcode = .qrCode("ABCDEFGHIJKLMNOP")
switch productBarcode {
case .upc(let numberSystem, let manufacturer, let product, let check):
print("UPC: \(numberSystem), \(manufacturer), \(product), \(check)")
case .qrCode(let code):
print("QRコード: \(code)")
}
// 出力:QRコード: ABCDEFGHIJKLMNOP
3. メソッドとプロパティ
enumにもメソッドやcomputed propertyを追加できます。
enum CompassPoint {
case north, south, east, west
// メソッドの追加
func description() -> String {
switch self {
case .north:
return "北"
case .south:
return "南"
case .east:
return "東"
case .west:
return "西"
}
}
// computed propertyの追加
var symbol: String {
switch self {
case .north:
return "↑"
case .south:
return "↓"
case .east:
return "→"
case .west:
return "←"
}
}
}
let direction = CompassPoint.north
print(direction.description()) // 北
print(direction.symbol) // ↑
実践的なenumの使用例
例1:APIレスポンスの状態管理
enum NetworkResult {
case success(data: String)
case failure(error: String)
case loading
}
func handleResponse(result: NetworkResult) {
switch result {
case .success(let data):
print("データ取得成功: \(data)")
case .failure(let error):
print("エラー: \(error)")
case .loading:
print("読み込み中...")
}
}
// 使用例
let response = NetworkResult.success(data: "ユーザー情報")
handleResponse(result: response)
// 出力:データ取得成功: ユーザー情報
例2:アプリの画面遷移管理
enum Screen {
case home
case profile(userId: String)
case settings
case detail(itemId: Int)
func navigate() {
switch self {
case .home:
print("ホーム画面を表示")
case .profile(let userId):
print("ユーザーID \(userId) のプロフィールを表示")
case .settings:
print("設定画面を表示")
case .detail(let itemId):
print("アイテムID \(itemId) の詳細を表示")
}
}
}
let screen = Screen.profile(userId: "user123")
screen.navigate()
// 出力:ユーザーID user123 のプロフィールを表示
例3:ゲームのキャラクター状態管理
enum CharacterState {
case idle
case walking(speed: Double)
case running(speed: Double)
case jumping(height: Double)
case attacking(damage: Int)
var description: String {
switch self {
case .idle:
return "待機中"
case .walking(let speed):
return "歩行中(速度: \(speed))"
case .running(let speed):
return "走行中(速度: \(speed))"
case .jumping(let height):
return "ジャンプ中(高さ: \(height))"
case .attacking(let damage):
return "攻撃中(ダメージ: \(damage))"
}
}
}
var playerState = CharacterState.idle
print(playerState.description) // 待機中
playerState = .running(speed: 8.5)
print(playerState.description) // 走行中(速度: 8.5)
enumとstructの使い分け
enumとstructは用途が異なります。
特徴 | enum | struct |
---|---|---|
用途 | 限定された選択肢を表現 | 関連するデータをまとめる |
値 | 決まった選択肢の中から1つ | 複数のプロパティを持つ |
適した場面 | 状態、モード、カテゴリーなど | データモデル、座標、設定など |
使い分けの例
// enumを使う場合:選択肢が限定されている
enum PaymentMethod {
case creditCard
case bankTransfer
case cash
}
// structを使う場合:複数のデータを持つ
struct User {
var name: String
var age: Int
var email: String
}
enumを使うメリット
- 型安全性が高い:存在しない値を指定できないため、バグを防げます
- 可読性が向上する:コードの意図が明確になります
- コンパイラのサポート:switch文で全caseを網羅していないとエラーになります
- リファクタリングが容易:caseを追加・変更すると、該当箇所が自動的に検出されます
- 柔軟性が高い:関連値を使うことで、複雑な状態管理も可能です
よくある間違いと注意点
間違い1:enumを使うべき場所でstructを使う
// 良くない例
struct Status {
static let success = "success"
static let failure = "failure"
}
// 良い例
enum Status {
case success
case failure
}
間違い2:生の値と関連値を混同する
生の値と関連値は同時に使えません。どちらか一方を選択します。
// エラー:生の値と関連値は同時に使えない
enum Example: Int {
case option1(value: String) = 1 // コンパイルエラー
}
まとめ
Swiftのenumは、限定された選択肢を安全に扱うための強力な機能です。以下のポイントを覚えておきましょう。
- enumは関連する選択肢のグループを定義する
- switch文との相性が良く、安全なコードが書ける
- 生の値で整数や文字列を関連付けられる
- 関連値で各caseに異なるデータを持たせられる
- メソッドやプロパティも追加できる
- 状態管理やモード切り替えに最適
enumをマスターすることで、バグの少ない保守しやすいSwiftコードが書けるようになります。ぜひ実際のプロジェクトで活用してみてください。