Ron
Ron

Reputation: 1660

SwiftUI retain cycle with .searchable

I think I found a retain cycle when binding an observable to a .searchable modifier...

to verify: create a new swiftUI app; replace ContentView.swift's content with this:

import SwiftUI

struct ContentView: View {
    
    var body: some View {
        NavigationView {
            List {
                NavigationLink("To Retain Cycle") {
                    RetainCycleView()
                }
            }
            .navigationTitle("Retain Cycle Demo")
        }
        .navigationViewStyle(.stack)
    }
}
    
struct RetainCycleView: View {
    
    @StateObject var model = Retainer()
//    @State var enteredText: String = ""
    
    var body: some View {
        VStack(alignment: .leading, spacing: 4) {
            Text("Navigate back to the previous view.")
            Text("You will see that 'Retainer' was NOT deallocated.")
            Text("(it's deinit function prints deallocing Retainer)")
                .font(.callout)
        }
        .padding()
        .searchable(text: $model.enteredText)
//       ^---- retain cycle
//        .searchable(text: $enteredText)
//       ^---- no retain cycle when using the @State var
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

class Retainer: ObservableObject {
    
    @Published var enteredText: String = ""
    
    init() { print("instantiated Retainer") }
    deinit { print("deallocing Retainer") }
}

When I pop the view off the stack, deinit won't be called for Retainer. If I remove the .searchable modifier, it does behave as expected.

Upvotes: 3

Views: 258

Answers (0)

Related Questions