環境
- Xcode 14.2
Settings.bundleを追加
「File」→「New」→「File...」から「Settings Bundle」を選択する
Root.plistの変更
Configファイルを作成
- UserDefaultに保存するソースコードを追加する
UserDefaultConfig.swift
import Foundation
@propertyWrapper
struct UserDefault<T> {
let key: String
let defaultValue: T
var wrappedValue: T {
get {
UserDefaults.standard.object(forKey: key) as? T ?? defaultValue
}
set {
UserDefaults.standard.set(newValue, forKey: key)
}
}
}
enum UserDefaultConfig {
// UserdefaultのkeyはPreference Itemsで設定したIdentifierにする
@UserDefault(key: "IS_STUB", defaultValue: false)
static var isStub: Bool
}
UserDefaultの値によって処理を切り分ける
例)レスポンスでStubを返すか、そのままAPIに投げる
LoginModel
import Foundation
protocol LoginModelInput: AnyObject {
func login(loginInfo: LoginInfo) async throws -> LoginResponse
}
class LoginModel: LoginModelInput {
func login(loginInfo: LoginInfo) async throws -> LoginResponse {
if UserDefaultConfig.isStub {
StubURLProtocol.requestHandler = { request in
let response = HTTPURLResponse(
url: request.url!, statusCode: 200, httpVersion: "HTTP/2", headerFields: [:]
)!
guard
let jsonDataURL = Bundle.main.url(forResource: "sample", withExtension: "json"),
let jsonData = try? String(contentsOf: jsonDataURL)
else {
fatalError("sample.json not found")
}
let data = jsonData.data(using: .utf8)
return (response, data)
}
// URLSession を作る
let config = URLSessionConfiguration.default
config.protocolClasses = [StubURLProtocol.self]
let session = URLSession(configuration: config)
// APIClient を作る
let client = APIClient(session: session)
// request 投げる
let request = LoginInfoRequest(logInfo: loginInfo)
let response = try await client.send(request)
return response
} else {
do {
let request = LoginInfoRequest(logInfo: loginInfo)
let response = try await APIClient().send(request)
return response
} catch APIError.networkError {
fatalError("ネットワークエラー")
} catch APIError.decodingError {
fatalError("デコードエラー")
}
}
}
}
注意点
このままだとリリースビルドをした際にも開発用のパラメータが出てしまうため、Active Compilation Conditionsを用いて、Build Phaseの一番最後にRelese Buildの際にはSettings.bundleを削除するScriptを作成する必要がある