Post

Replies

Boosts

Views

Activity

Reply to Add a ProgressView during a simple URLSession POST request in SwiftUI
In your code, requestTest is a name of a function. Using a function name in a condition of if-statement does not make sense. To use if-statement, you need an expression returning Bool. Please try something like this: import SwiftUI struct ContentView: View { @State private var tweetID = "" @State private var tweetStatus = "" @State private var response = "" @State var showAlert = false @State var sendToWebhook = false @State var isRequestInProgress: Bool = false //<- var body: some View { NavigationView { Form { Section(footer: Text("Test")) { TextField("Field to place response data", text: $response) TextEditor( text: $tweetStatus) .frame(height: 100) } Section { Button("Get Data") { // Where progress should start before function //↓Writing a View in an action closure does not make sensse //ProgressView("Test", value: 100, total: 100) requestTest() { results in response = results if response == "No Data!" { showAlert = true } } } if isRequestInProgress { //<- ProgressView() } } } .alert(isPresented: $showAlert) { Alert(title: Text("Tweet Sent"), message: Text("Your Tweet is sent! Your Tweet ID is shown in the field"), dismissButton: .default(Text("OK"))) } } } func requestTest(completion: @escaping(String) -> ()) { if let url = URL(string: "https://requestbin.net/r/ag4ipg7n") { var request = URLRequest(url: url) request.httpMethod = "POST" request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") var components = URLComponents(url: url, resolvingAgainstBaseURL: false)! components.queryItems = [ URLQueryItem(name: "TweetID", value: response), URLQueryItem(name: "Status", value: tweetStatus)] if let query = components.url!.query { request.httpBody = Data(query.utf8) } self.isRequestInProgress = true //<- let task = URLSession.shared.dataTask(with: request) { data, response, error in //↓ defer { DispatchQueue.main.async { self.isRequestInProgress = false } } if let data = data, let apiResponse = String(data: data, encoding: .utf8) { // IF Completed, these actions are shown below completion(apiResponse) self.showAlert = true tweetStatus = "" } else { completion("No Data!") } } task.resume() } } }
Jan ’22
Reply to Publishers.CombineLatest in SwiftUI
To utilize Combine well, you may need to know what are (or should be or can be) publisher. @State variables cannot be publishers without some additional code. To make publishers easily, you can work with ObservableObject with @Published variables: import SwiftUI import Combine class ValidateLogin { let user: String let pass: String init(user: String, pass: String) { self.user = user self.pass = pass } func validateMe() -> Bool { return user.count > 3 && pass.count > 3 } } class MyContent: ObservableObject { @Published var userText: String = "" @Published var passText: String = "" } struct ContentView: View { @StateObject var content = MyContent() @State var canSave: Bool = false @State var contentSubscriber: AnyCancellable? var body: some View { ZStack { VStack { TextField("Username", text: $content.userText) { } SecureField("Password", text: $content.passText) { } }.padding(.horizontal, 20.0) }.onAppear { self.contentSubscriber = self.content.$userText .combineLatest(content.$passText) .sink {userText, passText in let validateLogin = ValidateLogin(user: userText, pass: passText) self.canSave = validateLogin.validateMe() } } } }
Jan ’22