如何使用Swift 4中的iPad 5来宣传iBeacon

时间:2018-03-15 15:46:43

标签: ios swift4 ibeacon

所以我找到了一个关于使用iBeacons的好教程,我创建了一个接收器和一个广播器,但是当我运行代码时,我看不到有任何信标被广播。有没有人有一个很好的解决方案可以解决我的问题?

import UIKit
import CoreLocation
import CoreBluetooth
import Foundation

/// ibeacon class
class iBeaconConfiguration
{
    // You can use uuidgen in terminal to generate new one.
    static let uuid = UUID(uuidString: "7FA08BC7-A55F-45FC-85C0-0BF26F899530")!

    private init() {}
}

如果您想知道,上面的课程仅适用于UUID

class BroadcastViewController: UIViewController {
    fileprivate var broadcasting: Bool = false
    fileprivate var beacon: CLBeaconRegion?
    fileprivate var peripheralManager: CBPeripheralManager?
    @IBOutlet var statusLabel: UILabel!
    @IBOutlet var triggerButton: UIButton!

    override func viewDidAppear(_ animated: Bool) {
      super.viewDidAppear(animated)
      self.setNeedsStatusBarAppearanceUpdate()
    }

override func viewDidLoad() {
    super.viewDidLoad()

    statusLabel = UILabel()
    triggerButton = UIButton(frame: CGRect(x: 130, y: 10, width: 100, height: 50))
    triggerButton.backgroundColor = UIColor.blue
    triggerButton.addTarget(self, action: #selector(broadcastBeacon(sender:)), for: .touchUpInside)
    self.view.addSubview(triggerButton)

    let button = UIButton(frame: CGRect(x: 10, y: 10, width: 50, height: 50))
    button.backgroundColor = UIColor.red
    button.addTarget(self, action: #selector(dismiss1), for: .touchUpInside)
    self.view.addSubview(button)

    self.view.backgroundColor = UIColor.white
    let UUID: UUID = iBeaconConfiguration.uuid

    let major: CLBeaconMajorValue = CLBeaconMajorValue(arc4random() % 100 + 1)
    let minor: CLBeaconMinorValue = CLBeaconMinorValue(arc4random() % 2 + 1)

    self.beacon = CLBeaconRegion(proximityUUID: UUID, major: major, minor: minor, identifier: "tw.darktt.beaconDemo")

    self.peripheralManager = CBPeripheralManager(delegate: self, queue: nil)
}

deinit
{
    self.beacon = nil
    self.peripheralManager = nil
}

override func didReceiveMemoryWarning()
{
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}

    @IBAction func dismiss1() {
    //self.dismiss(animated: true, completion: nil)
    present(ReceiverViewController(), animated: true, completion: nil)
    }
}

// MARK: - Status Bar -
extension BroadcastViewController {
override var preferredStatusBarStyle: UIStatusBarStyle
{
    if self.broadcasting {
        return .lightContent
    }

    return .default
}

override var preferredStatusBarUpdateAnimation: UIStatusBarAnimation
{
    return .fade
}

override var prefersStatusBarHidden: Bool
{
    return false
}
}

//MARK: - Actions -
extension BroadcastViewController {
@IBAction fileprivate func broadcastBeacon(sender: UIButton) -> Void
{
    let state: CBManagerState = self.peripheralManager!.state

    if (state == .poweredOff && !self.broadcasting) {
        let OKAction: UIAlertAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)

        let alert: UIAlertController = UIAlertController(title: "Bluetooth OFF", message: "Please power on your Bluetooth!", preferredStyle: .alert)
        alert.addAction(OKAction)

        self.present(alert, animated: true, completion: nil)

        return
    }

    let titleFromStatus: (Void) -> String = {
        let title: String = (self.broadcasting) ? "Start" : "Stop"

        return title + " Broadcast"
    }

    let buttonTitleColor: UIColor = (self.broadcasting) ? UIColor.blue : UIColor.white

    sender.setTitle("nil", for: .normal)
    sender.setTitleColor(buttonTitleColor, for: .normal)

    let labelTextFromStatus: (Void) -> String = {
        let text: String = (self.broadcasting) ? "Not Broadcast" : "Broadcasting..."

        return text
    }

    self.statusLabel.text = "broadcast started"

    let animations: () -> Void = {
        let backgroundColor: UIColor = (self.broadcasting) ? UIColor.white : UIColor.blue

        self.view.backgroundColor = backgroundColor

        self.broadcasting = !self.broadcasting
        self.setNeedsStatusBarAppearanceUpdate()
    }

    let completion: (Bool) -> Void = {
        finish in
        self.advertising(start: self.broadcasting)
    }

    UIView.animate(withDuration: 0.25, animations: animations, completion: completion)
}

// MARK: - Broadcast Beacon

func advertising(start: Bool) -> Void
{
    if self.peripheralManager == nil {
        return
    }

    if (!start) {
        self.peripheralManager!.stopAdvertising()

        return
    }

    let state: CBManagerState = self.peripheralManager!.state

    if (state == .poweredOn) {
        let UUID:UUID = (self.beacon?.proximityUUID)!
        let serviceUUIDs: Array<CBUUID> = [CBUUID(nsuuid: UUID)]

        // Why NSMutableDictionary can not convert to Dictionary<String, Any> 
        var peripheralData: Dictionary<String, Any> = self.beacon!.peripheralData(withMeasuredPower: 1)  as NSDictionary as! Dictionary<String, Any>
        peripheralData[CBAdvertisementDataLocalNameKey] = "iBeacon Demo" 
        peripheralData[CBAdvertisementDataServiceUUIDsKey] = serviceUUIDs

        self.peripheralManager!.startAdvertising(peripheralData)
    }
}
}

// MARK: - CBPeripheralManager Delegate -
extension BroadcastViewController: CBPeripheralManagerDelegate {
func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager)
{
    let state: CBManagerState = peripheralManager!.state

    if state == .poweredOff {
        self.statusLabel.text = "Bluetooth Off"

        if self.broadcasting {
            self.broadcastBeacon(sender: self.triggerButton)
        }
    }

    if state == .unsupported {
        self.statusLabel.text = "Unsupported Beacon"
    }

    if state == .poweredOn {
        self.statusLabel.text = "Not Broadcast"
    }
}
}

