swiftuimkcoordinateregionappstorage

@App Storage and MKCoordinateRegion Function


Is it possible to save an MKCoordinateRegion Value in @App Storage? I tried this. But it doesn't work. I got the error 'No exact matches in call to initializer' .

    @AppStorage("region_key") var region = MKCoordinateRegion(
        center: CLLocationCoordinate2D(latitude: 34.011_286, longitude: -116.166_868),
        span: MKCoordinateSpan(latitudeDelta: 100, longitudeDelta: 100)
    )

Solution

  • Types that get stored in AppStorage have to conform to RawRepresentable. MKCoordinateRegion doesn't do this out-of-the-box, but you can add an extension to add conformance:

    extension MKCoordinateRegion : RawRepresentable {
        struct RepresentableForm : Codable {
            var centerLat : Double
            var centerLong : Double
            var latDelta: Double
            var longDelta : Double
        }
        
        public init?(rawValue: String) {
            guard let data = rawValue.data(using: .utf8), let result = try? JSONDecoder().decode(RepresentableForm.self, from: data)
            else {
                return nil
            }
            self = MKCoordinateRegion(
                center: CLLocationCoordinate2D(latitude: result.centerLat, longitude: result.centerLong),
                span: MKCoordinateSpan(latitudeDelta: result.latDelta, longitudeDelta: result.longDelta)
            )
        }
        
        public var rawValue: String {
            do {
                let data = try JSONEncoder().encode(RepresentableForm(centerLat: self.center.latitude, centerLong: self.center.longitude, latDelta: self.span.latitudeDelta, longDelta: self.span.longitudeDelta))
                return String(data: data, encoding: .utf8) ?? ""
            } catch {
                fatalError()
            }
        }
    }