
How to use async / await keywords in Swift | Swift Concurrency #3

Async, Await를 사용할 때의 스레드 환경 파악하기Actor를 활용한 스레드 환경 조정하기sleep 등 비동기 함수를 실행한 이후 스레드 환경 파악하기MainActor 내부의 스레드 상황 파악하기 func addSomething() async {
try? await Task.sleep(nanoseconds: 2_000_000_000)
let something1 = "Something1 : \(Thread.current)"
await MainActor.run(body: {
self.dataArray.append(something1)
let something2 = "Something2 : \(Thread.current)"
self.dataArray.append(something2)
})
}
...
Task {
await viewModel.addAuthor1()
await viewModel.addSomething()
let finalText = "FinalText : \(Thread.current)"
viewModel.dataArray.append(finalText)
}
Task.sleep 메소드는 throw 가능한 비동기 함수로 해당 코드를 실행한 이후의 스레드는 메인 스레드가 아님MainActor 내부에서의 스레드 환경은 언제나 메인 스레드(애플 프레임워크 내부의 싱글턴 객체)Task를 통해 await 대기 가능import SwiftUI
class AsyncAwaitBootCampViewModel: ObservableObject {
@Published var dataArray = [String]()
func addTitle1() {
dataArray.append("TITLE1 : \(Thread.current)\nIs Main? : \(Thread.isMainThread)")
}
func addTitle2() {
DispatchQueue.global().asyncAfter(deadline: .now() + 2) {
let title2 = "TITLE2 : \(Thread.current)\nIs Main? : \(Thread.isMainThread)"
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
self.dataArray.append(title2)
self.dataArray.append("Title3: \(Thread.current)\nIs Main? : \(Thread.isMainThread)")
}
}
}
func addAuthor1() async {
let author1 = "Author1 : \(Thread.current)"
self.dataArray.append(author1)
try? await Task.sleep(nanoseconds: 2_000_000_000)
// after sleep -> thread : not main thread
// try? await doSometing()
// await -> suspension point
let author2 = "Author2: \(Thread.current)"
// after sleep -> thread : main thread
await MainActor.run(body: {
self.dataArray.append(author2)
let author3 = "Author3: \(Thread.current)"
self.dataArray.append(author3)
})
await addSomething()
}
func doSometing() async throws {
print("do Something")
}
func addSomething() async {
try? await Task.sleep(nanoseconds: 2_000_000_000)
let something1 = "Something1 : \(Thread.current)"
await MainActor.run(body: {
self.dataArray.append(something1)
let something2 = "Something2 : \(Thread.current)"
self.dataArray.append(something2)
})
}
}
Task.sleep을 통해서는 현 스레드(메인)가 다른 스레드로 바뀌지만 doSomething이라는 함수를 통해서는 바뀌지 않음 → async 함수라 할지라도 스레드 환경이 코드에 따라 달라짐struct AsyncAwaitBootCamp: View {
@StateObject private var viewModel = AsyncAwaitBootCampViewModel()
var body: some View {
List {
ForEach(viewModel.dataArray, id:\.self) { data in
Text(data)
.font(.headline)
.fontWeight(.bold)
}
}
.onAppear {
Task {
await viewModel.addAuthor1()
await viewModel.addSomething()
let finalText = "FinalText : \(Thread.current)"
viewModel.dataArray.append(finalText)
}
}
}
}

현재 UI를 담당하는 있는 데이터 서비스의 코드가 실행되는 스레드가 메인 스레드인지 확인 필수. 동일한 객체에 비동기적으로 접근하고 있는 코드가 두 개 이상이라면
actor클래스를 통해 동기화 적용 가능하다는 데 주의하자