Skip to content

Instantly share code, notes, and snippets.

@koromiko
Created June 8, 2021 14:23
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save koromiko/35f6eb493a8f8fdd2da6a68b95231e42 to your computer and use it in GitHub Desktop.
Save koromiko/35f6eb493a8f8fdd2da6a68b95231e42 to your computer and use it in GitHub Desktop.
import SwiftUI
import UIKit
import Foundation
import Combine
enum RequestError: Error {
case apiError(reason: String)
}
class ResultController: ObservableObject {
@Published var senetence: String = ""
@Published var sentiment: String = ""
@Published var image: UIImage?
private func giveMeACat() async throws -> UIImage {
let imageUrl: String = try await getJSONResult(url: "https://api.thecatapi.com/v1/images/search", key: "url")
let (data, _) = try await URLSession.shared.data(from: URL(string: imageUrl)!, delegate: nil)
if let image = UIImage(data: data) {
return image
} else {
throw RequestError.apiError(reason: "The image data is broken")
}
}
private func getSentiment(sentence: String) async throws -> (String, String) {
var request = URLRequest(url: URL(string: "https://sentim-api.herokuapp.com/api/v1/")!)
request.allHTTPHeaderFields = ["Content-Type": "application/json" ]
request.httpMethod = "POST"
request.httpBody = try JSONSerialization.data(withJSONObject: ["text": sentence], options: .prettyPrinted)
let (data, _) = try await URLSession.shared.data(for: request, delegate: nil)
if let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any],
let result = json["result"] as? [String: Any],
let type = result["type"] as? String {
return (sentence, type)
} else {
throw RequestError.apiError(reason: "JSON parse error")
}
}
private func giveMeAJoke() async throws -> String {
return try await getJSONResult(url: "https://api.chucknorris.io/jokes/random", key: "value")
}
private func getJSONResult(url: String, key: String) async throws -> String {
let (data, _) = try await URLSession.shared.data(from: URL(string: url)!, delegate: nil)
if let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [String: Any],
let result = json[key] as? String {
return result
} else if let json = try JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [[String: Any]],
let result = json.first?[key] as? String {
return result
} else {
throw RequestError.apiError(reason: "JSON parse error")
}
}
private func fetchResult() async -> (joke: String, image: UIImage, sentiment: String)? {
do {
async let joke = await self.giveMeAJoke()
async let catImage = await self.giveMeACat()
let (sentence, senti) = try await self.getSentiment(sentence: await joke)
return try await (sentence, catImage, senti)
} catch {
print(error)
return nil
}
}
func generateANewJoke() {
DispatchQueue.global().async {
detach {
if let (sentence, image, sentiment) = await self.fetchResult() {
DispatchQueue.main.async {
self.senetence = sentence
self.sentiment = sentiment
self.image = image
}
}
}
}
}
}
struct ContentView: View {
@ObservedObject var controller = ResultController()
var body: some View {
VStack {
controller.image.map {
Image(uiImage: $0)
.resizable()
.scaledToFit()
.frame(width: 200, height: 200)
}
Text(controller.senetence)
.padding(.horizontal, 20)
.padding(.bottom, 10)
if !controller.sentiment.isEmpty {
HStack(alignment: .center) {
Text("This story is: ")
Text(controller.sentiment)
.font(Font.largeTitle)
}
}
Spacer()
Button("Random") {
controller.generateANewJoke()
}.padding(.bottom, 20)
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment