์ผ | ์ | ํ | ์ | ๋ชฉ | ๊ธ | ํ |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | 6 | |
7 | 8 | 9 | 10 | 11 | 12 | 13 |
14 | 15 | 16 | 17 | 18 | 19 | 20 |
21 | 22 | 23 | 24 | 25 | 26 | 27 |
28 | 29 | 30 | 31 |
- ํจ์คํธ์บ ํผ์ค
- Xcode
- swift
- Lv2
- ๋ฐฑ์ค
- XCTest
- Flutter
- reactorkit
- realm
- node.js
- BOJ
- SwiftUI
- Swfit
- MVVM
- TCA
- designpattern
- SnapKit
- tableView
- Kuring
- raywenderlich
- ios
- ํ๋ก๊ทธ๋๋จธ์ค
- BFS
- UIKit
- rxcocoa
- CollectionView
- RxSwift
- arkit
- visionOS
- combine
- Today
- Total
lgvv98
[Combine] Networking(feat. RestAPI) ๋ณธ๋ฌธ
Networking(feat. RestAPI)
Combine์ ํ์ฉํด์ ์ฝ๊ฒ ์๋ฒ์ ํต์ ์ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
์ด ๊ธ์ ์ ์ผ ์๋ ๋ถ๋ถ์์๋ MVVM์ ๋ํ ๊ณ ์ฐฐ๋ ๋ค์ด ์์ต๋๋ค.
๋์ด๋๋ ์ด 3๊ฐ์ง๋ก ๋๋์ด ์์ต๋๋ค. ํ์ผ์ ํ์ธํด์ฃผ์ธ์!
์ด ํฌ์คํ ์์๋ Refactoring(์)๊ณผ Advanced Model์ ๋ํด์๋ง ์ค๋ช ํฉ๋๋ค.
์์ธํ ์ฝ๋๋ ์๋ ์ฒจ๋ถ ํ์ผ์ ํ์ธํด์ฃผ์ธ์!!!
๐ฅ ๋ชฉ์ฐจ ๐ฅ
1. Refactoring (์)
2. MVVM์ ๋ํ ๊ณ ์ฐฐ(Combine ํ๋ฌ์ฐจ,, 2022.06.11)
๐ ๋ชจ๋ธ
//
// UserModel.swift
// CombineNetworking
//
// Created by Hamlit Jason on 2022/06/10.
//
// let user = try? newJSONDecoder().decode(User.self, from: jsonData)
import Foundation
// MARK: - UserElement
struct UserElement: Codable, Hashable {
let id: Int
let name, username, email: String
let address: Address
let phone, website: String
let company: Company
static func == (lhs: UserElement, rhs: UserElement) -> Bool {
return lhs.name == rhs.name && lhs.username == rhs.username
}
}
// MARK: - Address
struct Address: Codable, Hashable {
let street, suite, city, zipcode: String
let geo: Geo
static func == (lhs: Address, rhs: Address) -> Bool {
return lhs.street == rhs.street
}
}
// MARK: - Geo
struct Geo: Codable, Hashable {
let lat, lng: String
}
// MARK: - Company
struct Company: Codable, Hashable {
let name, catchPhrase, bs: String
}
typealias User = [UserElement]
๋ชจ๋ธ์์ ์ฃผ๋ชฉํด์ผ ํ๋ ๋ถ๋ถ์ Hashable์ ๋๋ค. ์ด ๋ถ๋ถ์ ์ฑํํด์ผ์ง ๋น๊ต๊ฐ ๊ฐ๋ฅํ๊ธฐ ๋๋ฌธ์ Hashable์ ์์๋ฐ๊ณ ๊ตฌํํฉ๋๋ค. == ๋ฉ์๋ ์์์ ๊ตฌํํ๋๋ฐ, ๋จ์ํ ์์ ๋ผ์ ์ ๋ง ํ๋์ ์์ฑ๋ง ๋ง์ผ๋ฉด ๊ฐ๋ค๊ณ ํ๋จํ๊ฒ ์ค์ ํ์์ต๋๋ค.
๐ ๋ทฐ
//
// RefactoringView.swift
// CombineNetworking
//
// Created by Hamlit Jason on 2022/06/11.
//
import SwiftUI
struct RefactoringView: View {
@EnvironmentObject var engine: RefactoringEngine
var body: some View {
NavigationView {
VStack {
HStack {
Image(systemName: "magnifyingglass")
.foregroundColor(Color.green)
TextField("", text: $engine.typing, onCommit: {
engine.input = engine.typing
})
}
.padding(.horizontal, 20)
.frame(height: 40)
.background(
RoundedRectangle(cornerRadius: 20)
.stroke(Color.green, lineWidth: 1)
)
.padding([.horizontal, .top], 16)
.padding(.bottom, 10)
Spacer()
List {
ForEach(engine.users, id: \.self) { user in
Text("idํํฐ๋ง ์์!: \(user.id)")
}
.listStyle(.plain)
}
.navigationBarTitleDisplayMode(.inline)
.toolbar {
ToolbarItem(placement: .principal) {
Text("๋ฆฌํฉํ ๋ง์์ง ์ฅ์ฐฉ!")
}
}
}
}
}
}
view ๋ถ๋ถ์ ๋๋ค. ํน๋ณํ ์ ์ ์์ต๋๋ค.
๋ค๋ง ๋ค๋น๊ฒ์ด์ ๋ทฐ๋ฅผ ์ค์ ํ ๋ navigationBarTitleDisplayMode๋ฅผ ์ง์ ํด์ฃผ์ง ์์ผ๋ฉด, ์ฐ๋ฆฌ๊ฐ ์ํ ๊ฐ๋ณด๋ค ํฐ ์์ญ์ผ๋ก ๋ค๋น๊ฒ์ด์ ๋ทฐ๋ฅผ ์ฐจ์งํด์ ์ํ๋ ๊ฒฐ๊ณผ๊ฐ ์๋ ์ ์์ต๋๋ค.
๐ ์์ง
//
// RefactoringEngine.swift
// CombineNetworking
//
// Created by Hamlit Jason on 2022/06/11.
//
// ๊ณ ๊ธ json: https://jsonplaceholder.typicode.com/users
import Combine
import SwiftUI
class RefactoringEngine: ObservableObject {
static let urlString = "https://jsonplaceholder.typicode.com/users"
@Published var users: User = []
var cancleables = Set<AnyCancellable>()
@Published var typing: String = ""
@Published var input: String = "" {
didSet {
send(filterId: Int(input))
}
}
init() {
send()
}
func send(filterId: Int? = nil) {
guard let url = URL(string: RefactoringEngine.urlString) else { return }
URLSession.shared.dataTaskPublisher(for: url)
.subscribe(on: DispatchQueue.global(qos: .background))
.receive(on: DispatchQueue.main)
.tryMap(handleOutput)
.decode(type: User.self, decoder: JSONDecoder())
.map { users in
return users.filter { user in
user.id != filterId
}
}
.sink { completion in
print("โ
completion \(completion)")
} receiveValue: { [weak self] responseElements in
print("โ
responseElements \(responseElements)")
self?.users = responseElements
}
.store(in: &cancleables)
}
func handleOutput(output: URLSession.DataTaskPublisher.Output) throws -> Data {
print("โ
\(#function)")
guard
let response = output.response as? HTTPURLResponse,
(200..<300) ~= response.statusCode else {
print("โ
\(#function) guard์ ๊ฑธ๋ ธ์ต๋๋ค.")
throw URLError(.badServerResponse)
}
print("โ
\(#function) guard๋ฅผ ํ์ถํ์ต๋๋ค.")
return output.data
}
}
์ฌ๊ธฐ๋์๋ ๊ทธ๋ฆฌ ์ด๋ ต์ง ์๊ฒ ์ฒ๋ฆฌํ๊ณ ์์ต๋๋ค. ํด๋น ์ฝ๋๋ ํ ์คํธ์์ ์ํ๋ ์กฐ๊ฑด๊ฐ์ ์ ๋ ฅํ๋ฉด ํํฐ๋ง์ด ๊ฐ๋ฅํ๊ฒ๋ ์ง์ํด์ค๋๋ค.
๊ธฐ์กด์๋ ํด๋ก์ ๋ฅผ ํตํด์ ์์ฑํด์ ์์ ์ฝ๋๋ณด๋ค ์กฐ๊ธ ๋ ๊ธด ์ฝ๋๊ฐ ๋ณต์กํ๊ฒ ๋ค๊ฐ์์ต๋๋ค.
ํ์ง๋ง ์์ ์ฝ๋๋ฅผ ํตํด ์ ๋ง ๊น๋ํ๊ฒ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
2. MVVM์ ๋ํ ๊ณ ์ฐฐ(Combine ํ๋ฌ์ฐจ,, 2022.06.11)
SwiftUI + Combine์ ๊ณต๋ถํ ๋ UIKit + RxSwift๋ฅผ ์ฌ์ฉํ๋๊น UI์ ๊ตฌ์ฑ ๋ฐฉ์์ด๋๊ฐ, delegate์ ๊ฐ์ ๋ถ๋ถ์ด ์ด๋ ค์ ๋ค. ์ดํด๊ฐ ๊น์ด์ง์๋ก ์ด๋ ค์ด ์ ์ด ๋ ์๊ฒผ๋๋ฐ, 'MVVM์ด ์ ์ด์ธ๋ฆฌ๋๊ฐ?' ์ด๋ค.
ํ์ผ์ ์ด์ด๋ณด๋ฉด ์๊ฒ ์ง๋ง, ์๋ฅผ๋ค์ด EasyView๊ฐ ์๋ค๊ณ ํ๋ฉด EasyViewModel๋ก ๋ค์ด๋ฐํ๋ฉด ์ข์ ํ์ผ์ EasyEngine์ผ๋ก ๋ค์ด๋ฐ ํ๋ค. ์ด๊ฒ ๋ ์ง๊ด์ ์ด๊ณ , ์ ์ด์ธ๋ฆฐ๋ฌ๊น..?
๋ด๊ฐ ์งํํ๋ ํ๋ก์ ํธ์ app๋จ์ UIKit์์ SwiftUI๋ก ์ ํํ์๋๋ฐ, viewModel์ด๋ผ๋ ๋ค์ด๋ฐ๋ณด๋ค ํด๋น ๊ธฐ๋ฅ์ ๋ ์๋ง๋ ๋ค์ด๋ฐ์ ์ฑํํด์ ์ฌ์ฉํ๊ณ ์๋ค.
'apple > ๐ SwiftUI & Combine' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[SwiftUI] EqutableView (feat. POD) (0) | 2023.08.08 |
---|---|
[iOS] NavigationSplitView (0) | 2023.08.05 |
[Combine] Let's study Combine! (feat. SwiftUI) (0) | 2022.06.03 |
[SwiftUI] @StateObject (0) | 2022.06.02 |
[SwiftUI] State and Data Flow (0) | 2022.06.02 |