简体   繁体   中英

Calling functions in init() of SwiftUI View and ObservableObject

So I have a few data fetching tasks for views (type: View )that need to be run as soon as a view is loaded. If I put them in .onAppear{} , they don't load at the right time. So I must put them in the init(){} block of the struct.

Also, I have data fetching tasks from view models. These also need to be run instantly, and if I call them in .onAppear{} , it's too late and the program won't load the data. So I put those functions in the init(){} block as well.

Here's the problem. It initializes like a HUGE amount of times. I have 3K reads a day on Firestore and I'm the only one using the app. When I connect my voice chat app, it joins the channel on init(){} but then it tries to join it like 17 more times.

So my question is: How do I call a function simultaneous to the View's initialization, but make sure it only runs once per loading of the view?

Here's some examples from my code to give further insight

struct VoiceChatView: View {
    @State var halfModalShown = false
    @State var settingsModalShown = false
    @Binding var topic : Topic
    @State var channel : Channel
    
    @State var isLocalAudioMuted = false
    private let audioEngine = AudioEngine()
    private var rtcEngine: AgoraRtcEngineKit {
        get {
            return audioEngine.agoraKit
        }
    }
    
    @State var currentUser = AuthViewModel.shared.user!
    
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    
    init(topic: Binding<Topic>, channel: Channel) {
        self._topic = topic
        self._channel = State(initialValue: channel)
        self.callOnce()
    }


    var body: some View {
        Text("Hello, world")
    }
}

If you look at callOnce() you'll notice it's being called multiple times. I need that to be called before anything else happens, yes. But I need it not to continuously call over and over.

Can you try the wording in init method

   init(topic: Binding<Topic>, channel: Channel) {
            self._topic = topic
            self._channel = State(initialValue: channel)
//            self.callOnce()
        if self._channel {
            self.callOnce()
        }
        }

You can put your function or works that you are doing in init of your View , in init of your class/mode l. never use View init for this kind of works, SwiftUI just initialize Views here and there and any time it thinks it must, so Never Ever do that .

Even if you could define a condition for controlling some data! this is Wrong code design!

You can put a condition that your Views waits for your class to start rendering in case also.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM