SwiftUI onSubmit 使实例无法取消分配

问题描述 投票:0回答:1

当从

@State
闭包访问视图的
@Binding
onSubmit
时,它会使视图无法取消初始化。基本示例:我们有一个按钮,它可以切换条件以显示带有
onSubmit
修饰符的目标视图。因此,多次点击按钮可以为我们提供以下诊断信息:

[Input] constructed: (1)
[Input] constructed: (2)
[Input] deallocating: (1)
[Input] constructed: (2)
[Input] deallocating: (1)
[Input] constructed: (2)
[Input] deallocating: (1)

我们可以看到:一个实例永远存活!

让我们用

onSubmit
注释行,或者用
onTapGesture
替换它,一切都会好起来的:

[Input] constructed: (1)
[Input] deallocating: (0)
[Input] constructed: (1)
[Input] deallocating: (0)
[Input] constructed: (1)
[Input] deallocating: (0)
[Input] constructed: (1)
[Input] deallocating: (0)

代码示例:

    import SwiftUI
    
    struct ContentView : View {
        
        @State private var state: Bool = false
        
        var body: some View {
            VStack {
                Button("push") { state.toggle() }
                if state { Input() } else { Color.red }
            }
        }
        
    }
    
    struct Input : View {
        
        @State private var text: String
        @State private var whatever: Bool
        private let tracing: InstanceTracer
        
        init() {
            self.text = "text"
            self.whatever = true
            self.tracing = InstanceTracer("Input")
        }
        
        var body: some View {
            TextField("placeholder", text: $text)
                .onSubmit { whatever.toggle() } // <- causes instance unable to deallocate
        }
        
    }
    
    final class InstanceTracer {
        
        private static var instances: [String : Int] = [ : ]
        
        private let name: String
        
        init(_ name: String) {
            self.name = name
            print("[\(name)] constructed: (\(increment(numberOf: name)))")
        }
        
        deinit { print("[\(name)] deallocating: (\(decrement(numberOf: name)))") }
        
        private func increment(numberOf name: String) -> Int {
            var number: Int = if let number: Int = Self.instances[name] { number } else { 0 }
            number += 1
            Self.instances[name] = number
            return number
        }
        
        private func decrement(numberOf name: String) -> Int {
            var number: Int = if let number: Int = Self.instances[name] { number } else { 0 }
            if number < 1 { return 0 }
            number -= 1
            Self.instances[name] = number
            return number
        }
        
    }
swiftui
1个回答
0
投票

避免永生实例的方法是使用

onCommit
TextField
参数而不是
onSubmit
修饰符:

var body: some View {
    TextField("placeholder", text: $text, onCommit: { whatever.toggle() })
    // instead of: TextField("placeholder", text: $text).onSubmit { whatever.toggle() }
}
© www.soinside.com 2019 - 2024. All rights reserved.