微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

iOS13做一个后台处理器来更新位置

如何解决iOS13做一个后台处理器来更新位置

我知道我不是唯一遇到此问题的人,

基本上,SwiftUI似乎无法请求位置总是,即使它位于info.plist中,您也必须稍后再对其进行调用(我已完成)。

我可以看到的问题是,人们不会将其从使用应用程序时更改为始终使用。

那么如何使后台处理器不断更新呢? -我看到Apple允许执行所有后台任务

我的信息.plist

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>CFBundleDevelopmentRegion</key>
    <string>$(DEVELOPMENT_LANGUAGE)</string>
    <key>CFBundleExecutable</key>
    <string>$(EXECUTABLE_NAME)</string>
    <key>CFBundleIdentifier</key>
    <string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
    <key>CFBundleInfoDictionaryVersion</key>
    <string>6.0</string>
    <key>CFBundleName</key>
    <string>$(PRODUCT_NAME)</string>
    <key>CFBundlePackageType</key>
    <string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
    <key>CFBundleShortVersionString</key>
    <string>$(MARKETING_VERSION)</string>
    <key>CFBundLeversion</key>
    <string>1</string>
    <key>LSRequiresIPhoneOS</key>
    <true/>
    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>
    <key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
    <string>Delivering location based Fuel Price Updates,Weather,News &amp; Sports. As well as local offers.</string>
    <key>NSLocationUsageDescription</key>
    <string>Delivering location based Fuel Price Updates,News &amp; Sports. As well as local offers.</string>
    <key>UIApplicationSceneManifest</key>
    <dict>
        <key>UIApplicationSupportsMultipleScenes</key>
        <false/>
        <key>UISceneConfigurations</key>
        <dict>
            <key>UIWindowScenesessionRoleApplication</key>
            <array>
                <dict>
                    <key>UISceneConfigurationName</key>
                    <string>Default Configuration</string>
                    <key>UISceneDelegateClassName</key>
                    <string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
                </dict>
            </array>
        </dict>
    </dict>
    <key>uibackgroundmodes</key>
    <array>
        <string>audio</string>
        <string>location</string>
    </array>
    <key>UILaunchStoryboardName</key>
    <string>LaunchScreen</string>
    <key>UIrequiredDeviceCapabilities</key>
    <array>
        <string>armv7</string>
    </array>
    <key>UIStatusBarHidden</key>
    <false/>
    <key>UIStatusBarStyle</key>
    <string>UIStatusBarStyleLightContent</string>
    <key>UISupportedInterfaceOrientations</key>
    <array>
        <string>UIInterfaceOrientationPortrait</string>
    </array>
    <key>UISupportedInterfaceOrientations~ipad</key>
    <array>
        <string>UIInterfaceOrientationPortrait</string>
        <string>UIInterfaceOrientationPortraitUpsideDown</string>
        <string>UIInterfaceOrientationLandscapeLeft</string>
        <string>UIInterfaceOrientationLandscapeRight</string>
    </array>
</dict>
</plist>


LocationServices.swift

//
//  LocationManager.swift
//  CoreLocationDemo
//
//  Created by Sheikh Bayazid on 7/18/20.
//  copyright © 2020 Sheikh Bayazid. All rights reserved.
//
import Foundation
import CoreLocation
import Combine
import UIKit
import SwiftUI


class LocationManager: NSObject,CLLocationManagerDelegate,ObservableObject {
    private let manager: CLLocationManager
    static var LMlat = 0.0
    static var LMlong = 0.0
    @Published var lastKNownLocation: CLLocation?

    
//    var getLat: String {
//        return "\(lastKNownLocation?.coordinate.latitude)"
//    }
//    var getLon: String {
//        return "\(lastKNownLocation?.coordinate.longitude)"
//    }
    
    
    
    
    func locationManager(_ manager: CLLocationManager,didChangeAuthorization status: CLAuthorizationStatus) {
        if status == .denied{
            print("denied")
        }
        else{
            print("athorized")
            manager.requestLocation()
        }
    }
    
    func start() {
        //manager.requestAlwaysAuthorization()
        manager.requestWhenInUseAuthorization()
        manager.startUpdatingLocation()
    }
    
    init(manager: CLLocationManager = CLLocationManager()) {
        self.manager = manager
        super.init()
    }
    

    
    
