使用 CLLocationManager 的 Swift 3 信标监控

标签 swift background monitoring locationmanager beacon

这是我尝试使用 CLLocationManager 进行信标区域监控的简化版本。

我需要通知多个(少于20个)区域的进入/退出事件。

即使在后台,我也能获得一致的位置输入事件。在客户端 View 或后台时,我没有在前台收到退出事件。

有一次我确实成功地在后台获得了退出事件,但我没有获得可变数量的信标区域来收听。

此代码中是否存在任何总体约定/逻辑缺陷?

//------------------
/* Client View Controller - Main Profile View */
class ClientVC: UIViewController, ClientVC_Preferences_Protocol, OpenPreferencesProtocol, ClientVCProtocol {

	/* Reference to AppDelegate file where location manager resides */
	let appDelegate = UIApplication.shared.delegate as! AppDelegate
	override func viewDidLoad(){

		// .. Obtain some beacon info - not shown

		for beacon in beacons {
	        /* Create a region for each beacon and start monitoring */
	        var region = CLBeaconRegion(proximityUUID: UUID(uuidString:beacon.UUID)!, identifier: beacon.Identifier)
	        region.notifyEntryStateOnDisplay = true
	        region.notifyOnExit = true
	        region.notifyOnEntry = true
	        self.appDelegate.locationManager.startMonitoring(for: region)
	    }
	}

	/* Protocol function to alert client when exit event occured */
	func alertClient(businessName:String) {
        
        let notification = UILocalNotification()
        notification.alertBody = "Did you leave " + businessName + "?"
        UIApplication.shared.presentLocalNotificationNow(notification)
        
        let alertController = UIAlertController(title: businessName, message: "Did you leave?", preferredStyle: .alert)
        
        let okAction = UIAlertAction(title: "Yes, I Left!", style: UIAlertActionStyle.default) {
            UIAlertAction in
        	// .. Do some firebase work - not shown
        }

        let cancelAction = UIAlertAction(title: "No, I'm Here!", style: UIAlertActionStyle.cancel) {
            UIAlertAction in
            // .. Do some firebase work - not shown
        }
        
        alertController.addAction(okAction)
        alertController.addAction(cancelAction)
        
        self.present(alertController, animated:true, completion:nil)
    }
}

//------------------
/* AppDelegate */

/* Protocol connected to Client View Controller */
protocol ClientVCProtocol{
    func alertClient(businessName:String) /* Displays alert to client when exiting the region */
    func reloadTableView() /* Refreshes table view */
}

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CLLocationManagerDelegate {

	/* Delegate for ClientVC Protocol - used to call methods */
	var ClientVCDelegate:ClientVCProtocol?

	/* Instantiate location manager */
	var locationManager = CLLocationManager()

	/* Triggered by entering a region */
	func locationManager(_ manager: CLLocationManager, didEnterRegion region: CLRegion) {
        print("Enter event " + region.identifier)
        // .. Do some firebase work - not shown
	}

	/* Triggered by exiting a region */
	func locationManager(_ manager: CLLocationManager, didExitRegion region: CLRegion) {

		/* Break set on this line to ensure whether or not this function is called */
		print("Exit Attempt") 

		/* Gets business name associated with region and calls protocol function to ClientVC */
		if let beaconRegion = region as? CLBeaconRegion {
            self.getBusinessName(region: region){
                (result: String) in
                print("Exit event " + region.identifier)
                self.ClientVCDelegate?.alertClient(businessName:result)
            }
        }
	}

	/* Runs when application finishes launching - configures location manager */
	func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {        
        self.fbRef = Database.database().reference()
        UIApplication.shared.registerUserNotificationSettings(
            UIUserNotificationSettings(types: .alert, categories: nil))
        
        /* Not sure how relevent all of these calls are */
        locationManager.delegate = self
        locationManager.desiredAccuracy = kCLLocationAccuracyBest
        locationManager.distanceFilter = 2000
        if #available(iOS 9.0, *) {
            locationManager.allowsBackgroundLocationUpdates = true
        }
        locationManager.startMonitoringSignificantLocationChanges()
        locationManager.pausesLocationUpdatesAutomatically = true
        locationManager.requestAlwaysAuthorization()
      
        return true
    }
}

最佳答案

一个问题是您只在 ViewController 中设置要监视的区域,如果您希望后台进入/退出事件火。

了解 CoreLocation 会跟踪您正在监控的区域,并会在区域状态发生变化时自动将您的应用程序启动到后台。但是,如果您设置 CLLocationManager、区域并在 AppDelegate 的 didFinishLaunching 方法中设置委托(delegate),它只会触发回调。

关于使用 CLLocationManager 的 Swift 3 信标监控,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44184041/

相关文章:

ios - 如何访问扩展类中自定义单元格的文本字段?

swift - 点击远程通知后导航栏丢失

css - 背景图片大小调整问题

android - 退出应用程序后按钮背景更改为默认

jQuery - 视差效果 - 将背景位置更改为 "Center Center"

linux - 如何将时钟周期中的进程 cpu 使用率转换为百分比?

monitoring - 如何使用 C# 从 Bios 获取 CPU 温度信息?

ios - 如何从 firebase 存储 Swift 4 ios 检索图像

Swift - 在 TableView 中更改标题部分的垂直对齐方式

ruby-on-rails - 如何使用monit监控nginx乘客