【问题标题】:How to set custom distance Filter , is it possible in Swift?如何设置自定义距离过滤器,在 Swift 中是否可以?
【发布时间】:2017-04-23 23:01:21
【问题描述】:

我是Swift 的新手,我试试这个

How to set accuracy and distance filter when using MKMapView

不知道为什么这段代码不起作用:

//start  mehtod out of scope
lazy var locationManager: CLLocationManager! = {
    let locationManager = CLLocationManager()


    //configeration for  user location access
    //The delegate object to receive update events.
    locationManager.delegate = self
    //The receiver does its best to achieve the requested accuracy
    //locationManager.desiredAccuracy = kCLLocationAccuracyBest
     self.locationManager.distanceFilter = 10.0
    //Requests permission to use location services while the app is in the foreground
    locationManager.requestWhenInUseAuthorization()
    //allow update notification when apps stay on background
    locationManager.allowsBackgroundLocationUpdates = true

    return locationManager
}() 

当我设置时它工作正常:

locationManager.desiredAccuracy = kCLLocationAccuracyBest

那我想要什么:

如果用户改变她的位置然后连续 15 分钟调用一个方法,我想在每 250 米后获取 LAT 和 LONG

 pushLocation(lat:double,long:double)

【问题讨论】:

  • 您是否在项目设置中设置了所有必需的权限?
  • 是的,当我设置 locationManager.desiredAccuracy = kCLLocationAccuracyBest 时它工作正常
  • 你想要什么距离过滤器?分享确切的描述
  • @ShobhakarTiwari 250 米。我要过滤的距离
  • 你想要 250 作为直径

标签: ios swift mapkit


【解决方案1】:

这是我正在使用的代码 - 全部在 Swift 3.0 中。

locationManager 的此设置将负责您所追求的距离过滤和准确性:

lazy var locationManager: CLLocationManager = {
    [unowned self] in
    var _locationManager = CLLocationManager()
    _locationManager.delegate = self
    _locationManager.desiredAccuracy = [Your Value For trackingAccuracy - see below]
    _locationManager.distanceFilter = [Your Value For the filter i.e., 250 for 250 meters]
    _locationManager.allowsBackgroundLocationUpdates = true
    _locationManager.pausesLocationUpdatesAutomatically = false 
    _locationManager.activityType = .fitness
    return _locationManager
    }()

精度设置来自位置管理器中的预定义设置,例如 kCLLocationAccuracyNearestTenMeters 或 kCLLocationAccuracyHundredMeters。

即使您的应用不在前台,允许后台更新的选项也能让您获得新积分。如果手机不时停止移动,则需要自动关闭暂停 - 否则,如果您的用户停止休息 5 分钟并且不会重新打开它,它将自动关闭捕获 - 您必须在“重做。

授权状态应单独检查如下,以便您可以在尚未获得授权的情况下请求授权:

    if CLLocationManager.authorizationStatus() != .authorizedAlways     // Check authorization for location tracking
    {
        locationManager.requestAlwaysAuthorization()                    // Will callbackdidChange... once user responds
    } else {
        locationManager.startUpdatingLocation()
    }

由于获得授权存在延迟,如果您必须提出请求,则需要等待请求它开始更新位置,直到您收到 locationManager 的回复,您可以执行以下操作:

