0

having a bit of trouble with the following.

I have a List in a VStack as follows:

List{
ForEach(fetchRequest.wrappedValue, id: \.self) { city in
                    
                 NavigationLink(destination: CityView(city: city, moc: self.moc)) {
                            
                            cityRow(city: city)
                 }
                    
         }
}

This list is populated from a coreData fetchrequest. Each NavigationLinks navigates to CityView and passes a city Object with it.

CityView had a observable object 'notificationHandler' defined as follows:

struct CityView: View {

    @ObservedObject var notificationHandler = NotificationHandler()
    @ObservedObject var city: City
    
    var body: some View {

    }
}

NotificationHandler() sets up an instance of NotificationHandler and sets up a few notification observers from within init as follows:

import Foundation
import Combine

class NotificationHandler: ObservableObject {
    
    let nc = NotificationHandler.default
    
    @Published var networkActive: Bool = false
    
    init() {
        nc.addObserver(self, selector: #selector(networkStart), name: Notification.Name("networkingStart"), object: nil)
        nc.addObserver(self, selector: #selector(networkStop), name: Notification.Name("networkingStop"), object: nil)
    }

}

My issues is this - when the app boots onto its first view which contins the list above - I'm getting a number of instance of NotificationHandler starting - one for every row of the list. - This has led me to the belief that the NavigationLinks in the list are preemtivly loading the CityView's they hold. However I believe this is no longer the case and lazy load is the defualt behaviour. To add to that adding an onAppear() within CityView shows the they are not being completly loaded.

Any help would be greatly appretiated, I can't work out how this is happening.

Thanks

swift--help
  • 637
  • 5
  • 15
  • So you have your own class named `NotificationCenter`, shadowing the Foundation class? And then, in your own class, you **use** the Foundation class? It will be easier to help you if you give your own class a name that doesn't conflict with an existing widely-used class. – rob mayoff Nov 06 '20 at 21:06
  • I've have edited it and changed the question. Unfortuantly makes no difference. Thanks for the help. – swift--help Nov 06 '20 at 21:07
  • 2
    Create the notification class at the top level instead and send it as a parameter to CityView (is that the same as OrganisationView?) or create an EnvironmentObject for it. – Joakim Danielson Nov 06 '20 at 21:12
  • Yes it is the same. I've made an edit sorry for the confusion. Do you mean create it in the first view and pass it through to CityView? I assumed an observableobject on city view wouldnt be initalized prior to becoming active? – swift--help Nov 06 '20 at 21:18
  • @JoakimDanielson both your methods also worked. Thanks again. – swift--help Nov 06 '20 at 21:36

2 Answers2

2

The Destination on the NavigationView is NOT lazy, so it initializes the Destination view as soon as it is created. An easy work around can be found here: SwiftUI - ObservableObject created multiple times. Wrap your Destination view within the LazyView.

nicksarno
  • 3,850
  • 1
  • 13
  • 33
1

Would like to share the latest updates for the solution of this problem.

https://stackoverflow.com/a/66520131

This is the way by which you can avoid creating multiple instances of ObservedObjects.

Sharing this because just lazy loading in NavigationLink doesn't solve the problem where refreshing the views at runtime as per user's actions creates and destroys ObservedObject multiple times.

Hence we need some solution where our Objects are created only once and also persists even after view is refreshed.

mohit kejriwal
  • 1,755
  • 1
  • 10
  • 19