Protocolを学んでいく上で、AssociatedTypeがなんなのかわからなかったため、メモ程度にここに記述。
AssociatedTypeとは?
Swiftでよく使うGenericsと同じように、Protocol内で定義する連想型のこと!
準拠時にどんな型にするかを指定することができる。
具体例
なんらかのAPIを叩く際!
まずは、protocolから定義!
APIRepository
protocol APIConfigure {
associatedtype ResponseEntity: Codable
static var path: String { get }
static func request(completion: ((ResponseEntity) -> ())?)
}
protocolにextensionを生やす!
APIRepository
extension APIConfigure {
static func request(completion: ((ResponseEntity) -> ())?) {
guard let url = URL(string: Self.path) else { return }
let task = URLSession.shared.dataTask(with: url) { data, _, _ in
guard let data = data, let responseEntity = try? JSONDecoder().decode(ResponseEntity.self, from: data) else {
return
}
completion?(responseEntity)
}
task.resume()
}
}
protocolに準拠したstructを作成する(structの中身は適当に作りました。)
APIClient
public struct APIClient {
struct UserGet: APIConfigure {
typealias ResponseEntity = User
static let path = "https://qiita.com/api/v2/users/anies1212"
}
struct ItemsGet: APIConfigure {
typealias ResponseEntity = [Item]
static let path = "https://qiita.com/api/v2/items"
}
}
struct User: Codable {
let name: String
init(name: String) {
self.name = name
}
}
struct Item: Codable {
let name: String
init(name: String) {
self.name = name
}
}
ViewControllerで実際に呼び出してみる!!
ViewController
class ViewController: UIViewController {
private let userNameLabel: UILabel = {
let label = UILabel()
label.textColor = .label
label.font = .systemFont(ofSize: 12, weight: .semibold)
label.textAlignment = .center
return label
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(userNameLabel)
getResponse()
view.backgroundColor = .white
}
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
userNameLabel.frame = CGRect(x: 0, y: 100, width: view.bounds.width, height: 50)
}
private func getResponse(){
APIClient.UserGet.request {[weak self] user in
DispatchQueue.main.async {
self?.userNameLabel.text = user.name
}
}
}
}
思ったこと
private func getResponse(){
APIClient.UserGet.request {[weak self] user in
DispatchQueue.main.async {
self?.userNameLabel.text = user.name
}
}
}
ViewController内でこんだけでレスポンスを呼べるのはとても便利だなと感じた。
protocolにassociatedTypeを持たせてあげるだけで、CodableなEntityである限り、なんでも共通のメソッドでレスポンスを呼べる!!