@nonobjc func locationManager(manager: CLLocationManager!, didChangeAuthorizationStatus status: CLAuthorizationStatus) {
    switch status
    {
    case .authorizedAlways:
        locationManager.startUpdatingLocation()

    default:
        [Whatever you want to do - you can't get locations]
    }
}

我需要 .authorizedAlways,根据您的用例,您也许可以摆脱 .authorizedWhenInUse。

我根据检查 locationManager 传回给我的位置中的准确度字段添加了一个额外的准确度过滤器。请注意,有单独的水平和垂直精度值(以米为单位的置信距离);如果你想使用海拔值,你需要注意第二个精度值,因为海拔在 iPhone 中本来就不太准确。

我还检查了新点是否是在前一点之后捕获的 - 有时会出现乱序值并指示“有问题”的值。我已经读到您可能会得到小于 0 的准确度值来表示问题,因此您可能需要在使用该位置之前进行检查,尽管我还没有看到这个问题。代码如下:

// Called back by location manager - passes arrays of new CLLocation points captured. With distanceFilter set to 250, this will get called for a change of 250M.  You'll want to save the value for your timed pushLocation function.

// This function needs to be trim as it continues to be called when TrailHead is in the background and, if 
// we take too long we'll get killed by iOS.

var savePosition: CLLocationCoordinate2D?
private var latestTimeProcessed = Date()  // Initialize to ensure any point accepted received after initialization

func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation])
{
    for location in locations {
        if latestTimeProcessed.compare(location.timeStamp) == .orderedAscending        // Out of seq indicates a locationManager problem - discard
            && location.horizontalAccuracy < [Whatever accuracy limit you want to use]    // Applying a user-selected quality filter
        {
            latestTimeProcessed = location.timeStamp      // Used to discard any earlier timestamped points returned by the location manager
            [PROCESS THE POSITION HERE - E.G.]

            savePosition = locations.last

        }
    }
}

就推送更新而言,我会添加一个计时器

private var myTimer: Timer? = nil  
private var longInterval = 900.0     // 900 seconds = 15 minutes

override func viewDidLoad()
{
    ....
        myTimer = Timer(timeInterval: timerInterval, target: myself, selector: #selector(myself.pushLocation), userInfo: nil, repeats: true)
        RunLoop.current.add(myTimer!, forMode: RunLoopMode.commonModes)
    ....
}

pushLocation(lat:double,long:double){
    [Use savePosition.latitude, savePosition.longitude]
}

希望这会有所帮助...

【讨论】:

  • 如果用户改变她的位置然后连续 15 分钟调用方法 pushLocation(lat:double,long:double),我想在每 250 米后获取 LAT 和 LONG跨度>
  • 我已经注意到您在第一个代码块中为 250 M 更改设置过滤器的位置,并在编辑我的答案的最终代码块中添加了计时器代码我发帖。
  • latestTimeProcessed 我不明白如何声明它
  • 只是一个日期属性;声明和初始化它我使用: private var latestTimeProcessed = Date() 我将在上面添加。
  • 很高兴我能帮上忙——希望 Apple 让他们的 API 文档在这样的事情上更有帮助,但在他们分享我们通过 StackExchange 学到的东西之前是关键(这就是我找到将这些东西放在一起的地方) .
【解决方案2】:

根据您的问题,您想在每 250 米 后获得 LATLONG 吗? 所以这里是Objective C Code :(感谢链接:https://stackoverflow.com/a/39996989/3400991)

首先调用此方法并存储此新位置,然后当任何(LAT,LONG)与此存储位置匹配时,您需要不断查找其他纬度和经度,则意味着您已经行驶了250米:

这里是 SWIFT3.0 代码:

func locationByMovingDistance(distanceMeters: Double, withBearing bearingDegrees: CLLocationDirection) -> CLLocation {
    let distanceRadians: Double = distanceMeters / (6372797.6)
        // earth radius in meters
    let bearingRadians: Double = bearingDegrees * M_PI / 180
    var lat1: Float = self.coordinate.latitude * M_PI / 180
    var lon1: Float = self.coordinate.longitude * M_PI / 180
    var lat2: Float = asin(sin(lat1) * cos(distanceRadians) + cos(lat1) * sin(distanceRadians) * cos(bearingRadians))
    var lon2: Float = lon1 + atan2(sin(bearingRadians) * sin(distanceRadians) * cos(lat1), cos(distanceRadians) - sin(lat1) * sin(lat2))
    return CLLocation(latitude: lat2 * 180 / M_PI, longitude: lon2 * 180 / M_PI)
}

如果您有任何进一步的问题,请随时发表评论。希望对您有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-05-06
    • 1970-01-01
    • 2022-11-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-07-12
    相关资源
    最近更新 更多