Question: Swiftui http request without button

Hello guys,

I´m new to the forum and have a question concerning a http request which should be established without a button clicked. Basically I would like to have everything inside the button´s action tag done automatically without a button clicked.

Thanks in advance.

Nikias

Here is my code from the ts.view :

import SwiftUI



struct ContentView: View {

    

    @State var username: String = "..."

    @State var password: String = "..."

    

    var body: some View {

        

            ZStack {

                VStack {

                        

                    Button(action: {

                        if 1==1 {



                            let myUrl = URL(string: "

                               

                               var request = URLRequest(url:myUrl!)

                               

                               request.httpMethod = "POST"// Compose a query string

                               

                               let postString = "Name=\($username)&Passwort=\($password)";

                               

                               request.httpBody = postString.data(using: String.Encoding.utf8);

                               

                               let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in

                                   

                                   if error != nil

                                   {

                                       print("error=\(error)")

                                       return

                                   }

                                   

                                   // You can print out response object

                                   print("response = \(response)")

                          

                                   //Let's convert response sent from a server side script to a NSDictionary object:

                                   do {

                                       let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary

                                       

                                       if let parseJSON = json {

                                           

                                           // Now we can access value of First Name by its key

                                           let firstNameValue = parseJSON["Name"] as? String

                                           print("firstNameValue: \(firstNameValue)")

                                        let dateien =  firstNameValue?.components(separatedBy: ",")

                    

                    print(dateien)

            

                    

                                       }

                                   } catch {

                                       print(error)

                                   }

                                   }

                                   task.resume()



                        }

                    }) {

                        LoginButtonContent()

                    }

            }

        }

        

    }

}



struct TestView_Previews: PreviewProvider {

    static var previews: some View {

        ContentView()

    }

}


I had to remove the URL.

I would like to have everything inside the button´s action tag done automatically without a button clicked.

You can do it without a button clicked, but never automatically.
You need to define when to do it.
For example, if you want to do it when the view appears, you can use onAppear.


Please use the Code block (icon < >) to include some code in your post.

Yes I would put the code in a separate function. You can call this function during .onAppear on one of your views. You could then also keep it as an action for your button, so clicking the button would also execute the code block.
Hello,

Thanks for your answer.
I have tried to implement the on Appear function but I failed.
Could you please rewrite the code with the on Appear function because I don't manage to do so.

thanks a lot.

I have tried to implement the on Appear function but I failed.

Please show your code that failed.
<

import SwiftUI



struct ContentView: View {

    

    @State var username: String = "."

    @State var password: String = "."

    

    var body: some View {

        

            ZStack {

                VStack {

                        

                    .onAppear(perform: {

                        if 1==1 {



                            let myUrl = URL(string: ".");

                               

                               var request = URLRequest(url:myUrl!)

                               

                               request.httpMethod = "POST"// Compose a query string

                               

                               let postString = "Name=\($username)&Passwort=\($password)";

                               

                               request.httpBody = postString.data(using: String.Encoding.utf8);

                               

                               let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in

                                   

                                   if error != nil

                                   {

                                       print("error=\(error)")

                                       return

                                   }

                                   

                                   // You can print out response object

                                   print("response = \(response)")

                          

                                   //Let's convert response sent from a server side script to a NSDictionary object:

                                   do {

                                       let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary

                                       

                                       if let parseJSON = json {

                                           

                                           // Now we can access value of First Name by its key

                                           let firstNameValue = parseJSON["Name"] as? String

                                           print("firstNameValue: \(firstNameValue)")

                                        let dateien =  firstNameValue?.components(separatedBy: ",")

                    

                    print(dateien)

            

                    

                                       }

                                   } catch {

                                       print(error)

                                   }

                                   }

                                   task.resume()



                        }

                    }

                )

            }

        }

        

    }

}



struct TestView_Previews: PreviewProvider {

    static var previews: some View {

        ContentView()

    }

} >

Please use the Code block (icon < >) to include some code in your post.

Button with icon < > in the bottom bar of editing area. Not put < and > separately.

Hello Sir,

It doesn't work with the <> ones.

Could you me even if I don't have them?

Thanks

Nikias

It doesn't work with the <> ones.

It works.


You may not be doing it right.


