RxSwift.Observable 从闭包到函数重构 `compactMap` 后的内存泄漏
Memory leak after refactoring `compactMap` for RxSwift.Observable from closure to function
我发现我的代码中可能存在泄漏,因为单元测试测试是否在 deinit
:
处调用依赖项
func testDeinit_ShouldStopMinutesTicker() throws {
let minutesTicker = MockMinutesTicker(elapsedTicksAfterStart: [(), (), ()])
var viewModel: AppointmentViewModel? = createAppointmentViewModel(minutesTicker: minutesTicker)
viewModel = nil
XCTAssertTrue(minutesTicker.isStopCalled)
}
这个测试通常是绿色的。但是当我重构这个时:
func selectAppointment(index: Int) {
selectedCellParamRelay.accept(index)
}
private func setupCellParamSelection() {
selectedCellParamRelay
.withLatestFrom(sortedCellParams) { ([=12=], ) }
.compactMap { [weak self] index, cellParams in
guard let `self` = self,
let selectedParam = cellParams[safe: index],
self.isUpcomingAppointment(selectedParam) else { return nil }
return selectedParam
}
.bind(to: upcomingCellParamRelay)
.disposed(by: disposeBag)
}
进入这个:
func selectAppointment(index: Int) {
selectedCellParamRelay.accept(index)
}
private func setupCellParamSelection() {
selectedCellParamRelay
.withLatestFrom(sortedCellParams) { ([=13=], ) }
.compactMap(selectAppointment(index:from:))
.bind(to: upcomingCellParamRelay)
.disposed(by: disposeBag)
}
private func selectAppointment(
index: Int,
from cellParams: [AppointmentCellParam]
) throws -> AppointmentCellParam? {
guard let selectedParam = cellParams[safe: index],
isUpcomingAppointment(selectedParam) else { return nil }
return selectedParam
}
private func isUpcomingAppointment(_ appointment: AppointmentCellParam) -> Bool {
return appointment.status != .missed && appointment.status != .finished
}
它变成红色,deinit
根本没有被调用。
正在从 init
调用 setupCellParamSelection
函数来设置事件处理程序以按索引选择任何约会单元格。 sortedCellParams
是由依赖项发出的中继,依赖项又会从后端获取值。
你能帮我看看第二个代码哪里出了问题吗?
谢谢。
是的,因为 .compactMap(selectAppointment(index:from:))
需要保持 self
才能调用 selectAppointment
,即使函数不需要 self。
这里的解决方案是将 isUpcomingAppointment(_:)
和 selectAppointment(index:from:)
移到 class 之外,或者作为 class.
中的静态函数
我发现我的代码中可能存在泄漏,因为单元测试测试是否在 deinit
:
func testDeinit_ShouldStopMinutesTicker() throws {
let minutesTicker = MockMinutesTicker(elapsedTicksAfterStart: [(), (), ()])
var viewModel: AppointmentViewModel? = createAppointmentViewModel(minutesTicker: minutesTicker)
viewModel = nil
XCTAssertTrue(minutesTicker.isStopCalled)
}
这个测试通常是绿色的。但是当我重构这个时:
func selectAppointment(index: Int) {
selectedCellParamRelay.accept(index)
}
private func setupCellParamSelection() {
selectedCellParamRelay
.withLatestFrom(sortedCellParams) { ([=12=], ) }
.compactMap { [weak self] index, cellParams in
guard let `self` = self,
let selectedParam = cellParams[safe: index],
self.isUpcomingAppointment(selectedParam) else { return nil }
return selectedParam
}
.bind(to: upcomingCellParamRelay)
.disposed(by: disposeBag)
}
进入这个:
func selectAppointment(index: Int) {
selectedCellParamRelay.accept(index)
}
private func setupCellParamSelection() {
selectedCellParamRelay
.withLatestFrom(sortedCellParams) { ([=13=], ) }
.compactMap(selectAppointment(index:from:))
.bind(to: upcomingCellParamRelay)
.disposed(by: disposeBag)
}
private func selectAppointment(
index: Int,
from cellParams: [AppointmentCellParam]
) throws -> AppointmentCellParam? {
guard let selectedParam = cellParams[safe: index],
isUpcomingAppointment(selectedParam) else { return nil }
return selectedParam
}
private func isUpcomingAppointment(_ appointment: AppointmentCellParam) -> Bool {
return appointment.status != .missed && appointment.status != .finished
}
它变成红色,deinit
根本没有被调用。
正在从 init
调用 setupCellParamSelection
函数来设置事件处理程序以按索引选择任何约会单元格。 sortedCellParams
是由依赖项发出的中继,依赖项又会从后端获取值。
你能帮我看看第二个代码哪里出了问题吗?
谢谢。
是的,因为 .compactMap(selectAppointment(index:from:))
需要保持 self
才能调用 selectAppointment
,即使函数不需要 self。
这里的解决方案是将 isUpcomingAppointment(_:)
和 selectAppointment(index:from:)
移到 class 之外,或者作为 class.