Created
June 8, 2021 14:23
-
-
Save koromiko/35f6eb493a8f8fdd2da6a68b95231e42 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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