Reputation: 11
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
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
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