Ios 将CLLocationCoordinate2D的字符串转换为数组

Ios 将CLLocationCoordinate2D的字符串转换为数组,ios,swift,firebase,firebase-realtime-database,cllocation,Ios,Swift,Firebase,Firebase Realtime Database,Cllocation,更新之前的问题以获得更好的解释 var breadcrumbs: [CLLocationCoordinate2D] = [] var path: [CLLocationCoordinate2D] = [] 每10秒调用一次,将CLLocationCoordinate2D附加到数组中 func addBreadcrumb(){ let speed = (locationmanager.location?.speed)! let speedRounded = speed.round

更新之前的问题以获得更好的解释

var breadcrumbs: [CLLocationCoordinate2D] = []
var path: [CLLocationCoordinate2D] = []
每10秒调用一次,将CLLocationCoordinate2D附加到数组中

func addBreadcrumb(){
    let speed = (locationmanager.location?.speed)!
    let speedRounded = speed.roundTo(places: 4)
    let crumbCoordinate = locationmanager.location?.coordinate

    breadcrumbs.append(crumbCoordinate!)
    tripSpeeds.append(speedRounded)
}
用户完成行程后,点击一个按钮,调用以下函数。这会将数据输入firebase。我将保存为字符串,否则会出现错误

func submitTripPath(){
    let tripID: String? = tripUID
    let tripPath = String(describing: breadcrumbs) //This may be the problem
    let speeds = String(describing: tripSpeeds)

    var ref: FIRDatabaseReference!
    ref = FIRDatabase.database().reference()
    let tripRef = ref.child("TripPaths").child(tripID!)
    let tripDictionary = ["routePath" : tripPath, "routeSpeed" : speeds] as [String : Any]
    tripRef.updateChildValues(tripDictionary) { (err, ref) in
        if err != nil {
            print(err!)
            return
        }
    }
}
在另一个屏幕中,我成功地拉出Firebase数据库引用中的坐标字符串

let routePath = dict["routePath"] as! String //This may also be an issue
//output looks like this
"[__C.CLLocationCoordinate2D(latitude: 37.337728550000001, longitude: -122.02796406), __C.CLLocationCoordinate2D(latitude: 37.337716899999997, longitude: -122.02835139), __C.CLLocationCoordinate2D(latitude: 37.337694319999997, longitude: -122.0287719)]"
我希望能够将其用作CLLocationCoordinate2D中的数组,以使用以下命令绘制多段线我无法将此字符串转换为可用的CLLocationCoordinate2D数组。

    if (path.count > 1) {
        let sourceIndex = path.count - 1
        let destinationIndex = path.count - 2

        let c1 = path[sourceIndex]
        let c2 = path[destinationIndex]

        var a = [c1, c2]
        let polyline = MKPolyline(coordinates: &a, count: a.count)
        mapContainerView.add(polyline)
    }

如果您对保存原始阵列、从Firebase中提取或转换字符串有任何建议,请告诉我。如果您需要其他代码作为参考,请告诉我。

所以我认为您最大的问题是您正在使用字符串(描述:)。这将添加您看到的那些奇怪的类名。您最好为lat/long提出自己的编码方法,然后对其进行反向编码以获取您的位置数据。因此,下面这样的方法将是一种更好的方法

func submitTripPath(){
    let tripID: String? = tripUID
    let tripPath = encodeCoordinates(coords: breadcrumbs)
    let speeds = String(describing: tripSpeeds)

    var ref: FIRDatabaseReference!
    ref = FIRDatabase.database().reference()
    let tripRef = ref.child("TripPaths").child(tripID!)
    let tripDictionary = ["routePath" : tripPath, "routeSpeed" : speeds] as [String : Any]
    tripRef.updateChildValues(tripDictionary) { (err, ref) in
        if err != nil {
            print(err!)
            return
        }
    }
}

func encodeCoordinates(coords: [CLLocationCoordinate2D]) -> String {
    let flattenedCoords: [String] = coords.map { coord -> String in "\(coord.latitude):\(coord.longitude)" }
    let encodedString: String = flattenedCoords.joined(separator: ",")
    return encodedString
}

func decodeCoordinates(encodedString: String) -> [CLLocationCoordinate2D] {
    let flattenedCoords: [String] = encodedString.components(separatedBy: ",")
    let coords: [CLLocationCoordinate2D] = flattenedCoords.map { coord -> CLLocationCoordinate2D in
        let split = coord.components(separatedBy: ":")
        if split.count == 2 {
            let latitude: Double = Double(split[0]) ?? 0
            let longitude: Double = Double(split[1]) ?? 0
            return CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
        } else {
            return CLLocationCoordinate2D()
        }
    }
    return coords
}

我只是使用逗号和冒号进行编码,但您可以很容易地使用其他东西。

所以我认为您最大的问题是使用字符串(描述:)。这将添加您看到的那些奇怪的类名。您最好为lat/long提出自己的编码方法,然后对其进行反向编码以获取您的位置数据。因此,下面这样的方法将是一种更好的方法

func submitTripPath(){
    let tripID: String? = tripUID
    let tripPath = encodeCoordinates(coords: breadcrumbs)
    let speeds = String(describing: tripSpeeds)

    var ref: FIRDatabaseReference!
    ref = FIRDatabase.database().reference()
    let tripRef = ref.child("TripPaths").child(tripID!)
    let tripDictionary = ["routePath" : tripPath, "routeSpeed" : speeds] as [String : Any]
    tripRef.updateChildValues(tripDictionary) { (err, ref) in
        if err != nil {
            print(err!)
            return
        }
    }
}

func encodeCoordinates(coords: [CLLocationCoordinate2D]) -> String {
    let flattenedCoords: [String] = coords.map { coord -> String in "\(coord.latitude):\(coord.longitude)" }
    let encodedString: String = flattenedCoords.joined(separator: ",")
    return encodedString
}

func decodeCoordinates(encodedString: String) -> [CLLocationCoordinate2D] {
    let flattenedCoords: [String] = encodedString.components(separatedBy: ",")
    let coords: [CLLocationCoordinate2D] = flattenedCoords.map { coord -> CLLocationCoordinate2D in
        let split = coord.components(separatedBy: ":")
        if split.count == 2 {
            let latitude: Double = Double(split[0]) ?? 0
            let longitude: Double = Double(split[1]) ?? 0
            return CLLocationCoordinate2D(latitude: latitude, longitude: longitude)
        } else {
            return CLLocationCoordinate2D()
        }
    }
    return coords
}

我只是使用逗号和冒号进行编码,但您可以很容易地使用其他内容。

可能的重复我不认为这是重复的,因为我在单个字符串中有一个包含许多CLLocationCoordiant2D的字符串,而不是每个字符串的字符串。。。我可以从中提取lat/lng。我已经用单独的注释来做了。如果你知道我如何将这个答案应用到我的问题上,你能进一步解释一下吗?这个字符串最初是如何创建的?最好从一个更好的编码方法开始。@rmaddy在另一个屏幕中跟踪用户的路径,创建一个CLLocationCoordiant2D数组,并将其作为字符串保存在firebase中。如果尝试将其保存为数组,则会出现错误:由于未捕获的异常“InvalidFirebaseData”而终止应用程序,原因:'(updateChildValues:withCompletionBlock:)无法在0处存储NSConcreteValue类型的对象。只能存储NSNumber、NSString、NSDictionary和NSArray类型的对象。我知道它是一个字符串,但有更好的方法将坐标数组转换为字符串,这将使将字符串转换回坐标数组更加容易。您当前创建字符串的方法使返回非常困难。我想重提你的问题,重点是通过Firebase实现坐标数组往返转换的最佳方法。包括您当前创建字符串的相关代码以及您解码字符串的尝试。可能的重复我不认为这是重复的,因为我在单个字符串中有一个包含许多CLLocationCoordiant2D的字符串,而不是每个字符串的字符串。。。我可以从中提取lat/lng。我已经用单独的注释来做了。如果你知道我如何将这个答案应用到我的问题上,你能进一步解释一下吗?这个字符串最初是如何创建的?最好从一个更好的编码方法开始。@rmaddy在另一个屏幕中跟踪用户的路径,创建一个CLLocationCoordiant2D数组,并将其作为字符串保存在firebase中。如果尝试将其保存为数组,则会出现错误:由于未捕获的异常“InvalidFirebaseData”而终止应用程序,原因:'(updateChildValues:withCompletionBlock:)无法在0处存储NSConcreteValue类型的对象。只能存储NSNumber、NSString、NSDictionary和NSArray类型的对象。我知道它是一个字符串,但有更好的方法将坐标数组转换为字符串,这将使将字符串转换回坐标数组更加容易。您当前创建字符串的方法使返回非常困难。我想重提你的问题,重点是通过Firebase实现坐标数组往返转换的最佳方法。包括您当前创建字符串的相关代码以及您解码字符串的尝试。尤其是在decode中,您可能希望确保decode始终返回有效的CLLocationCoordiant2D,而不仅仅是一个空的init。这看起来很有趣。它工作得很好,将数据放入数据库,但使用DecodeCordinates不起作用,因为它显示了一个错误:无法将'String'类型的值转换为预期的参数类型'NSCoder',来自,让routePath=dict[“routePath”]as!firebase引用中的字符串。将其作为NSCoder取出也不起作用。您应该能够按照以下要求执行
let routePath:String=dict[“routePath”]!字符串路径=解码坐标(encodedString:routePath)
从数据库中取出后,
打印(routePath)
是什么样子?理论上应该是“180:180,90:90”。你的答案是正确的!谢谢你在这件事上帮了我的忙,并一直支持我!我接受了这个答案。我相信这个答案在将来会帮助很多人。实现它需要记住的一件事是,我在示例代码中很少进行错误检查。尤其是在decode中,您可能希望确保decode始终返回有效的CLLocationCoordiant2D,而不仅仅是一个空的init。这看起来很有趣。它工作得很好,将数据输入到数据库中,但是使用decodecordinations并不能像它显示的那样工作