iOS Bluetooth периферийное устройство ManagerDidUpdateState никогда не вызывается

Я пытаюсь настроить свой iPhone в качестве монитора сердечного ритма и отправлять информацию, используя стандартную службу сердечного ритма, чтобы приложение, запущенное на моем ПК, могло получать данные. Я новичок в iOS, но у меня уже есть Bluetooth, работающий на Android и Windows. Я следую за информацией здесь, и я падаю на первое препятствие...

Как указано в документе, я сначала позвоню

CBPeripheralManager *myPeripheralManager = [[CBPeripheralManager alloc] initWithDelegate:(id<CBPeripheralManagerDelegate>)self queue:nil options:nil];

Я также реализую функцию обратного вызова ПериферическийМанигер DidUpdateState, но здесь кроется проблема. Этот обратный вызов никогда не запускается! Я ждал несколько минут, и ничего не произошло. Я подозреваю, что пропустил очень простой шаг, потому что я искал весь день и ничего не нашел в Интернете! Кто-нибудь может объяснить явные шаги, которые нужно предпринять как в коде, так и в физическом выполнении вещей с моим iPhone? Должен ли он иметь соединение до запуска этого обратного вызова? Это должно быть в паре с чем-либо?

Вот полный код. Все работает нормально, я не получаю никаких ошибок.

#import "ViewController.h"
@import CoreBluetooth;

@interface ViewController()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    NSLog(@"App running...");

    //Create the peripheral manager
    CBPeripheralManager *myPeripheralManager = [[CBPeripheralManager alloc] initWithDelegate:(id<CBPeripheralManagerDelegate>)self queue:nil options:nil];
}

- (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral{
    int state = peripheral.state;
    NSLog(@"Peripheral manager state =  %d", state);

    //Set the UUIDs for service and characteristic
    CBUUID *heartRateServiceUUID = [CBUUID UUIDWithString: @"180D"];
    CBUUID *heartRateCharacteristicUUID = [CBUUID UUIDWithString:@"2A37"];
    CBUUID *heartRateSensorLocationCharacteristicUUID = [CBUUID UUIDWithString:@"0x2A38"];


    //char heartRateData[2]; heartRateData[0] = 0; heartRateData[1] = 60;

    //Create the characteristics
    CBMutableCharacteristic *heartRateCharacteristic =
    [[CBMutableCharacteristic alloc] initWithType:heartRateCharacteristicUUID
                                       properties: CBCharacteristicPropertyNotify
                                            value:nil
                                      permissions:CBAttributePermissionsReadable];

    CBMutableCharacteristic *heartRateSensorLocationCharacteristic =
    [[CBMutableCharacteristic alloc] initWithType:heartRateSensorLocationCharacteristicUUID
                                       properties:CBCharacteristicPropertyRead
                                            value:nil
                                      permissions:CBAttributePermissionsReadable];
    //Create the service
    CBMutableService *myService = [[CBMutableService alloc] initWithType:heartRateServiceUUID primary:YES];
    myService.characteristics = @[heartRateCharacteristic, heartRateSensorLocationCharacteristic];

    //Publish the service
    NSLog(@"Attempting to publish service...");
    [peripheral addService:myService];

    //Set the data
    NSDictionary *data = @{CBAdvertisementDataLocalNameKey:@"iDeviceName",
                           CBAdvertisementDataServiceUUIDsKey:@[[CBUUID UUIDWithString:@"180D"]]};

    //Advertise the service
    NSLog(@"Attempting to advertise service...");
    [peripheral startAdvertising:data];

}

- (void)peripheralManager:(CBPeripheralManager *)peripheral
            didAddService:(CBService *)service
                    error:(NSError *)error {

    if (error) {
        NSLog(@"Error publishing service: %@", [error localizedDescription]);
    }
    else NSLog(@"Service successfully published");
}

- (void)peripheralManagerDidStartAdvertising:(CBPeripheralManager *)peripheral
                                       error:(NSError *)error {

    if (error) {
        NSLog(@"Error advertising: %@", [error localizedDescription]);
    }
    else NSLog(@"Service successfully advertising");
}

@end

2 ответа

Решение

Предмет myPeripheralManager освобождается, как только viewDidLoad Метод возвращает, так как у вас есть только одна ссылка, указывающая на этот объект, и он выходит из области видимости.

Решение состоит в том, чтобы создать свойство в ViewController который ссылается на случай CBPeripheralManager:

@interface ViewController()
@property (nonatomic, strong) CBPeripheralManager *myPeripheralManager;
@end

а затем инициализировать свойство в viewDidLoad:

self.myPeripheralManager = myPeripheralManager = [[CBPeripheralManager alloc] initWithDelegate:(id<CBPeripheralManagerDelegate>)self queue:nil options:nil];

Вы можете прочитать больше об управлении памятью (в частности, об автоматическом подсчете ссылок) в Objective-C.

Мое решение по этому вопросу:

import UIKit
import CoreBluetooth

class BluetoothManager: NSObject, CBPeripheralManagerDelegate {

    static let sharedInstance = BluetoothManager()

    var bluetoothPeripheralManager: CBPeripheralManager?


    override fileprivate init() {
    }

    func start() {
        bluetoothPeripheralManager = CBPeripheralManager(delegate: self, queue: nil, options: nil)

    }

    // MARK - CBCentralManagerDelegate
    func peripheralManagerDidUpdateState(_ peripheral: CBPeripheralManager) {

        var statusMessage = ""

        switch peripheral.state {
        case .poweredOn:
            statusMessage = "Bluetooth Status: Turned On"

        case .poweredOff:
            statusMessage = "Bluetooth Status: Turned Off"

        case .resetting:
            statusMessage = "Bluetooth Status: Resetting"

        case .unauthorized:
            statusMessage = "Bluetooth Status: Not Authorized"

        case .unsupported:
            statusMessage = "Bluetooth Status: Not Supported"

        default:
            statusMessage = "Bluetooth Status: Unknown"
        }

        print(statusMessage)

        if peripheral.state == .poweredOff {
            //TODO: Update this property in an App Manager class
        }
    }}

Использование:

BluetoothManager.sharedInstance.start()

Запустите и включите / выключите и Bluetooth, должно появиться сообщение журнала, указывающее состояние Bluetooth.

Другие вопросы по тегам