BJH*_*ios 4 ios swiftui combine xcode12
我有以下 SwiftUI 视图,其中包含一个子视图,该子视图在五秒后消失。showRedView淡入淡出是通过接收组合时间发布者的结果触发的,但是更改发布者接收器块中的值sink会导致内存泄漏。
import Combine
import SwiftUI
struct ContentView: View {
@State var showRedView = true
@State var subscriptions: Set<AnyCancellable> = []
var body: some View {
ZStack {
if showRedView {
Color.red
.transition(.opacity)
}
Text("Hello, world!")
.padding()
}
.onAppear {
fadeRedView()
}
}
func fadeRedView() {
Timer.publish(every: 5.0, on: .main, in: .default)
.autoconnect()
.prefix(1)
.sink { _ in
withAnimation {
showRedView = false
}
}
.store(in: &subscriptions)
}
}
Run Code Online (Sandbox Code Playgroud)
我认为这是通过该系列在幕后以某种方式进行管理的AnyCancellable。我对 SwiftUI 和 Combine 比较陌生,所以肯定我要么把这里搞砸了,要么没有正确思考。避免这种泄漏的最佳方法是什么?
编辑:添加一些显示泄漏的图片。
视图应该被认为是描述视图的结构以及它如何对数据做出反应。它们应该是小型、单一用途、易于初始化的结构。他们不应该持有具有自己生命周期的实例(例如保留发布者订阅) - 这些实例属于视图模型。
class ViewModel: ObservableObject {
var pub: AnyPublisher<Void, Never> {
Timer.publish(every: 2.0, on: .main, in: .default).autoconnect()
.prefix(1)
.map { _ in }
.eraseToAnyPublisher()
}
}
Run Code Online (Sandbox Code Playgroud)
并用于.onReceive对视图中已发布的事件做出反应:
struct ContentView: View {
@State var showRedView = true
@ObservedObject vm = ViewModel()
var body: some View {
ZStack {
if showRedView {
Color.red
.transition(.opacity)
}
Text("Hello, world!")
.padding()
}
.onReceive(self.vm.pub, perform: {
withAnimation {
self.showRedView = false
}
})
}
}
Run Code Online (Sandbox Code Playgroud)
因此,通过上述安排,发布TimerPublisher者prefix链似乎导致了泄漏。它也不是适合您的用例的正确发布者。
以下实现了相同的结果,没有泄漏:
class ViewModel: ObservableObject {
var pub: AnyPublisher<Void, Never> {
Just(())
.delay(for: .seconds(2.0), scheduler: DispatchQueue.main)
.eraseToAnyPublisher()
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1468 次 |
| 最近记录: |