One more, I am not Sir. You should better not use it.
Okay, I`m sorry,

Are you able to send the corrected code anyways?


Nikias
Code Block
import SwiftUI
struct ContentView: View {
    
    @State var username: String = "."
    @State var password: String = "."
    
    var body: some View {
        
            ZStack {
                VStack {
                        
                    .onAppear(perform: {
                        if 1==1 {
                            let myUrl = URL(string: "http://192.168.1.180/int.php");
                               
                               var request = URLRequest(url:myUrl!)
                               
                               request.httpMethod = "POST"// Compose a query string
                               
                               let postString = "Name=\($username)&Passwort=\($password)";
                               
                               request.httpBody = postString.data(using: String.Encoding.utf8);
                               
                               let task = URLSession.shared.dataTask(with: request) { (data: Data?, response: URLResponse?, error: Error?) in
                                   
                                   if error != nil
                                   {
                                       print("error=\(error)")
                                       return
                                   }
                                   
                                   // You can print out response object
                                   print("response = \(response)")
                          
                                   //Let's convert response sent from a server side script to a NSDictionary object:
                                   do {
                                       let json = try JSONSerialization.jsonObject(with: data!, options: .mutableContainers) as? NSDictionary
                                       
                                       if let parseJSON = json {
                                           
                                           // Now we can access value of First Name by its key
                                           let firstNameValue = parseJSON["Name"] as? String
                                           print("firstNameValue: \(firstNameValue)")
                                        let dateien =  firstNameValue?.components(separatedBy: ",")
                    
                    print(dateien)
            
                    
                                       }
                                   } catch {
                                       print(error)
                                   }
                                   }
                                   task.resume()
                        }
                    }
                )
            }
        }
        
    }
}
struct TestView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}


Thanks for updating your code. It gets far more readable and would save readers time.
(When you see extra empty lines than your original code, Edit > Paste and Match Style of Safari would work.)

In your code, you put too many lines in an action closure, you should better create a method and just call it inside an action closure.
Code Block
struct ContentView: View {
@State var username: String = "."
@State var password: String = "."
var body: some View {
ZStack {
VStack {
.onAppear { //-> Cannot infer contextual base in reference to member 'onAppear'
doHttpRequest()
}
//...
}
}
}
func doHttpRequest() {
if 1==1 { //# Do you still need this?
let myUrl = URL(string: "...")! //# Trailing semicolon is not needed
var request = URLRequest(url: myUrl)
request.httpMethod = "POST"// Compose a query string
let postString = "Name=\($username)&Passwort=\($password)" //# ???
request.httpBody = postString.data(using: .utf8)
let task = URLSession.shared.dataTask(with: request) {
(data, response, error) in
//# Use if-let when you want to use the unwrapped value
if let error = error {
print("error=\(error)")
return
}
//# Use guard-let when nil has no meaning and want to exit on nil
guard let response = response else {
print("Unexpected nil response")
return
}
// You can print out response object
print("response = \(response)")
//Let's convert response sent from a server side script to a NSDictionary object:
do {
//# Use guard-let when nil has no meaning and want to exit on nil
guard let data = data else {
print("Unexpected nil data")
return
}
//#1 `mutableContainer` has no meaning in Swift
//#2 Use Swift Dictionary type instead of `NSDictionary`
let json = try JSONSerialization.jsonObject(with: data) as? [String: Any]
if let parseJSON = json {
// Now we can access value of First Name by its key
//# Use if-let when you want to use the unwrapped value
if let firstNameValue = parseJSON["Name"] as? String {
print("firstNameValue: \(firstNameValue)")
let dateien = firstNameValue.components(separatedBy: ",")
print(dateien)
}
}
} catch {
print(error)
}
}
task.resume()
}
}
}

(I have brushed up some parts of doHttpRequest. Please see comments with //#.)

You should better include the error messages when you want to ask something about codes causing errors.

The error Cannot infer contextual base in reference to member 'onAppear' occurs becauseonAppear is a method classified as view modifier, which must be added to a view.
In your code, there is no view directly before .onAppear.

For example, if you put .onAppear to the outermost view of body, you can write it as:
Code Block
var body: some View {
ZStack {
VStack {
//...
}
}
.onAppear { //# This `onAppear` is added to `ZStack{...}`
doHttpRequest()
}
}


Hello,

the function an the request work perfectly fine but now I´like to view the array "Dateien" that I get off the HTTP-Request with a For- loop: There should be an Image an the filename for each string in the array "Dateien", which works fine with the example array.

Code Block
import SwiftUI
struct ContentView4: View {
    
    @State var showingDetail = false
    
    @State var username: String = "."
    @State var password: String = "."
    
    let dateien = Optional(["word.png", "vi.png", "text.png", "pp.png", "pdf.png", "ordner.png", "ex.png", "datei.png", "bild.png"])
    
    var body: some View {
        ScrollView(.vertical) {
        ZStack{
            VStack {
                ForEach(0 ..< dateien!.count) {
                    Button(action: {
                        print("button pressed")
                        self.showingDetail.toggle()
                    }) {
                    Image("datei")
                    }
                        .scaledToFit()
                        .padding(0)
                
                    Text(self.dateien![$0])
            }
            }
        }
        .sheet(isPresented: $showingDetail) {
                    ts()
                }
        .onAppear { //# This `onAppear` is added to `ZStack{...}`
            doHttpRequest()
        }
    }
    }


But I don't get how to use the Array" Dateien" from the Http-Request instead of the example one.
Heeres my code for the request:

Code Block
 func doHttpRequest() {
            let myUrl = URL(string: "http://192.168.1.180/int.php")! //# Trailing semicolon is not needed
            var request = URLRequest(url: myUrl)
            request.httpMethod = "POST"// Compose a query string
            let postString = "Name=\($username)&Passwort=\($password)"
            
            request.httpBody = postString.data(using: .utf8)
            
            let task = URLSession.shared.dataTask(with: request) {
                (data, response, error) in
                
                //# Use if-let when you want to use the unwrapped value
                if let error = error {
                    print("error=\(error)")
                    return
                }
                
                //# Use guard-let when nil has no meaning and want to exit on nil
                guard let response = response else {
                    print("Unexpected nil response")
                    return
                }
                // You can print out response object
                print("response = \(response)")
                
                //Let's convert response sent from a server side script to a NSDictionary object:
                do {
                    //# Use guard-let when nil has no meaning and want to exit on nil
                    guard let data = data else {
                        print("Unexpected nil data")
                        return
                    }
                    //#1 `mutableContainer` has no meaning in Swift
                    //#2 Use Swift Dictionary type instead of `NSDictionary`
                    let json = try JSONSerialization.jsonObject(with: data) as? [String: Any]
                    
                    if let parseJSON = json {
                        // Now we can access value of First Name by its key
                        //# Use if-let when you want to use the unwrapped value
                        if let firstNameValue = parseJSON["Name"] as? String {
                            print("firstNameValue: \(firstNameValue)")
                            let dateien =  firstNameValue.components(separatedBy: ",")
                            print(dateien)
                            let greeting = dateien
                        }
                    }
                } catch {
                    print(error)
                }
            }
            task.resume()
    }
}
struct TestView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView4()
    }
}
struct ts: View {
    var body: some View {
        NavigationView {
        VStack {
            Text("Datei.pdf")
                .font(.system(size: 60))
                .foregroundColor(.black)
                .padding(50)
            Text("+")
                .font(.headline)
                .foregroundColor(.white)
                .padding()
                .frame(width: 220, height: 60)
                .background(Color.yellow)
                .cornerRadius(35.0)
            Text("Datei herunterladen")
                .font(.headline)
                .foregroundColor(.white)
                .padding()
                .frame(width: 220, height: 60)
                .background(Color.blue)
                .cornerRadius(35.0)
            Text("Datei umbenennen")
                .font(.headline)
                .foregroundColor(.white)
                .padding()
                .frame(width: 220, height: 60)
                .background(Color.green)
                .cornerRadius(35.0)
            Text("Datei löschen")
                .font(.headline)
                .foregroundColor(.white)
                .padding()
                .frame(width: 220, height: 60)
                .background(Color.red)
                .cornerRadius(35.0)
            }
        }
    }
}

I would be very glad I you help me out for another time.

Thanks

Nikias

But I don't get how to use the Array" Dateien" from the Http-Request instead of the example one.

It's dateien, not Dateien. In Swift, identifiers are case sensitive, you should better care about that even in non-code context.

Assume your print(dateien) (line 85 of doHttpRequest()) shows expected result,
you just need to update the property dateien with the local variable dateien.
Code Block
self.dateien = dateien


To make this work, the declaration of the property dateien (line 19 of ContentView4) needs to be var, not let.


By the way, why are you adding Optional to the property declaration of dateien?
Code Block
    let dateien = Optional(["word.png", "vi.png", "text.png", "pp.png", "pdf.png", "ordner.png", "ex.png", "datei.png", "bild.png"])

With declaring it as non-Optional, you can reduce some risky-and-never-want-to-use forced unwrappings (!).
Code Block
    var dateien: [String] = []

Or if you need some initial values:
Code Block
    var dateien: [String] = ["word.png", "vi.png", "text.png", "pp.png", "pdf.png", "ordner.png", "ex.png", "datei.png", "bild.png"]


Hello,

Thanks a lot for your quick reply.

i have now got this, but It says

"Cannot use mutating member on immutable value: 'self' is immutable."

on Line 43:

Code Block
import SwiftUI
struct ContentView4: View {
    
    @State var showingDetail = false
    
    @State var username: String = "."
    @State var password: String = "."
    
    var dateien = Optional(["word.png", "vi.png", "text.png", "pp.png", "pdf.png", "ordner.png", "ex.png", "datei.png", "bild.png"])
    
    var body: some View {
        ScrollView(.vertical) {
        ZStack{
            VStack {
                ForEach(0 ..< dateien!.count) {
                    Button(action: {
                        print("button pressed")
                        self.showingDetail.toggle()
                    }) {
                    Image("datei")
                    }
                        .scaledToFit()
                        .padding(0)
                
                    Text(self.dateien![$0])
            }
            }
        }
        .sheet(isPresented: $showingDetail) {
                    ts()
                }
        .onAppear { //# This `onAppear` is added to `ZStack{...}`
            doHttpRequest()
        }
    }
    }
    
    mutating func doHttpRequest() {
            let myUrl = URL(string: "http://192.168.1.180/int.php")! //# Trailing semicolon is not needed
            var request = URLRequest(url: myUrl)
            request.httpMethod = "POST"// Compose a query string
            let postString = "Name=\($username)&Passwort=\($password)"
            
            request.httpBody = postString.data(using: .utf8)
            
            let task = URLSession.shared.dataTask(with: request) {
                (data, response, error) in
                
                //# Use if-let when you want to use the unwrapped value
                if let error = error {
                    print("error=\(error)")
                    return
                }
                
                //# Use guard-let when nil has no meaning and want to exit on nil
                guard let response = response else {
                    print("Unexpected nil response")
                    return
                }
                // You can print out response object
                print("response = \(response)")
                
                //Let's convert response sent from a server side script to a NSDictionary object:
                do {
                    //# Use guard-let when nil has no meaning and want to exit on nil
                    guard let data = data else {
                        print("Unexpected nil data")
                        return
                    }
                    //#1 `mutableContainer` has no meaning in Swift
                    //#2 Use Swift Dictionary type instead of `NSDictionary`
                    let json = try JSONSerialization.jsonObject(with: data) as? [String: Any]
                    
                    if let parseJSON = json {
                        // Now we can access value of First Name by its key
                        //# Use if-let when you want to use the unwrapped value
                        if let firstNameValue = parseJSON["Name"] as? String {
                            print("firstNameValue: \(firstNameValue)")
                            let dateien =  firstNameValue.components(separatedBy: ",")
                            print(dateien)
                            self.dateien = dateien
                        }
                    }
                } catch {
                    print(error)
                }
            }
            task.resume()
    }
}
struct TestView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView4()
    }
}
struct ts: View {
    var body: some View {
        NavigationView {
        VStack {
            Text("Datei.pdf")
                .font(.system(size: 60))
                .foregroundColor(.black)
                .padding(50)
            Text("+")
                .font(.headline)
                .foregroundColor(.white)
                .padding()
                .frame(width: 220, height: 60)
                .background(Color.yellow)
                .cornerRadius(35.0)
            Text("Datei herunterladen")
                .font(.headline)
                .foregroundColor(.white)
                .padding()
                .frame(width: 220, height: 60)
                .background(Color.blue)
                .cornerRadius(35.0)
            Text("Datei umbenennen")
                .font(.headline)
                .foregroundColor(.white)
                .padding()
                .frame(width: 220, height: 60)
                .background(Color.green)
                .cornerRadius(35.0)
            Text("Datei löschen")
                .font(.headline)
                .foregroundColor(.white)
                .padding()
                .frame(width: 220, height: 60)
                .background(Color.red)
                .cornerRadius(35.0)
            }
        }
    }
}


"Cannot use mutating member on immutable value: 'self' is immutable."

Sorry, I have forgotten one thing. In struct used as View, you need @State in addition to making it var:
Code Block
    @State var dateien = ["word.png", "vi.png", "text.png", "pp.png", "pdf.png", "ordner.png", "ex.png", "datei.png", "bild.png"]

(Seems I need to repeat, remove Optional.)

Also, you need to remove mutating from doHttpRequest().
Question: Swiftui http request without button
 
 
Q