使用专用 class 用 iPhone 模拟信标

Simulate beacon with iPhone using dedicated class

我想使用 iPhone 发送信标信号。目前它将在 Objective C 中实现,但有计划稍后将其转换为 Swift,因此我也有兴趣找出在此阶段可能遇到的任何重要差异。

在一些研究中,我发现了模拟信标的一些局限性

以及使用 class 而非视图控制器时出现的一些问题的信息,至少在 swift

中是这样

Using iPhone as iBeacon Transmitter

在最后一个 link 中,我找到了 link 到 Swift 的教程,用于使用 iPhone 模拟 iBeacon - 代码放在视图控制器中,它可以在这个地方工作。

https://www.hackingwithswift.com/example-code/location/how-to-make-an-iphone-transmit-an-ibeacon

但是如果我想让应用程序做一些其他事情而不仅仅是传输 BLE 信号,那么从 View Controller 使用 Core Bluetooth 是一个严重的限制。而这些其他东西需要关闭我的控制器。

很快我将尝试为 Objective C 创建一些工作代码,稍后为 Swift 创建一些工作代码,用于发射 BLE 信号并仍然改变可见的视图控制器。但是也许有人做过类似的事情并且能够说出是否有任何问题,就像之前提到的那样

是的,您绝对可以在 ViewController 之外的 iOS 上设置信标传输。下面是一个简单的 Swift class,我曾经在许多项目中这样做过。

但是请注意,虽然您可以使用这样的 class 来做广告,而不管哪个 ViewController 在前台,但如果您的整个应用程序都在后台,则广告将停止。这是 Apple iOS 的限制。有关详细信息,请参阅

  import Foundation
  import CoreBluetooth
  import CoreLocation
  import UIKit

  class BeaconTransmitter: NSObject, CBPeripheralManagerDelegate {
    var region: CLBeaconRegion?
    var on = false
    var _peripheralManager: CBPeripheralManager?
    var peripheralManager: CBPeripheralManager {
      if _peripheralManager == nil {
        _peripheralManager = CBPeripheralManager(delegate: self, queue: nil)
      }
      return _peripheralManager!
    }
    override init() {
      super.init()
    }

    func stop() {
      on = false
      peripheralManager.stopAdvertising()
    }

    func start(region: CLBeaconRegion) {
      on = true
      self.region = region
      startTransmitting()
    }

    func startTransmitting() {
      if let region = region {
        let peripheralData = region.peripheralData(withMeasuredPower: -59) as Dictionary
        peripheralManager.stopAdvertising()
        peripheralManager.startAdvertising(peripheralData as? [String : AnyObject])
      }
    }

    func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
      if(peripheral.state == .poweredOn) {
        if on {
          startTransmitting()
        }
      }
      else if(peripheral.state == .poweredOff) {
        NSLog("Bluetooth is off")
      }
      else if(peripheral.state == .unsupported) {
        NSLog("Bluetooth not supported")
      }
    }
  }