Global Actor란 프로젝트 내부에서 접근 가능한 유일한 actor로 어디서든 다양한 선언을 isolate하는데 사용할 수 있는 타입입니다
Global Actor 이전에 Actor란
아래는 메서드로 간단한 데이터를 가져오도록 하는 코드입니다. 이런 상황에서는 문제가 발생하지 않습니다.
func getData() async {
let data = await manager.getDataFromDatabase() // actor이므로 자동 async 코드로 인식
self.dataArray = data
}
하지만 엄청 무거운 작업을 Main Thread 에서 작업한다면 문제가 발생할 수 있습니다. 이런 목적으로 Actor이 만들어졌습니다.
Global Actor 사용 목적
만약 아래와 같은 actor가 존재한다고 하였을 때 아래 actor 말고 외부에서 아래의 actor에 isolated 된 메서드로 만들고 싶으면 MyNewDataManager actor를 Global 하게 사용하면 해결이 될 것입니다. 이것이 바로 Global Actor를 사용하는 목적입니다.
Global Actor를 이용하면 Global하게 프로젝트 어디서든 Actor를 Global하게 싱글톤으로 사용 가능
actor MyNewDataManager {
func getDataFromDatabase() -> [String] {
return ["One", "Two", "Three"]
}
}
Global Actor 파악하기
- iOS 13.0 버전부터 사용할 수 있습니다.
- 기존에 선언된 actor를 shared 인스턴스로 만들어 접근하도록 합니다.
- 싱글톤으로 사용되어야 합니다.
Global Actor 선언
@globalActor로 선언된 코드는 반드시 shared 인스턴스를 만들어야합니다.
@globalActor struct MyGlobalActor {
static var shared = MyNewDataManager()
}
이렇게 MyNewDataManger actor를 가지고 @globalActor를 만들었다면 이제 actor 에 존재하는 메서드들은 @globalActor의 shared 싱글톤을 통해 사용합니다.
class GlobalActorViewModel: ObservableObject {
@Published var dataArray: [String] = []
let manager = MyGlobalActor.shared
@MyGlobalActor
func getData() async {
let data = await manager.getDataFromDatabase()
self.dataArray = data
}
}
추가로 getData 메서드에 @MyGlobalActor를 사용하였는데 이것은 globalActor인 MyGlobalActor에 isolated 되는 메서드로 지정하는 것입니다.
globalActor를 이용하여 actor 외부에서 actor에 isolated 시키는게 가능해졌습니다.
@MyGlobalActor
func getData() async {
MainActor
MainActor는 GlobalActor 종류 중 하나인데 Actor와 다르게 Main Thread에서 작업을 수행한다고 지정하는 것 입니다.
보통은 Main Thread는 UI를 업데이트하는데 사용되는 스레드입니다. 즉 UI에 관여하는 데이터에 @MainActor를 붙여주면 해당 데이터를 가지고 작업을 할 때 Main Thread에서 작업이 이루어진다고 지정할 수 있습니다.
다음은 UI의 값이 반영되는 데이터입니다, UI에 해당 데이터가 직접적으로 관여하므로 Main Thread에서 작업이 이루어져야 합니다. 그러므로 @MainActor를 사용합니다.
@MainActor @Published var dataArray: [String] = []
추가로 해당 데이터에 값을 수정하기 위해서는 @MainActor 프로퍼티 래퍼를 사용하기 때문에 MainActor.run 메서드를 이용하여 작업할 내용을 클로저 내부에 넣어줍니다.
class GlobalActorViewModel: ObservableObject {
@MainActor @Published var dataArray: [String] = []
let manager = MyGlobalActor.shared
@MyGlobalActor
func getData() async {
let data = await manager.getDataFromDatabase()
await MainActor.run(body: {
self.dataArray = data
})
}
}
추가로 클래스 자체를 MainActor로 지정할 수 있다는 특징도 있습니다.
@MainActor class GlobalActorViewModel: ObservableObject {
'SwiftUI' 카테고리의 다른 글
AsyncPublisher (.value로 비동기적으로 데이터 처리) (0) | 2024.05.25 |
---|---|
MacPaw/OpenAI SwiftUI Package 분석하기 (0) | 2024.05.25 |
Actor (0) | 2024.05.21 |
Value Type, Reference Type, Stack, Heap, Struct, Class 사용되는 상황들, @StateObject 가 클래스여야 하는 이유 (0) | 2024.05.20 |
Class, ARC, Weak Self (0) | 2024.05.20 |