일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
Tags
- 동시성
- scrollview
- Algorithm
- 프로세스 스케줄링
- decode
- 데드락
- Codable
- async
- Linked List
- IOS
- COLOR
- core data
- 오브젝트
- 상호배제
- Apple Developer Academy
- 비동기
- deadlock
- UserDefaults
- 가상 메모리
- Swift
- 운영체제
- 100 days of SwiftUI
- SwiftUI
- struct
- 알고리즘
- forEach
- 동기화
- @state
- 인프런
- 앨런
Archives
- Today
- Total
기어가더라도 제대로
[SwiftUI-기초] URLSession 으로 Codable Data 받아오기 본문
- iTunes API 를 이용해서 데이터를 받아올 겁니다.
- 기반 사항은 이렇습니다.
- 리스트로 뿌려주는 간단한 코드
struct Response: Codable {
var results: [Result]
}
struct Result: Codable {
var trackId: Int
var trackName: String
var collectionName: String
}
struct MusicView: View {
@State private var results = [Result]()
var body: some View {
List(results, id: \.trackId) { result in
VStack(alignment: .leading) {
Text(result.trackName)
.font(.headline)
Text(result.collectionName)
}
}
}
}
동기? 비동기!
- 동기(동시적) 코드는 작업이 시작부터 완료시까지 다른 시스템이 기다리는 코드
- 비동기 코드:
- 작업이 시작되고 해당 작업을 잠시 완료되는 동안 잠자게하고 다른 작업을 할 수 있게 하는 코드
- 그러다가 작업이 완료되면 다시 제어권을 얻는 코드
- 예) "작업하는데 시간이 좀 걸리니까, 앱의 나머지 부분은 하던대로 하고 나는 완료되면 알려줄게~"
- 이런 비동기 코드가 있으면, 네트워크 작업이나, 용량이 큰 다운로드를 진행하는데 화면이 멈추거나 기다려야하는 단점을 보완할 수 있습니다.
비동기 코드를 선언하는 방법
- 비동기 메서드를 선언
- 비동기 함수 호출 블록을 선언
- 비동기 메서드의 경우엔 이 함수 내부에서 이 작업은 비동기적으로 실시됩니다. 라고 하는 부분을 명시를 해줘야합니다.
- 그 전에 크게 함수를 선언하는 라인에서 비동기적으로 작업이 완료될 수 있다는 점을 async 키워드로 알려줍니다.
func loadData() async {
}
- 그리고 이것을 컨텐트 뷰에서 실행을 한다고 해볼게요.
- 비동기적 흐름은 별도의 과정이 필요합니다.
- 예시로 화면이 켜지면 어떤 작업을 실행시키는 .onAppear { } 를 보여준다고 해볼게요.
.onAppear {
loadData()
}
- 이렇게 하면 오류가 발생합니다. 빌드 컴파일이 안됩니다.
- 앞으로 실행하는 블럭은 비동기적인 흐름을 처리할 수 있다고 알려주는 모디파이어를 달아줘야합니다.
.task {
await loadData()
}
- await: 이 해당 작업이 비동기적이므로 비동기 흐름 블록 안에서는 기달려달라는 그런 키워드입니다.
- 전체 .task { } 는 비동기적이고, 그러므로 실행을 하고 기다리지 않습니다. 다시 메인 앱의 흐름이 주도권을 가집니다.
- 다만 블럭 내부를 실행하면서는 비동기적으로 처리될 loadData() 의 결과를 기다린다는 것이죠.
메서드 내부 구현
- 컨텐츠를 가져올 URL 을 생성
- URL 로부터 데이터를 가져온다.(Fetch)
- 가져온 데이터를 우리가 사용할 수 있는 데이터 타입인 Response 구조체로 변환한다.(decoding)
func loadData() async {
// 1. URL 생성
guard let url = URL(string: "https://itunes.apple.com/search?term=taylor+swift&entity=song") else {
print("Invalid URL")
return
}
do {
// 2. Fetch data
let (data, meta) = try await URLSession.shared.data(from: url)
// 3. Decode data
if let response = try? JSONDecoder().decode(Response.self, from: data) {
results = response.results
}
print((meta as! HTTPURLResponse).statusCode)
} catch(let error) {
print(error.localizedDescription)
}
}
- URL() 로 생성하면 옵셔널 URL 이 나오기 때문에 guard-let 구문으로 URL을 타입을 얻습니다 .
- URLSession 에 그 url 을 넣고 마찬가지로 비동기 흐름이기 때문에 여기서 키워드를 표시해줍니다.
- 전체 메서드에서 URLSession.shared.data(from: url) 이 부분이 비동기적으로 실행되기 때문에 async 메서드로 선언
- 오류의 가능성이 있기에 do - catch - try 로 오류의 가능성을 대비합니다.
- URLSession.shared.data(from: url) 메서드의 결과값은 튜플 타입이기 때문에 저렇게 선언 가능합니다.
- 마지막으로 JSONDecoder를 이용해서 data 를 원하는 타입으로 변환합니다. 그 값을 results 에 넣는것이죠.
결론
- 비동기 코드는 처음이 어렵습니다. 자주 보면 이해됩니다.
- API 를 이용해서 값을 가져오는 것이 아주 자주 있는 일이죠.
- async, await, .task { } 에 익숙해지면 좋겠습니다.
'SwiftUI - 기초' 카테고리의 다른 글
[SwiftUI-기초] Navigation 일관된 경험 제공하기 (0) | 2023.09.07 |
---|---|
[SwiftUI-기초] 비동기적 이미지 뷰 - AsyncImage() (0) | 2022.11.26 |
[SwiftUI-기초] @Published 프로퍼티를 지닌 Codable 타입 저장 (0) | 2022.11.24 |
[SwiftUI-기초] UserDefaults 와 SwiftUI (0) | 2022.11.23 |
[SwiftUI-기초] Shape 를 복잡한 애니메이션 주기 (0) | 2022.11.22 |
Comments