We created a custom view extension to extend the functionality of .alert
and add a bunch of customizations to fit with our needs;
import SwiftUI
extension View {
public func alertX(isPresented: Binding<Bool>, content: () -> AlertX) -> some View {
let alertX_view = AlertX_View(visible: isPresented, alertX: content())
let alertXVC = AlertXViewController(alertX_view: alertX_view, isPresented: isPresented)
alertXVC.modalPresentationStyle = .overCurrentContext
alertXVC.view.backgroundColor = UIColor.clear
alertXVC.modalTransitionStyle = .crossDissolve
if isPresented.wrappedValue == true {
if AlertX_View.currentAlertXVCReference == nil {
AlertX_View.currentAlertXVCReference = alertXVC
}
let viewController = self.topViewController()
viewController?.present(alertXVC, animated: true, completion: nil)
} else {
alertXVC.dismiss(animated: true, completion: nil)
}
return self
}
... truncated for brevity
}
It is called on a view in the same way as .alert is called;
.alertX(isPresented: $viewModel.showAlert) {
AlertX(logo: networkStore.currentNetwork.networkTheme.systemLogo ,
logoColor: networkStore.activeColors.lightTextColor ,
backgroundColor: networkStore.activeColors.primaryColor,
title: Text("AlertX Test"))
}
Where $viewModel.showAlert
is @Published var showAlert: Bool
and AlertX
is a custom view that contains our proprietary customizations to fit with our B2B application.
The issue I am having is that the information inside the closure for .alertX(isPresented:
is called every time the view loads or changes state, regardless of whether or not the $viewModel.showAlert
binding changes. The same is NOT true of the built in .alert
view extension which is ONLY called when the $viewModel.showAlert
value changes.
What modifications do I need to make in my implementation of public func alertX(isPresented: Binding<Bool>, content: () -> AlertX) -> some View {
so that the information inside the closure it is only called when the binding value changes?
Remember that SwiftUI will reload all of the structs and functions all the time - and then decides, based on the data dependencies, which part to redraw. So any code in your view functions will run. A lot.
Try this: at the top of that function, put
Instead of checking it later on in the function.
Related, you might also want to look into making this code into a ViewModifier, and then your alertX function just applies the viewModifier based on the isPresented binding, otherwise returns self.