除此之外,我还阅读了苹果在其网站上提供的文档,但我对此并不是很了解。我也可能喜欢10个不同的Github项目并尝试过它们,但它们都是用早期版本的swift编写的。

2 个答案:

答案 0 :(得分:0)

假设你有一个iBeacon扫描应用程序正在运行(否则,如果你的设备正确播放,那将很难知道)......

我建议开始简单...得到&#34;开始播放&#34;部分工作,然后添加额外的东西。

创建一个新项目(或将新VC添加到当前项目中)。添加&#34;开始&#34;和&#34;停止&#34;按钮,您将连接到下面的@IBAction个功能。

将此作为新VC的课程:

//
//  BroadcasterViewController.swift
//
//  Created by Don Mag on 3/16/18.
//

import UIKit
import CoreLocation
import CoreBluetooth

class BroadcasterViewController: UIViewController, CBPeripheralManagerDelegate {

    var myBeacon: CLBeaconRegion!
    var beaconData: NSDictionary!
    var peripheralMgr: CBPeripheralManager!

    let myRegionID = "myRegionID"

    @IBAction func startBeacon(_ sender: Any) {

        // don't do anything if myBeacon already exists
        guard myBeacon == nil else { return }

        let beaconUUID = "7FA08BC7-A55F-45FC-85C0-0BF26F899530"
        let beaconMajor: CLBeaconMajorValue = 123
        let beaconMinor: CLBeaconMinorValue = 456

        let uuid = UUID(uuidString: beaconUUID)!
        myBeacon = CLBeaconRegion(proximityUUID: uuid, major: beaconMajor, minor: beaconMinor, identifier: "MyIdentifier")

        beaconData = myBeacon.peripheralData(withMeasuredPower: nil)
        peripheralMgr = CBPeripheralManager(delegate: self, queue: nil, options: nil)

    }

    @IBAction func stopBeacon(_ sender: Any) {

        // don't do anything if there's no peripheral manager
        guard peripheralMgr != nil else { return }

        peripheralMgr.stopAdvertising()
        peripheralMgr = nil
        beaconData = nil
        myBeacon = nil

    }

    func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {
        if peripheral.state == .poweredOn {
            peripheralMgr.startAdvertising(beaconData as! [String: AnyObject]!)
        } else if peripheral.state == .poweredOff {
            peripheralMgr.stopAdvertising()
        }
    }

}

在&#34;广播公司&#34;上运行该应用设备,然后点击开始按钮。然后运行你的&#34;扫描仪&#34;应用程序在另一台设备上,看看你是否找到了新的&#34;设备作为iBeacon&#34;

注意:我确定您知道,您的扫描仪必须正在扫描您在广播公司上使用的beaconUUID。在此示例代码中,我使用了您在问题中发布的相同UUID字符串。

这对我来说很好 - 所以希望它会为你做同样的事情。如果此部分正常工作,那么您可以实现应用程序的其余部分 - UI,状态标签,任何其他选项 - 并添加一些错误处理(蓝牙未启用或未授予权限,等)。

答案 1 :(得分:0)

您无法在iBeacon广告中添加任何额外内容,并将其识别为此类内容。这两行是一个问题,必须删除:

#!/usr/bin/perl
use warnings;
use strict;

my $input = '...';
my $expected = '...';

$input =~ s/ =/:/g;
$input =~ s/\[(.*)\]/}\n$1: {/g;
$input =~ s/^/config.n8_v2_BB_RSI_SL = {\n/;
$input =~ s/(?<!\{)$/,/mg;
$input =~ s/,\n}//;
$input =~ s/,\n}/ }/g;
$input =~ s/,$/ }\n};/;

$input eq $expected or die 'Different';

第一行尝试将广播名称添加到广告中。你不能这样做,因为这种信息包里没有额外的空间。

第二行尝试将GATT服务UUID添加到广告中。这根本不符合逻辑。 iBeacon广告是蓝牙LE制造商广告,其不广告GATT服务。添加此选项会导致广告无效或导致广告API失败。

显示的代码可能存在其他问题。我建议在应用程序开始时简化代码以开始转换,这样您就可以消除任何可能的UI错误。我会使用像Locate这样的Android检测器,这样即使您的ProximityUIID错误也可以看到广告。与iOS不同,Android可以看到任何信标广告。