StrongSelfDataService라는 final class가 있고, class method로 getData()가 있다.
final class StrongSelfDataService {
func getData() async -> String {
"Updated data!"
}
}
StrongSelfBootcampViewModel라는 view model이 있고, 여기에는 @Published 변수인 var data: String이 있다. 또한 위의 데이터 서비스 클래스를 참조하는 변수 dataService가 있다.
final class StrongSelfBootcampViewModel: ObservableObject {
@Published var data: String = "Some title"
let dataService = StrongSelfDataService()
}
만약에 다음과 같은 함수가 있다고 하자.
func updateData() {
Task {
data = await dataService.getData()
}
}

updateData()가 실행되고, 그 결과 (받아온 데이터)가 화면 위에 표시된다고 가정해보면.weak self가 등장했다.여기서 다음 구문들은 모두 strong self를 사용한다.
// self, [self] 생략.
func updateData1() {
Task {
data = await dataService.getData()
}
}
// [self] 생략.
func updateData2() {
Task {
self.data = await self.dataService.getData()
}
}
// 생략 없음.
func updateData3() {
Task { [self] in
self.data = await self.dataService.getData()
}
}
반면 weak self를 사용하려면 다음과 같다.
// This is a weak reference.
func updateData4() {
Task { [weak self] in
if let data = await self?.dataService.getData() {
self?.data = data
}
}
}
그런데 왜 지금까지 배웠던 동시성 코드에는 weak self가 없을까?
→ 필요가 없기 때문!
→ Task를 통해 strong self 임에도 선택적으로 deinit 할 수 있다.
다음처럼 Task에 변수를 부여하면, Task.cancle()을 통해 선택적으로 실행을 종료할 수 있다.
private var someTask: Task<Void, Never>? = nil
func updateData5() {
someTask = Task { [self] in
self.data = await self.dataService.getData()
}
}
// Task.cancel()을 통해, Task내의 구문들의 실행을 멈출 수 있다.
func cancelTasks() {
someTask?.cancel()
someTask = nil
}
// 에를 들어, 화면이 종료 된 경우 cancel()을 실행
SOME VIEW
.onDisappear {
viewModel.cancelTasks()
}
Task에 변수를 지정하지 않고, 그대로 두어서 의도적으로 strong self를 사용할 수도 있다.