Jamong25
Jamong25

Reputation: 11

How to add HTTP header in swiftui and how to get data from json?

I'm making an application that translates languages by using KakaoTalk api. I added header on url and sent http GET request to get the data from json.. but I can't get the data. I don't know what is wrong.. [1]: https://i.sstatic.net/iQtnu.png

      struct QuoteData: Decodable {
          var translated_text: [String]
        }
        struct ContentView: View {
          @State var quotedata: QuoteData?
          var body: some View {
            Button("get"){self.getData())
            Text(quotedata?.translated_text[0] ?? "아니")
          }
          func getData() {
            let token = "8995e2de40ee9b465734713e5a0d2ac5"
            guard let url = URL(string: "https://dapi.kakao.com/v2/translation/translate?src_lang=en&target_lang=kr&query=cotton") else {
              fatalError("Invalid URL")
            }
            var request = URLRequest(url: url)
            request.httpMethod = "GET"
            request.setValue("KakaoAK\(token)", forHTTPHeaderField: "Authorization")
            URLSession.shared.dataTask(with: request) { data, response, error in
              guard let data = data else{ return }
              if let decodedData = try? JSONDecoder().decode(QuoteData.self, from: data){
                DispatchQueue.main.async {
                  self.quotedata = decodedData
                }
              }
            }.resume()
          }
        }

Upvotes: 0

Views: 4309

Answers (2)

kanaloa
kanaloa

Reputation: 41

For those who want to use the new Async Await pattern, I used this which worked great!

static func fetchContact(urlString: String) async throws -> Contact {
    guard let url = URL(string: urlString) else {
        throw FetchError.invalidURL
    }
    var request = URLRequest(url: url)
    request.httpMethod = "GET"
    request.setValue(Functions().api, forHTTPHeaderField: "ACCESS_TOKEN")
// Functions().api is just a private string that stores the api key
    let (data, _) = try await URLSession.shared.data(for: request)        
    let result = try JSONDecoder().decode(Contact.self, from: data)
    return result
}
enum FetchError: Error {
    case invalidURL
    case missingData
}

I can call the above with this:

let contact = try await Functions.fetchContact(urlString: "https://api.crmworkspace.com/v1/contacts/\(id)")

In SwiftUI I call call this function from a view:

func call(phone: String, id: Int) async {
    if let url = URL(string: "tel:\(phone.numbersOnly)") {
        await UIApplication.shared.open(url)
        do {
            let contact = try await Functions.fetchContact(urlString: "https://api.crmworkspace.com/v1/contacts/\(id)")
            // Do whatever with the contact object here...
        } catch {
            print("Request failed with error: \(error)")
        }
    }
}

Here's the part of the view that calls this function:

Button(action: {
            Task {
                await Functions().call(phone: result.phoneNumber, id: Int(result.id))
            }
        }, label: {
            Label(result.phoneNumber, systemImage: "phone.circle.fill")
        })

I find the new async/await pattern much easier to write and debug than closures! Hope this helps someone.

Upvotes: 0

Tushar Sharma
Tushar Sharma

Reputation: 2882

Your token value is space separated KakaoAK 8995e2de40ee9b465734713e5a0d2ac5, you have to pass it the same way in your request header, else you will face 401 unauthorized error.

Also, the response is of type [[String]] for key "translated_text”, and not [String].

Below is the working code-:

import SwiftUI


struct QuoteData: Decodable {
    var translated_text: [[String]]
}

struct Test: View {
    @State var quotedata: QuoteData?
    
    var body: some View {
        VStack{
            Button("get") {
                self.getData()
            }
            Text(quotedata?.translated_text[0][0] ?? "아니")
        }
    }
    
    func getData() {
        let token = "8995e2de40ee9b465734713e5a0d2ac5"
        guard let url = URL(string: "https://dapi.kakao.com/v2/translation/translate?src_lang=en&target_lang=kr&query=cotton") else {
            fatalError("Invalid URL")
        }
        var request = URLRequest(url: url)
        request.httpMethod = "GET"
        request.setValue("KakaoAK \(token)", forHTTPHeaderField: "Authorization")
        URLSession.shared.dataTask(with: request) { data, response, error in
            guard let data = data else{ return }
            do{
                let decodedData =  try JSONDecoder().decode(QuoteData.self, from: data)
                DispatchQueue.main.async {
                    self.quotedata = decodedData
                }
            }catch let error{
                print(error)
            }
        }.resume()
    }
}

Upvotes: 4

Related Questions