ios - SwiftUI:使用数据库连接实现评级视图
问题描述
在我的应用程序中,我希望用户给电影评分。电影是从 REST 接口加载的,评级应该存储在本地。问题是我不知道如何保持用户的新评级。
我可以从我的数据库中加载评级并更改 MovieRow 中的值,但我不知道如何获取回调以保存更改后的评级。
这是我所拥有的:
struct RatingView: View {
@Binding var rating: Int
var maximumRating = 5
var offImage: Image?
var onImage = Image(systemName: "star.fill")
var offColor = Color.gray
var onColor = Color.yellow
var body: some View {
HStack {
ForEach(1..<maximumRating + 1) { number in
self.image(for: number)
.foregroundColor(number > self.rating ? self.offColor : self.onColor)
.onTapGesture {
self.rating = number
}
}
}
}
func image(for number: Int) -> Image {
if number > rating {
return offImage ?? onImage
} else {
return onImage
}
}
}
struct MovieRow: SwiftUI.View {
let movie: Movie
@State var ownRating: Int
var body: some SwiftUI.View {
ZStack(alignment: Alignment(horizontal: .leading, vertical: .bottom)) {
ZStack(alignment: Alignment(horizontal: .trailing, vertical: .top
)) {
KFImage(movie.fullPosterURL)
.cancelOnDisappear(true)
.resizable()
.frame(height: 250)
RatingView(rating: $ownRating)
.padding([.top, .trailing], 20.0)
}
Text(movie.title)
.font(.largeTitle)
.padding(.all)
.background(Color(.darkGray)
.opacity(0.5))
.foregroundColor(.white)
}
}
}
struct MovieListView: View {
@ObservedObject var viewModel = MovieViewModel()
var body: some View {
List{
ForEach(viewModel.movies) { movie in
MovieRow(movie: movie, ownRating: self.viewModel.ratingForMovieId(id: movie.id))
.listRowInsets(EdgeInsets())
}
}
}
}
class MovieViewModel: ObservableObject{
private let provider: NetworkManager?
private let ratingModel = RatingModel()
@Published var movies = [Movie]()
init(provider: NetworkManager? = NetworkManager(), movies: [Movie] = []) {
self.provider = provider
self.movies = movies
loadNewMovies()
}
func loadNewMovies(){
provider?.getNewMovies(page: 1) {[weak self] movies in
print("\(movies.count) new movies loaded")
self?.movies.removeAll()
self?.movies.append(contentsOf: movies)}
}
func ratingForMovieId(id: Int)->Int{
return ratingModel.ratingForMovieId(movieId: id)
}
}
class RatingModel{
let realm = try! Realm()
func ratingForMovieId(movieId: Int)->Int{
let result = realm.objects(MovieRating.self).filter("movieId = %@", movieId)
guard let movieRating = result.first else{
return 0
}
return movieRating.rating
}
func updateRating(movieId: Int, rating: Int){
try! realm.write {
realm.create(MovieRating.self, value: ["movieId": movieId, "rating": rating], update: .modified)
}
}
}
解决方案
要对此给出具体答案,您必须提供有关数据库/ViewModel/REST-Interface 的更多信息
有些事情可能会解决您的@State var ownRating: Int
问题@Binding var ownRating: Int
。State
旨在仅在视图中使用并应声明private
,Binding
将传递与ViewModel
何时onTapGesture
激活参考您ViewModel
并从那里使用 REST 接口预先建立的 save()/update()。
如果您的保存/更新方法需要对象/id 保持不变,您可能必须将整个Movie
对象或id
变量传递给。RatingView
评级更改时刷新的 UI 取决于发生某事的“ping”或“通知”。SwiftUI 及其教程在这方面严重依赖 CoreData。
我对 Realm 不熟悉,但这是我可以收集到的。Realm
有NotificationTokens
这将为可观察对象中的 SwiftUI 更新提供所需的通知。
获取 ListView 的对象 -如何在 SwiftUI 中使用 Realm
入门指南 - https://realm.io/docs/swift/latest/
带有 UITableView 查询代码的教程应该是您所需要的 - https://academy.realm.io/posts/meetup-jp-simard-mastering-realm-notifications/
observed
使用Realm 对象对 ListView 进行故障排除-将 Realm 与 SwiftUI 一起使用时索引越界
创建领域数据模型并保存 - https://learnappmaking.com/realm-database-swift-getting-started/
您应该使用标准 CRUD 方法创建一个 ObservableObject。
Movie
来自 UI 的对象 ->在 Realm 中 ->使用来自 Realm 的新查询ViewModel.create(newMovie: Movie)
通知/保存@Published var movies
在ViewModel
init()
Retrieve [Movie]
from Realm
-> setup NotifiationToken
to observe
and @Published var movies
with the new query from Realm
从 UI 更新 Movie.rating -> Realm 中的 ViewModel.update(updatedMovie)->@Published var movies
使用来自 Realm 的新查询通知/更新
删除的工作方式与其他方式相同。
关于如何持久化有很多不同的方法,这当然不是最有效的,因为它每次都会检索整个查询,但它应该让你开始。NotificationToken 似乎支持更新到正确的字母NotificationToken.observer
。
专门针对您的代码。当用户onTapGesture
使用您应该引用的新评级viewModel.update(updatedMovie: updatedMovie)
时,当视图movies
从NotificationToken
.
推荐阅读
- amazon-web-services - How can I import data from Amazon RDS (MySQL) and render it on my S3 static website?
- python-3.x - 创建一个新文件夹和文件,并使它们在所有应用程序脚本 PyQt5 中可读
- docker-compose - docker-compose for portainer with traefik v2 gives "failure: unable to retrieve server settings and status"
- javascript - 在工具提示的“标题属性”中显示“今天日期” – Bootstrap
- php - 如何在 laravel 7 上设置 vue 模板
- python - 如何从另一个 python 脚本将网站地址传递给 SpiderClass
- python - /pembayaran/ ModelForm 处的 ValueError 未指定模型类。姜戈
- function - Kotlin 列表中的 groupby 和 foreach
- python - 按下按钮时 gif 不播放 PyQt5
- c - 使用逻辑运算符返回值