    func locationManager(_ manager: CLLocationManager,didFailWithError error: Error) {
        print(error.localizedDescription)
    }
    
    
    func startUpdating() {
        self.manager.delegate = self
       // self.manager.requestAlwaysAuthorization()
        self.manager.requestWhenInUseAuthorization()
        self.manager.startUpdatingLocation()
    }
    
    func locationManager(_ manager: CLLocationManager,didUpdateLocations locations: [CLLocation]) {
        
        lastKNownLocation = locations.last
       // print(lastKNownLocation!.coordinate.latitude)
        self.manager.requestAlwaysAuthorization()
        if(lastKNownLocation!.coordinate.latitude != LocationManager.LMlat && lastKNownLocation!.coordinate.longitude != LocationManager.LMlong)
        {
            print("Last KNown Location Is not a match")
            LocationManager.LMlat = lastKNownLocation!.coordinate.latitude
            LocationManager.LMlong = lastKNownLocation!.coordinate.longitude
            
            updateServerLocation(latitude: LocationManager.LMlat,longitude:  LocationManager.LMlong)
        }
        
        /* Maybe Use in Future Version
        let geoCoder = CLGeocoder()
        let location = CLLocation(latitude: lastKNownLocation!.coordinate.latitude,longitude: lastKNownLocation!.coordinate.longitude)
        geoCoder.reverseGeocodeLocation(location,completionHandler:
            {
                placemarks,error -> Void in

                // Place details
                guard let placeMark = placemarks?.first else { return }

                // Location name
                if let locationName = placeMark.location {
                    print(locationName)
                }
                // Street address
                if let street = placeMark.thoroughfare {
                    print(street)
                }
                // City
                if let city = placeMark.subAdministrativeArea {
                    print(city)
                }
                // Zip code
                if let zip = placeMark.isoCountryCode {
                    print(zip)
                }
                // Country
                if let country = placeMark.country {
                    print(country)
                }
                
        })
        */
        
        
        //showLocation()
    }
    
    func updateServerLocation(latitude:Double,longitude:Double)
    {
        let locationurl = URL(string: "https://EXAMPLE.com/lat=\(latitude)&long=\(longitude)")!
        //print(locationurl )
        // print("location: \(MusicPlayer.uuid ?? "") lat: \(latitude),long: \(longitude)")
         
          URLSession.shared.dataTask(with: locationurl) { (data,res,err) in
          dispatchQueue.main.async{
           // print("The Server should of updated")
            
              //  guard let data = data else { return }
                
            }
             return
        }.resume()
    }
    

//    func showLocation(){
//        print("From showLocation method")
//        print("Latitude: \(getLat)")
//        print("Longitude: \(getLon)")
//    }
    
    
}

以及在我的ContentView.Swift

 var lat: String{
        return "\(location.lastKNownLocation?.coordinate.latitude ?? 0.0)"
    }
    
    var lon: String{
        return "\(location.lastKNownLocation?.coordinate.longitude ?? 0.0)"
    }
    
    init() {
        self.location.startUpdating()
    }

enter image description here

解决方法

我建议您做一些事情来改善对位置的使用。

首先,您似乎对以下事实感到困惑:当您在iOS 13上请求“始终”位置许可时,实际上会提示用户“使用中”。在iOS 13.4上,您可以先请求(并接收)“使用中”,然后再询问“始终”来触发“始终”的提示。在某些情况下,这是正确的方法,但我认为您的应用不是其中之一。

您应该首先观看WWDC 2019上的What's new in Core Location。它说明了临时位置许可的工作原理。

查看您的代码,看来您正在尝试重新发明significant location change monitoring。 Core Location可以为您做到这一点,仅在用户移动500m或更多时才提供更新;听起来很适合您的用例。

另外,根据您的用例,我看不到您实际上需要ios13 +上的“ always”权限;您可以在启用背景模式的情况下使用“使用时”进行重要的位置更改监控。当用户停止音频流时,可以停止后台位置更新。您的应用没有充分的理由可以在用户不播放音频时访问其位置。

请注意,在iOS 12及更早版本中,您将需要“始终”许可,但是由于提到了SwiftUI,因此大概是最低支持的版本是iOS 13。

最后,对于Swift UI,应该在场景委托中创建一个LocationServices之类的对象,并将其注入到环境中,而不是由视图创建。

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。