Hello! I'm doing a small project that allows users to rate photos of each other anonymously. Here I have a screen; all I need is view updates when I click the "Rate" button. Now I see that my data updates and view doesn't
struct PhotoCellView: View {
@State var photo: Photo
@State private var ratingButtonTapped = false
@StateObject var viewmodel = PhotosViewModel()
var body: some View {
VStack {
AsyncImageWithAuth(url: URL(string: getFullURL(photo.url))) { image in image
.resizable()
} placeholder: {
Image("placeholder")
.resizable()
}
.frame(width: 400, height: 400)
SliderView(rating: $viewmodel.attractivenessRating, text: "Attractiveness")
SliderView(rating: $viewmodel.smartRating, text: "Smart")
SliderView(rating: $viewmodel.trustWorthyRating, text: "Trustworthy")
Button {
Task {
viewmodel.ratePhoto(id: photo.id)
let _: () = viewmodel.getRandomPhoto() { result in
switch result {
case .success(let randomPhoto):
viewmodel.photo = randomPhoto
case .failure(let error):
print(error)
}
}
ratingButtonTapped.toggle()
}
} label: {
Text("Rate")
.foregroundColor(.white)
.frame(width: UIScreen.main.bounds.width-32, height: 48)
}
.background(Color(.black))
.cornerRadius(10)
.padding(.top, 24)
}
}
}
struct PhotosView: View {
@StateObject var viewmodel = PhotosViewModel()
@State private var isDataLoaded = false
var body: some View {
NavigationView {
VStack {
ScrollView {
if let photo = viewmodel.photo {
PhotoCellView(photo: photo)
} else {
ContentUnavailableView("No new images",
systemImage:"photo.stack",
description: Text("Try again later :("))
}
}
}
}
.onAppear {
viewmodel.isLoading = true
let _: () = viewmodel.getRandomPhoto() { result in
switch result {
case .success(let randomPhoto):
print("success ")
case .failure(let error):
print(error)
}
}
viewmodel.isLoading = false
isDataLoaded = true
}
if viewmodel.isLoading {
LoadingView()
}
}
}
func ratePhoto(_ photoRequest: PhotoRateRequest, completion: @escaping (Result<Void,Error>) -> Void) {
guard let rateURL = URL(string: rateURL + "\(String(describing: photoRequest.file_id!))/rate") else {
completion(.failure(NetworkError.invalidURL))
return
}
var request = URLRequest(url: rateURL)
var photoRequestWithId = photoRequest
do {
let token = try Store.shared.getTokenFromStorage()
let userId = try? Store.shared.getUserIdFromToken(token: token)
photoRequestWithId.addId(id: userId!)
request.setValue(token, forHTTPHeaderField: "jwt-token")
} catch let error {
completion(.failure(KeyStoreError.unableToGetData))
return
}
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
if let _ = photoRequestWithId.file_id, let __ = photoRequestWithId.account_id {
do {
request.httpBody = try JSONEncoder().encode(photoRequestWithId)
} catch {
completion(.failure(NetworkError.decodingError))
return
}
} else {
completion(.failure(NetworkError.invalidCredentials))
}
let task = URLSession.shared.dataTask(with: request) { (data, response, error ) in
do {
let result = (response as? HTTPURLResponse)!.statusCode
switch result {
case 200:
completion(.success(()))
return
default:
completion(.failure(NetworkError.invalidResponse))
return
}
}
}
}
func deletePhoto(_ fileId: Int) async throws -> Error? {
guard let url = URL(string: getFileURLById(id: fileId)) else {
return NetworkError.invalidURL
}
var request = URLRequest(url: url)
request.httpMethod = "DELETE"
do {
let token = try Store.shared.getTokenFromStorage()
request.setValue(token, forHTTPHeaderField: "jwt-token")
} catch {
return KeyStoreError.unableToGetData
}
let (_, response) = try await URLSession.shared.data(for: request)
let statusCode = (response as? HTTPURLResponse)?.statusCode
if statusCode != 200 {
return NetworkError.invalidResponse
}
return nil
}