0

I want to achieve an alert that has a text field embedded in it WITHOUT the help of iOS 16. It went smoothly until I wanted to update a variable when I press one of the buttons.

Currently, I have the custom alert code, which is straight up copied from a YouTube video that works perfectly:

extension View {
    func alertTF(title: String, message: String, hintText: String, primaryTitle: String, secondaryTitle: String, primaryAction: @escaping (String) -> (), secondaryAction: @escaping () -> () ) {
        let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
        alert.addTextField { field in
            field.placeholder = hintText
        }
        
        alert.addAction(.init(title: secondaryTitle, style: .cancel, handler: { _ in
            secondaryAction()
        }))
        
        alert.addAction(.init(title: primaryTitle, style: .default, handler: { _ in
            if let text = alert.textFields?[0].text {
                primaryAction(text)
            } else {
                primaryAction("")
            }
        }))
        
        rootController().present(alert, animated: true, completion: nil)
    }
    
    func rootController() -> UIViewController {
        guard let screen = UIApplication.shared.connectedScenes.first as? UIWindowScene else {
            return .init()
        }
        
        guard let root = screen.windows.first?.rootViewController else {
            return .init()
        }
        
        return root
    }
}

and here's the SwiftUI code that calls it:

@State private var submittedExportRequest = false

...

VStack {
     ARViewWrapper(submittedExportRequest: $submittedExportRequest, exportedURL: $exportedURL, submittedName: submittedName)
         .ignoresSafeArea()
                
     Button("Export") {
        alertTF(title: "Save as", message: "Please enter your file name", hintText: "my_file", primaryTitle: "Save", secondaryTitle: "cancel") { text in
        print(text)
        submittedName = text
        
        // Does not update my binding value.
        submittedExportRequest.toggle()

        } secondaryAction: {
            print("cancelled")
        }
    }
}

and a UIViewRepresentable View that is supposed to be called when one of the button is pressed:

@Binding var submittedExportRequest: Bool
@Binding var exportedURL: URL?
var submittedName: String

...

func updateUIView(_ uiView: ARView, context: Context) {
        
        // This does not get executed 
        if submittedExportRequest {
            ...
        }
    }

As you can see, the alert does not update my binding that was supposed to be passed in and refresh my UIViewRepresentable. Would be grateful if anyone could offer advice on how to approach this. Thanks!

9
  • why you are toggle value of button 2 times that's why it is not going to call if submittedExportRequest you need to remove submittedExportRequest.toggle() before alertTF(title: "Save as" in VStack. add submittedExportRequest.toggle() only on tap on Save button which is already added then check. I don't know what code has your func makeUIView(context: Context) method so according to value you can update it. Commented May 25, 2023 at 5:57
  • Nice catch. I accidentally uncommented my code in the previous line, and I had two while pasting it into StackOverflow. It still doesn't work with one toggle though. Commented May 25, 2023 at 6:01
  • Keep in mind that ARViewWrapper is a View and would not affect the order because state changes should still be able to occur regardless of its placement Commented May 25, 2023 at 6:09
  • Although I am reading the View before changing it, shouldn't it still update when submittedExportRequest updates its boolean? I thought UpdateUIView means that it will keep obtaining new changes and would take in the binding. Commented May 25, 2023 at 6:23
  • Sorry my bad, actually my mistake in code but i'm getting update value with submittedExportRequest.toggle() and able to execute that code if submittedExportRequest { Commented May 25, 2023 at 6:27

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.