UserDefaultsを初期化する
UserDefaults を初期化するためには
if let bundleId = Bundle.main.bundleIdentifier { UserDefaults.standard.removePersistentDomain(forName: bundleId) }
persistentDomain(forName:)で domainNameで指定した、KeyとValueのディクショナリーが受け取れる。
domainNameをBundleIdentiferに指定することで、アプリ内すべてのKeyとValueが得られる
iOSで使いにくいUserDefaultをなんとかする
はじめに
iOSアプリにおいて、アプリを消しても値を保存しておける、UserDefaultはとても便利だと思う。 しかしながら、どうしても使いにくい部分が存在する。 例えば、UserDefaultの値を取り出すKeyがStringなところだ。
よくある使い方
// 保存する UserDefaults.standard.set("sample", forKey: "sampleKey") UserDefaults.standard.synchronize() // とりだす var str = UserDefaults.standard.string(forKey: "sampleKey")
- Key値をタイポすると実行時まで築くことができない
- stored propertyのように使用したい
stored propertyのように振る舞うために
前準備
class DefaultsKeys { static let sampleKey = DefaultsKey<String>("sampleKey") private init() {} } class DefaultsKey<ValueType>: DefaultsKeys { let key: String init(_ key: String) { self.key = key } } extension UserDefaults { subscript(key: DefaultsKey<String>) -> String { get { if let value = string(forKey: key.key) { return value } else { return "" } } set { set(newValue,forkey: key.key) synchronize() } } }
使い方
UserDefaults.standard[.sampleKey] = "sample" let str = UserDefaults.standard[.sampleKey]
その他
- static let sampleKey のところを増やすことでKeyを増やせる
- subscript を増やせばString以外にも対応可能
- DefalutsKeyとDefaultsKeysを統合したかったのですが、staticプロパティはGenericタイプに対応していない。
おわりに
なんとかスッキリと利用することができるようになったので満足。
参考URL
レガシーコード改善を読んで
クラスをテストにしやすくするには
1. クラス間の依存性を下げる。
2. 他のクラスを使用する場合、そのやりとりをプロトコルで定義することで、テスト用のモックと振替可能にする。
1. クラス間の依存性を下げる
クラスをテストする上で、大変になってくるのは、テスト対象のクラスを個別で生成•使用することが難しくなこと。
あるクラスが他のクラスを参照している場合、そのクラスをテストするためには他のクラスも生成しなければならない。他のクラスもまた別のクラスを参照するとかになると、どんどん話はややこしくなっていく。
では、どうするのか。
一番良いのはクラスが他のクラスに依存しなくても成立するようにすることだ。しかし、それが困難な場合もある。
その場合、必要に応じて他のクラスの情報を渡すのが良いだろう。インスタンス生成時のイニシャライザやメソッドの引数にその情報を渡すのだ。
引数と渡すとこで、テスト時にはその引数をテスト用クラスに差し替えることが可能となる。
2. 他のクラスとのやりとりをプロトコルで定義する。
1. の話の続きとして、1.では引数で他のクラスとの依存性注入すると書いた。
今度は、依存される側のクラスをテストクラスに差し替えることを考えよう。
依存される側とクラスをどうやって、テストクラスに差し替えるか。
そこで利用するのがプロトコルである。プロトコルで、依存する側が必要とする処理を定義しておき、依存される側がそのプロトコルに則って実装する。
こうすることで、依存される側をテストクラスに差し替える場合、プロトコルで定義されたメソッドのみをテスト用に書くだけで良い。
後は、イニシャライザやメソッドの引数としてテスト用クラスを渡すことで、テストを実施することができる。
追記(2017/4/22)
イニシャライザの引数にすべてのクラスを渡すのは困難。
渡されるクラスがないと、生成されるクラスが存在できない場合、依存が高い場合はイニシャライザの引数として渡す。
クラス生成後に状態のように後から別のクラスをSetする場合は、イニシャライザで渡したり、メンバ変数に参照を渡すよりも、setメソッドを定義したほうがよさそう。
テスト時もsetメソッドにダミーのテストを渡せるように。
メンバ変数を直接いじるは、カプセル化的にもよくない。
もちろん、setメソッドではプロトコルでsetできるようにしておくのがベスト。
レガシーコード改善ガイド (Object Oriented SELECTION)
- 作者: マイケル・C・フェザーズ,ウルシステムズ株式会社,平澤章,越智典子,稲葉信之,田村友彦,小堀真義
- 出版社/メーカー: 翔泳社
- 発売日: 2009/07/14
- メディア: 大型本
- 購入: 45人 クリック: 673回
- この商品を含むブログ (157件) を見る