staticについて
staticはインスタンスを作成しなくてもアクセスできる「静的プロパティ」と呼ばれます。
実務で使われる場面
よく利用されるのは、アプリ全体で使う設定値や定数の管理です。
例えば長文の文字列を管理したい場合や、変更しないAPIのURLなどがあります。
APIのURL
struct APIConfig {
static let baseURL = "https://api.example.com/v1"
static let apiKey = "API_KEY"
}
使い方
let url = URL(string: "\(APIConfig.baseURL)/user/profile?api_key=\(APIConfig.apiKey)")
「設定値を複数箇所で使い回す」「変更時に全体へ反映したい」
→ static letで管理するのが定石です。
長文の定型文・エラーメッセージの管理
struct ErrorMessages {
static let networkError = """
通信エラーが発生しました。インターネット接続を確認して、もう一度お試しください。
"""
static let serverMaintenance = """
現在サーバーメンテナンス中です。ご迷惑をおかけしますが、しばらくしてから再度アクセスしてください。
"""
}
使い方
※仮のアラート表示関数です
showAlert(title: "エラー", message: ErrorMessages.networkError)
現場では「画面Aと画面Bで同じ文言を使いたい」なんてことがよくあります
→ 重複を避けるためにもstaticが便利です。
実際に使ってみた
以下にstaticプロパティと通常のプロパティを並べて、その違いを確かめてみます。
class SoccerTeam {
var soccerTeamName: String
static let teamColor: String = "Red"
init(soccerTeamName: String) {
self.soccerTeamName = soccerTeamName
}
func redTeamColor() -> String {
return "\(soccerTeamName)のチームカラーは\(SoccerTeam.teamColor)です"
}
}
print(SoccerTeam.teamColor)
let team = SoccerTeam(soccerTeamName: "Arsenal FC")
print(team.redTeamColor())
static関連のエラー⚠️
その1️⃣
Static properties may only be declared on a type
これはstaticを使う場所が間違っている場合に表示されます。
つまり、staticは 「クラス・構造体・列挙型」などの型(Type) の中でしか宣言できません。
例えば、以下のようにクラスの外側で宣言してしまうと発生します。
static let teamColor: String = "Red"
class SoccerTeam {
var soccerTeamName: String
}
その2️⃣
Static property ' ' is not concurrency-safe because it is nonisolated global shared mutable state
グローバルに共有される可変の状態だから、複数スレッドから同時にアクセスされると危険だよ! と警告をされてしまっています。
staticをグローバル変数としてvarで宣言していた場合、他からアクセスされて書換えられてしまうリスクがあると警告されます。
その場合は@MainActorやactorを付与します。これらを付与することで以下のようなメリットが得られます。
- 複数人が同時に同じものをいじって混乱するのを防ぐ
(同時アクセスによるデータの矛盾や壊れを防止) - アクセスは「順番に1人ずつ」または「単独で」行う仕組みを作ることで安全にする
MainActorのパターン
import UIKit
@MainActor
class SoccerTeam {
let name: String
let position: String
var goals: Int = 0
static let soccerTeamName: String = "FC Bayern München"
static var totalGoals: Int = 0
init(name: String, position: String) {
self.name = name
self.position = position
}
func scoreAGoal() {
goals += 1
SoccerTeam.totalGoals += 1
}
}
actorのパターン
import UIKit
actor SoccerTeam {
let name: String
let position: String
var goals: Int = 0
static let soccerTeamName: String = "FC Bayern München"
static var totalGoals: Int = 0
init(name: String, position: String) {
self.name = name
self.position = position
}
func scoreAGoal() {
goals += 1
SoccerTeam.totalGoals += 1
}
}
まとめ
staticは共通言語の設定など汎用性が高く大変便利なプロパティです。
使い勝手がいいので実務でもよく利用するため、しっかり理解し活用しようと思います