如何重构MapView中的位置相关计算属性为更简洁实现?
优化MapView中位置信息计算属性的代码结构
当然可以优化,下面提供几种简洁且可复用的方案,帮你减少重复代码、提升结构整洁度:
方案1:给CLLocation添加扩展,封装格式化逻辑
把位置属性的格式化逻辑封装到CLLocation的扩展里,这样不仅当前View能用,其他需要处理位置格式化的地方也能复用:
import CoreLocation extension CLLocation { // 格式化纬度 var formattedLatitude: String { "\(coordinate.latitude)" } // 格式化经度 var formattedLongitude: String { "\(coordinate.longitude)" } // 格式化海拔 var formattedAltitude: String { "\(altitude)" } // 格式化楼层 var formattedFloor: String { String(describing: floor) } // 格式化速度 var formattedSpeed: String { "\(speed)" } // 格式化速度精度 var formattedSpeedAccuracy: String { "\(speedAccuracy)" } }
然后在MapView里简化计算属性,统一处理可选值:
struct MapView: View { @StateObject var locationManager = LocationManager() // 统一封装lastLocation的可选访问 private var currentLocation: CLLocation? { locationManager.lastLocation } var userLatitude: String { currentLocation?.formattedLatitude ?? "0" } var userLongitude: String { currentLocation?.formattedLongitude ?? "0" } var userAltitude: String { currentLocation?.formattedAltitude ?? "0" } var userFloor: String { currentLocation?.formattedFloor ?? "nil" } var userSpeed: String { currentLocation?.formattedSpeed ?? "0" } var userSpeedAccuracy: String { currentLocation?.formattedSpeedAccuracy ?? "0" } var body: some View { // 原有代码 } }
方案2:用结构体封装所有位置信息
把所有格式化后的位置值整合到一个自定义结构体中,让MapView的代码更简洁,访问位置信息时更统一:
import CoreLocation struct FormattedLocationInfo { let latitude: String let longitude: String let altitude: String let floor: String let speed: String let speedAccuracy: String init(location: CLLocation?) { self.latitude = "\(location?.coordinate.latitude ?? 0)" self.longitude = "\(location?.coordinate.longitude ?? 0)" self.altitude = "\(location?.altitude ?? 0)" self.floor = String(describing: location?.floor) self.speed = "\(location?.speed ?? 0)" self.speedAccuracy = "\(location?.speedAccuracy ?? 0)" } }
然后在MapView里只需要一个计算属性:
struct MapView: View { @StateObject var locationManager = LocationManager() // 一次性生成所有格式化后的位置信息 private var formattedLocation: FormattedLocationInfo { FormattedLocationInfo(location: locationManager.lastLocation) } var body: some View { // 使用时直接调用,比如Text(formattedLocation.latitude) // 原有代码 } }
这种方式的好处是,后续如果需要添加新的位置属性,只需要修改FormattedLocationInfo即可,MapView里不需要额外改动。
方案3:用通用方法统一处理可选值和格式化
如果不想定义额外类型,也可以写两个通用方法,统一处理可选位置的访问和格式化逻辑:
struct MapView: View { @StateObject var locationManager = LocationManager() // 处理非可选属性的格式化 private func formatNonOptional<T>(_ keyPath: KeyPath<CLLocation, T>, defaultValue: String) -> String { guard let location = locationManager.lastLocation else { return defaultValue } return "\(location[keyPath: keyPath])" } // 处理可选属性的格式化 private func formatOptional<T>(_ keyPath: KeyPath<CLLocation, T?>) -> String { guard let location = locationManager.lastLocation else { return "nil" } return String(describing: location[keyPath: keyPath]) } var userLatitude: String { formatNonOptional(\.coordinate.latitude, defaultValue: "0") } var userLongitude: String { formatNonOptional(\.coordinate.longitude, defaultValue: "0") } var userAltitude: String { formatNonOptional(\.altitude, defaultValue: "0") } var userFloor: String { formatOptional(\.floor) } var userSpeed: String { formatNonOptional(\.speed, defaultValue: "0") } var userSpeedAccuracy: String { formatNonOptional(\.speedAccuracy, defaultValue: "0") } var body: some View { // 原有代码 } }
这种方案能快速减少重复的guard let和可选链代码,让单个计算属性的逻辑更清晰。
内容的提问来源于stack exchange,提问作者theMap
相关产品推荐
相关产品推荐

