在assign
的文档中,其内容如下...
此操作员创建的Subscribers / Assign实例维护一个 对对象的强引用,并在上游时将其设置为nil 发布者完成(正常或有错误)。
在ViewModifier
中assign
方法下面的subscribeToKeyboardChanges()
中,它是指self,但self是这里的结构,因此无法创建强引用。
subscribeToKeyboardChanges()
中的订阅没有立即被释放?struct KeyboardHandler: ViewModifier {
@State private var keyboardHeight: CGFloat = 0
func body(content: Content) -> some View {
content
.padding(.bottom, self.keyboardHeight)
.animation(.default)
.onAppear(perform: subscribeToKeyboardChanges)
}
private let keyboardWillShow = NotificationCenter.default
.publisher(for: UIResponder.keyboardWillShowNotification)
.compactMap { $0.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect }
.map { $0.height }
private let keyboardWillHide = NotificationCenter.default
.publisher(for: UIResponder.keyboardWillHideNotification)
.map { _ in CGFloat.zero }
private func subscribeToKeyboardChanges() {
_ = Publishers.Merge(keyboardWillShow, keyboardWillHide)
.subscribe(on: DispatchQueue.main)
.assign(to: \.self.keyboardHeight, on: self)
}
}
答案 0 :(得分:0)
我相信您指的是错误的功能描述。这是正确的一个:
分配(至:开:)
将发布者的输出分配给对象的属性。
...
返回值
AnyCancellable实例。如果没有,请在此实例上调用cancel() 不再希望发布者自动分配属性。 取消初始化此实例也会取消自动分配。
因此,在您的subscribeToKeyboardChanges
示例代码中,预期在函数完成后将取消订阅。您必须牢记从AnyCancellable
返回的assign
才能将预订保留在内存中。
编辑:
似乎在这一行assign
复制了self
并将其保存在内存中,直到调用cancel()
。
.assign(to: \.self.keyboardHeight, on: self)
因此,使用View
视图修饰符的KeyboardHandler
将永远不会被取消分配订阅,并且最终将在导航期间使内存膨胀。例如,这是经过3次导航后仍在内存中查看KeyboardHandler
的3个实例的屏幕截图。