【Swift】よく見る『.shared』・シングルトンの意味

公開日: 

はじめに

let foo = Hoge.shared  // いやsharedってなに

このようなsharedを使った実装を見たことがある人は多いかもしれません。

これは大体の場合、シングルトンというデザインパターンに基づいて実装されています。

『シングルトン』とは

シングルトンとは簡単にいうと

インスタンスが”1 つ”しか生成されないことが保証されているクラス

です。簡単な例だと、

sample.swift
// シングルトンの例
class SingletonExample {

  // インスタンスを参照するためのプロパティ
  static let shared = SingletonExample()

  // 適当なプロパティ
  var greeting: String = "おはよう"

  // privateなイニシャライザ
  private init() {}
}

// シングルトンを参照①
let hoge = SingletonExample.shared

print(hoge.greeting) // "おはよう"

// シングルトンを参照②
let fuga = SingletonExample.shared

// シングルトンのプロパティを変更
fuga.greeting = "hello"

print(hoge.greeting) // "hello"

こんな感じ。

普通のクラスのようにインスタンスを生成しようとしてもイニシャライザがprivateなので、エラーが出てしまいます。

なので、シングルトンのインスタンスを参照するにはsharedプロパティを用いて、”1 つ”のインスタンスを参照するしかありません。

参照するためのプロパティの名前はなんでもいいですが、シングルトンパターンだということがわかりやすいようにsharedという名前をつける慣習があるようです。

インスタンスが”1 つ”しか生成されないことが保証されているわけですね。

いつ使うの?

シングルトンがどういうものかは理解したとしても、結局一番知りたいのは使う場面。

結論から言いますと、シングルトン不要論みたいなのもあるらしく、そんなに頻出で絶対に必要なものではありません。

というのも、前回の記事で書いたstaticキーワードで代用できる場合が多いです。

https://www.yukendev.com/blogs/swift-static

  • インスタンスが 1 つしかないことを保証する
  • インスタンス化せずにプロパティやメソッドを使う

この二つは無駄なインスタンスを生成しないという点で似ている概念です。自分のインターン先のコードでは、下のコードのように UserDefaults を使うときにシングルトンが使われていました。

sample.swift
final class SingletonUserDefaults {

  static var shared = SingletonUserDefaults()

  private init() {}

  private lazy var userDefaults = UserDefaults.standard


  var mailAddress: String {
      get {
          return userDefaults.string(forKey: "MailAddress") ?? ""
      }
      set(value) {
          userDefaults.set(value, forKey: "MailAddress")
      }
  }
}

// 呼び出し
let UD = SingletonUserDefaults.shared

print(UD.mailAddress)

先輩のエンジニアになぜここでシングルトンを採用したのか聞いてみたところ、

「使用箇所が多くてその都度インスタンス化していたらメモリが勿体無かったからですね。」

とのこと。また、

「変数を全部 static にすれば、シングルトンじゃなくても実装できますよ。」

とも言っていました。やっぱり、シングルトンと static は割と似ているんですね。なので自分はやっぱり

staticでいいんじゃないか??

ってなってしまいます。そこら辺を詳しく知りたい方は、こちらの記事がわかりやすかったです。

https://medium.com/swift-column/singleton-398078bcc58d

まとめ

シングルトンとはインスタンスが”1 つ”しか生成されないことを保証されているクラスである。

でも、大体の場合staticを使って置き換えることができるのでstaticでよくね?ってなりました。この記事はあくまで僕が自分で調べたり、ソースコードを見て学んだことのアウトプットなので間違っていたり、もっと魅力的なシングルトンの使い方があるかもしれません。その場合は、教えていただけるとありがたいです。

では

Bye