Adam Tucholski
Adam Tucholski

Reputation: 1077

Simulate beacon with iPhone using dedicated class

I want to transmit beacon signal using iPhone. For now it will be implemented in Objective C, but there is a plan to convert it to Swift later, so I'm also interested in finding any important differences I can encounter at this phase.

In some research I was able to find some limitations in simulating beacon

Can I make iPhone/iPad broadcast as Eddystone Beacon?

and also informations of some problems when using class other than view controller, at least in swift

Using iPhone as iBeacon Transmitter

In this last link I found link to Swift tutorial for simulating iBeacon with iPhone - code is placed in View Controller and it works in this place.

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

But using Core Bluetooth from View Controller is serious limitation if I want app to do some other stuff than just transmitting BLE signal. And this other stuff needs dismissing my controller.

Soon I will try to create some working code for Objective C and later for Swift for emitting BLE signal and still changing visible View Controllers. But maybe someone had done something like that and will be able to say if there was any problems, like mentioned before

Upvotes: 2

Views: 984

Answers (1)

davidgyoung
davidgyoung

Reputation: 64916

Yes, you can absolutely set up beacon transmitting on iOS outside a ViewController. Below is a simple Swift class that I have used to do so on a number of projects.

Note, however, that while you can use a class like this to advertise regardless of which ViewController is in the foreground, advertising will stop if your entire app is in the background. This is an Apple iOS limitation. See here for more info.

  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")
      }
    }
  }

Upvotes: 2

Related Questions