-
Notifications
You must be signed in to change notification settings - Fork 0
Issue
이도연 edited this page Jul 24, 2024
·
8 revisions
reactor.state.map { $0.todos }
.distinctUntilChanged()
.withUnretained(self)
.map { owner, todos in
EditTodoConverter
.convertToTodo(todos: todos) { todo in
owner.reactor.action.onNext(.deleteTodo(todo)) // ❌
}
}
.bind(to: baseView.collectionView.sectionBinder)
.disposed(by: disposeBag)- closure 캡쳐는 상위 스코프 내에서 일어난다.
-
convertToTodo후행 클로저의 상위 스코프는map { }이다. -
map { }에서.withUnretained(self)구문을 통해self를 약한 참조로 변경하였지만convertToTodo의 클로저가self(owner)에 대해 캡쳐하면서 암시적으로 강한 참조로 변경된다.
reactor.state.map { $0.todos }
.distinctUntilChanged()
.withUnretained(self)
.map { owner, todos in
EditTodoConverter
.convertToTodo(todos: todos) { [weak owner] todo in
owner?.reactor.action.onNext(.deleteTodo(todo))
}
}
.bind(to: baseView.collectionView.sectionBinder)
.disposed(by: disposeBag)- 중첩된 클로저 내부에서도 상위 스코프에서 캡쳐할 내용을
weak으로 명시해준다.
reactor.state.map { $0.timeOptions }
.withUnretained(self)
.map { owner, options in
EditNotificationConverter.convertToTimeOption(
options: options,
selectedOptions: owner.reactor.currentState
.selectedTimeOptions,
onSelect: { [weak owner] option in
guard let owner = owner else { return false } // ✅
let isOptionAlreadySelected = owner.reactor.currentState
.selectedTimeOptions
.contains(option)
// ...
return !isOptionAlreadySelected
}
)
}
.bind(to: baseView.timeOptionCollectionView.sectionBinder)
.disposed(by: disposeBag)- 중첩된 클로저 내에서
weak을 사용한 후guard let구문을 사용하는 것은 가능하다.
baseView.addTodoButton.onTap
.withUnretained(self)
.subscribe(onNext: { owner, _ in
UIView.animate(withDuration: 0.25) {
owner.baseView.newTodoTextField.layer.opacity = 1.0
}
owner.baseView.newTodoTextField.textField.becomeFirstResponder()
})
.disposed(by: disposeBag)-
UIView.animation클로저의 경우, 상위 스코프의 owner를 재사용해도 캡처 문제가 발생하지 않았다. 왜 일까? - 단, self를 그대로 캡처하면 문제가 발생했다. ➡️ 상위 스코프에서 강한 참조로 전환되어 문제가 발생한 것.
-
알았당!
UIView.animate의 클로저 캡처가 실행되는 시점은onTap이 실행되는 시점이다!onTap은 vc > view > button > onTap 구조로 존재하므로 vc가 해제되면onTap도 해제되어UIView.animate가 owner를 캡쳐할 일이 아예 없게된다. 즉, 클로저 내부에서[weak owner]를 사용하지 않으면owner를 강하게 캡쳐하는것이 맞지만, 이 경우엔 owner가 없다면 owner를 캡쳐할 일도 없게되는 것이다. -
이와 다르게 첫번째 경우에는 owner 캡쳐를 가지고 있는 곳이 vc > view > collection view > data source > item 이다. 즉, item에서 클로저를 '저장'하고 있기 때문에
[weak owner]를 사용하지 않으면 반드시 강한 캡처로 저장되게 된다. -
저장 되는 클로저가 상위 스코프이냐, 하위 스코프이냐에 따른 차이이다.