SwiftUIでシングルトンクラスを作る方法です。
シングルトンクラスとは、アプリ内で一意に存在するクラスのことで、アプリ内のどこからアクセスしてもただ一つのインスタンスを返します。
EnvironmentObjectとの違い
SwiftUIには、EnvironmentObjectという、どこのViewからアクセスしても同じインスタンスを参照できるプロパティラッパがありますが、あえてシングルトンクラスを作る理由はなんでしょう。
それは、View以外からも参照したいからです。
EnvironmentObjectは、Viewを継承したビュー構造体にしか定義できません。
MVVMで開発している場合で言えば、Model、あるいはViewModelからEnvironmentObjectのインスタンスにアクセスしたいことが出てくるでしょう。そんな時に解決してくれるのがシングルトンクラスです。
実装
以下のように定義します。
class Singleton{
static var shared = Singleton()
var hoge = "hoge"
}
Viewから呼んでみましょう。
struct ContentView: View {
var body: some View {
Text("hoge")
.onAppear(){
print(Singleton.shared.hoge)
}
}
}
結果
hoge
EnvironmentObject×Singleton
EnvironmentObjectとしても使えるようにするには、ObservableObjectに準拠させれば良いです。
class Singleton: ObservableObject{
static var shared = Singleton()
@Published var hoge = "hoge"
}
mainスレッドで、EnvironmentObjectとして登録します。
@main
struct FuerMoneyNextApp: App {
let persistenceController = PersistenceController.shared
var body: some Scene {
WindowGroup {
ContentView()
.environment(\.managedObjectContext, persistenceController.container.viewContext)
.environmentObject(Singleton.shared)
}
}
}
こうすれば、Viewで呼び出したSingletonクラスが更新された際には、自動で再描画してくれます。
今度はEnvironmentObjectとして、Viewで呼び出してみましょう。
struct ContentView: View {
@EnvironmentObject var env: Singleton
var body: some View {
Text("hoge")
.onAppear(){
print(env.hoge)
}
}
}
結果
hoge
ViewModelから呼び出す場合はSingleton.sharedです。
struct ContentView: View {
@ObservedObject var vm = ContentViewModel()
var body: some View {
Text("hoge")
.onAppear(){
vm.callHoge()
}
}
}
class ContentViewModel: ObservableObject{
func callHoge(){
print(Singleton.shared.hoge)
}
}
結果
hoge
超簡単なコードで、両方の使い方ができるので便利です。
終わり