Swift

[Swift Standard Library]

빨간체리반지 2024. 8. 1. 08:55

Concurrency

Task

(idel time 부여)

ex) try? await Task.sleep(for: .milliseconds(500))

Actor

protocol Actor : AnyActor

[ ] https://sujinnaljin.medium.com/swift-actor-뿌시기-249aee2b732d 추가 공부 필요!

병렬 프로그래밍에서 데이터 경합(Data Race) 문제를 줄이기 위해 고안되었다.

  1. 동기화된 상태 관리
    : actor 내부의 상태는 actor 자신만이 직접 접근할 수 있으며, 다른 코드가 접근하려면 actor의 메서드를 통해야 합니다. 이렇게 하면 동시성 문제를 피할 수 있습니다.
  2. 직렬화된 접근
    : actor의 메서드는 한 번에 하나의 쓰레드만 접근할 수 있도록 직렬화됩니다. 따라서 동일한 상태에 동시에 여러 쓰레드가 접근할 일이 없어집니다.
  3. 비동기 메서드 호출
    : actor의 메서드는 비동기적으로 호출됩니다. 이는 async/await 패턴을 사용하여 비동기 작업을 간편하게 처리할 수 있도록 합니다.

MainActor

@globalActor final actor MainActor

main Dispatch Queue 내에서 실행되도록 명시한다.

직접 DispatchQueue.main.async 를 호출할 필요가 없다.

ex) UILabel, UIViewController 도 @MainActor 가 붙어있다.

 

(사용)

  1. class 에 명시 : 해당 클래스의 모든 function 과 property 가 메인 큐에서 자동으로 설정/호출/접근 된다.
  2. function 에 명시 : 해당 함수는 메인 큐에서 실행된다.
    • ex) 내부로직은 메인 큐에서 실행되지만, 내부의 await 비동기 작업은 메인스레드를 보장하지 않는다.
@MainActor
func load() async {
	// 1. 메인스레드 보장.
	let data = await loadData()
	// 3. 메인스레드 보장.
	setDataToLabel(data)
}

func loadData() async {
	// 2. 비동기 작업 실행
}

 

(주의)

  • async-await 을 사용해야 유효하다.
    • closure 혹은 combine 사용시 내부 로직의 main thread 를 보장하지 않는다. ayns-await 와 다른 동시성 모델이기 때문.
@MainActor // 🙂
class ListViewModel: ObservableObject {
    func load() {
        loader.loadItems { [weak self] result in
            /*
            😰
            @MainActor 가 붙어 함수 자체는 메인스레드에서 호출되지만,
            closure 내부는 백그라운드에서 수행된다.
            */
            self?.result = result
        }
    }
}

preconcurrency

주로 objective-c 와 상호 작용하는 코드에서 사용한다.

Objective-C에서는 동시성 모델이 Swift와 다르기 때문에, 이 속성을 사용하여 경고를 억제하고 호환성을 유지한다.

'Swift' 카테고리의 다른 글

Attribute Wrapper  (0) 2024.08.01