如何解决在 UserDefaults 更新上更新 swiftUI 视图
我完全是 Swift 和 SwiftUI 的菜鸟,我正在尝试为自己构建一个项目,在那里我可以跟踪我的锻炼并学习一些 Swift。 我遇到的问题是,我有一个视图显示我的所有锻炼课程,并由我在 UserDefaults 中的设置进行格式化。用户可以将此设置更改为“公制”或“英制” 更改此项时,视图应更新以表示这些更改。
我拥有的数据是:
extension WorkoutSession {
@nonobjc public class func fetchRequest() -> NSFetchRequest<WorkoutSession> {
return NSFetchRequest<WorkoutSession>(entityName: "WorkoutSession")
}
@NSManaged public var created_at: Date?
@NSManaged public var id: UUID?
@NSManaged public var reps: Int16
@NSManaged public var sets: Int16
@NSManaged public var updated_at: Date?
@NSManaged public var weight: Double
@NSManaged public var height: Double
@NSManaged public var notes: String?
@NSManaged public var type: Workout?
override public func awakeFromInsert() {
super.awakeFromInsert()
setPrimitiveValue(UUID(),forKey: "id")
setPrimitiveValue(Date(),forKey: "updated_at")
}
override public func willSave() {
super.willSave()
if let updated_at = updated_at {
if updated_at.timeIntervalSince(Date()) > 10.0 {
self.updated_at = Date()
}
} else {
self.updated_at = Date()
}
}
var formattedWeight: String {
var measurement = Measurement(value: self.weight,unit: UserDefaultsWrapper().savedUnitWeight)
let numberFormatter = NumberFormatter()
let measurementFormatter = MeasurementFormatter()
measurement.convert(to:UserDefaultsWrapper().getWeightUnit)
numberFormatter.maximumFractionDigits = 2
measurementFormatter.unitOptions = .providedUnit
measurementFormatter.numberFormatter = numberFormatter
return measurementFormatter.string(from: measurement)
}
// No matter the user defined weight we always save the values in Kilogram so we can convert to anything afterwards
func convertWeightFromUserDefinedUnitToKilogram(weight: Double) -> Double {
let measurement = Measurement(value: weight,unit: UserDefaultsWrapper().getWeightUnit)
return measurement.converted(to: UserDefaultsWrapper().savedUnitWeight).value
}
}
extension WorkoutSession : Identifiable {
}
我还让自己成为 userDefaults 的帮手
import SwiftUI
import Foundation
enum UserDefaultsKeys: String {
case measurementUnit = "measurementUnit"
}
enum measurementUnit: String,CaseIterable {
case metric = "metric"
case imperial = "Imperial"
}
struct UserDefaultsWrapper {
let defaults = UserDefaults.standard
var savedUnitWeight = UnitMass.kilograms
var savedUnitHeight = UnitLength.meters
@AppStorage(UserDefaultsKeys.measurementUnit.rawValue) var selectedUnit: String = measurementUnit.metric.rawValue
var getMeasurementUnit: measurementUnit {
get {
let locale = Locale.current
let systemMeasurementUnit = locale.usesMetricSystem ? measurementUnit.metric : measurementUnit.imperial
return measurementUnit(rawValue: selectedUnit) ?? systemMeasurementUnit
}
set(unit) {
defaults.set(unit.rawValue,forKey: UserDefaultsKeys.measurementUnit.rawValue)
}
}
var getWeightUnit: UnitMass {
switch getMeasurementUnit {
case measurementUnit.imperial:
return UnitMass.pounds
case measurementUnit.metric:
fallthrough
default:
return UnitMass.kilograms
}
}
var getHeightUnit: UnitLength {
switch getMeasurementUnit {
case measurementUnit.imperial:
return UnitLength.feet
case measurementUnit.metric:
fallthrough
default:
return UnitLength.meters
}
}
}
这是风景
import SwiftUI
struct WorkoutDetailView: View {
@Environment(\.managedobjectContext) var moc
@State private var showingAddWorkoutView = false
@Observedobject var workout: Workout
var body: some View {
List {
ForEach(workout.sessionsArray,id: \.id) { session in
Text("\(session.formattedWeight)")
}
.onDelete(
perform: { offsets in
self.removeItems(at: offsets,from: workout)
}
)
}
.listStyle(InsetGroupedListStyle())
.navigationTitle(workout.name ?? "UnkNown Workout")
.navigationBarItems(
leading: EditButton(),trailing:
Button(action: {
self.showingAddWorkoutView = true
}) {
Image(systemName: "plus")
}
)
.sheet(isPresented: $showingAddWorkoutView) {
AddWorkoutSession(workout: workout)
.environment(\.managedobjectContext,moc)
}
}
func removeItems(at offsets: IndexSet,from workout: Workout) {
for offset in offsets {
let sessionToDelete = workout.sessionsArray[offset]
workout.removeFromSessions(sessionToDelete)
moc.delete(sessionToDelete)
}
if moc.hasChanges{
try? moc.save()
}
}
}
问题是,当我将单位从英制更改为公制并返回会话视图时,视图未更新,但是当我返回锻炼视图并再次打开会话视图时,更改就在那里。
如果您需要更多代码,请告诉我。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。