SwiftUI中UserDefaults存储镜头焦距值不一致问题求助
SwiftUI中UserDefaults存储镜头焦距值不一致问题求助
大家好,我在SwiftUI里开发了一个计算相机视野的视图,用户可以通过滑块或步进器调整镜头焦距(lensFocalLength),需求是用户调整后的值能被保存,下次打开视图时自动加载上次的设置。我用了UserDefaults来实现持久化,但现在遇到了一个很头疼的问题:比如用户把焦距设为100mm,下次打开视图时显示的却是98、105这类接近但不准确的数值,完全不一致,试了好几次都是这样,找不到原因。
以下是我的完整代码,麻烦各位帮忙排查一下问题所在:
import SwiftUI import Foundation struct Calc2View: View { @State private var lensFocalLength: Double let sensorWidth = 36.0 // Full frame sensor width init() { _lensFocalLength = State(initialValue: UserDefaults.standard.double(forKey: "selectedLens") != 0 ? UserDefaults.standard.double(forKey: "selectedLens") : 50.0) } var body: some View { NavigationView { ScrollView { VStack { HStack{ Text("Camera input") .font(.headline) .fontWeight(.bold) Spacer() } Divider() VStack{ HStack { Text("Lens") .font(.headline) .multilineTextAlignment(.leading) Spacer() Text("\(lensFocalLength, specifier: "%.0f") mm") Spacer() Stepper("", value: $lensFocalLength, in: 1...1000) } HStack { Slider(value: $lensFocalLength, in: 10...1000, step: 1) .accentColor(.blue) } } .onChange(of: lensFocalLength) { newValue, _ in UserDefaults.standard.set(newValue, forKey: "selectedLens") } if lensFocalLength > 0 { let fov = 2 * atan(sensorWidth / (2 * lensFocalLength)) * (180 / .pi) // New formula let humanFOV = 200.0 let fovealFOV = 120.0 let nikonSensorWidth = 23.6 let canonSensorWidth = 22.3 let microFourThirdsSensorWidth = 17.3 let nikonFOV = 2 * atan(nikonSensorWidth / (2 * lensFocalLength)) * (180 / .pi) let canonFOV = 2 * atan(canonSensorWidth / (2 * lensFocalLength)) * (180 / .pi) let microFourThirdsFOV = 2 * atan(microFourThirdsSensorWidth / (2 * lensFocalLength)) * (180 / .pi) let nikonEquivalentFocalLength = lensFocalLength / 1.5 let canonEquivalentFocalLength = lensFocalLength / 1.6 let microFourThirdsEquivalentFocalLength = lensFocalLength / 2.0 VStack(alignment: .leading) { Divider() Color.clear.frame(height: 5) VStack(alignment: .leading){ Text("Lens Field of View:") .font(.headline) .fontWeight(.bold) HStack { Text("FullFrame") Spacer() Text("\(fov, specifier: "%.1f") degrees") } HStack { Text("APS-C") Spacer() Text("\(nikonFOV, specifier: "%.1f") degrees") } HStack { Text("APS-C Canon") Spacer() Text("\(canonFOV, specifier: "%.1f") degrees") } HStack { Text("Micro 4/3rd") Spacer() Text("\(microFourThirdsFOV, specifier: "%.1f") degrees") } Divider() Color.clear.frame(height: 5) Text("Equivalent lens:") .font(.headline) .fontWeight(.bold) HStack { Text("Full Frame") Spacer() Text("\(lensFocalLength, specifier: "%.0f") mm") } HStack { Text("APS-C") Spacer() Text("\(nikonEquivalentFocalLength, specifier: "%.0f") mm") } HStack { Text("APS-C Canon") Spacer() Text("\(canonEquivalentFocalLength, specifier: "%.0f") mm") } HStack { Text("Micro 4/3rd") Spacer() Text("\(microFourThirdsEquivalentFocalLength, specifier: "%.0f") mm") } Divider() Color.clear.frame(height: 5) Text("Full Frame Field of View:") .font(.headline) .fontWeight(.bold) Color.clear.frame(height: 5) } } VStack { ZStack { FOVTriangle(fov: humanFOV) .fill(Color.green.opacity(0.5)) FOVTriangle(fov: fovealFOV) .fill(Color.blue.opacity(0.5)) FOVTriangle(fov: fov) .fill(Color.pink.opacity(1.0)) } .frame(height: 200) .frame(width: 200) Image(systemName: "camera") // Add SF Symbol .font(.largeTitle) Spacer() HStack{ Image(systemName: "square.fill") .foregroundColor(.green) .opacity(0.5) .font(.system(size: 20)) Text("FoV both eyes") Spacer() Image(systemName: "square.fill") .foregroundColor(.red) .opacity(1.0) .font(.system(size: 20)) Text("Lens") Spacer() HStack{ Image(systemName: "square.fill") .foregroundColor(.blue) .opacity(0.5) .font(.system(size: 20)) Text("Binocular") } } } } else { Text("Please enter a valid focal length") } } .navigationTitle("Field of View") .navigationBarTitleDisplayMode(.inline) .padding() } } .navigationViewStyle(.stack) } } struct FOVTriangle: Shape { var fov: Double func path(in rect: CGRect) -> Path { var path = Path() let radians = fov * (.pi / 180.0) let height = Double(rect.height) / 3.1 let width = tan(radians / 2) * height / 3.1 let startPoint = CGPoint(x: rect.midX, y: rect.maxY) let leftPoint = CGPoint(x: rect.midX - CGFloat(width), y: 0) let rightPoint = CGPoint(x: rect.midX + CGFloat(width), y: 0) path.move(to: startPoint) path.addLine(to: leftPoint) path.addLine(to: rightPoint) path.addLine(to: startPoint) return path } } #Preview { Calc2View() }
试了好多次都没解决这个问题,实在没办法了,希望各位能帮我找出问题所在,谢谢大家!
备注:内容来源于stack exchange,提问作者Serge Benati
相关产品推荐
相关产品推荐

