Статьи

iOS 7 SDK: Core Bluetooth — практический урок

Инфраструктура Core Bluetooth (CB) предоставляет ресурсы, необходимые приложениям iOS для связи с устройствами, оснащенными технологией Bluetooth с низким энергопотреблением (BTLE). Из этого туториала Вы узнаете, как настроить CB от iOS 5 до iOS 7. Кроме того, вы узнаете, как настроить центральный и периферийный интерфейс Core Bluetooth, как общаться между ними, а также присущи лучшие методы программирования при работе с CB.


Основные уроки по Bluetooth разделены на две части. Первый из них охватывает теоретический аспект Core Bluetooth, в то время как этот урок является полным практическим уроком. Вы найдете полный исходный код, прикрепленный к этому сообщению.


Цель этого руководства — научить вас, как использовать базовую платформу Bluetooth. Мы подготовили пример исходного кода, который облегчит вашу жизнь, и обойдёт создание проекта и просмотр конфигурации. Вы должны загрузить образец кода в начале этой страницы.

Мы предполагаем, что вы знакомы с основами XCode и iOS, поскольку мы сосредоточимся только на основных данных Bluetooth. Пример кода содержит следующее:

  • Приложение, которое использует контроллер навигации, три представления и встроенные контроллеры.
  • Начальный вид контроллера ViewController с двумя кнопками
  • CBCentralManagerViewController который создает пользовательский iBeacon
  • CBPeripheralViewController который получает iBeacon и внутреннюю информацию
  • Заголовочный файл SERVICES с некоторыми переменными для использования в приложении.

Все представления уже на месте и правильно определены. Вам просто нужно добавить код для основного процесса Bluetooth. Откройте проект, запустите его и поиграйте с объектами, чтобы ознакомиться с кодом.

Файл SERVICES.h содержит два уникальных UUID. Они были созданы с помощью терминальной команды uuidgen . Вы должны сгенерировать их для своего приложения, или вы можете использовать их.

Обратите внимание, что этот урок нуждается в двух устройствах iOS для правильной работы. Run проект, и вы увидите интерфейс, похожий на этот:

iOS_CB_Image4

Иллюстрация интерфейса CB

В этом руководстве вы будете CBCentralManagerViewController класс CBCentralManagerViewController . Первым шагом является добавление двух протоколов, которые поддерживают CBCentralManager и CBPeripheral . Объявление этих протоколов определяет методы (подробнее об этом позже). Ваш interface должен быть таким:

1
@interface CBCentralManagerViewController : UIViewController < CBCentralManagerDelegate, CBPeripheralDelegate>

Теперь вы должны определить три свойства: CBCentralManager , CBPeripheral и NSMutableData . Первые два очевидны, а последний используется для хранения информации, которая распределяется между устройствами.

1
2
3
@property (strong, nonatomic) CBCentralManager *centralManager;
@property (strong, nonatomic) CBPeripheral *discoveredPeripheral;
@property (strong, nonatomic) NSMutableData *data;

На этом этапе вы можете перейти к файлу реализации. Вы увидите предупреждение, но перед тем как его решить, вы должны centralManger и объекты data . Вы должны запустить centralManager с собственным делегатом и без какой-либо очереди. Вы должны использовать метод viewDidLoad и результат должен быть похож на это:

1
2
_centralManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
   _data = [[NSMutableData alloc] init];

Чтобы устранить проблему с предупреждением, необходимо добавить - (void)centralManagerDidUpdateState:(CBCentralManager *)central метод - (void)centralManagerDidUpdateState:(CBCentralManager *)central .

Это обязательный метод протокола. Он проверяет состояние устройства и действует соответственно. Есть несколько возможных состояний, и в вашем приложении вы всегда должны проверять их. Состояния:

  • CBCentralManagerStateUnknown
  • CBCentralManagerStateResetting
  • CBCentralManagerStateUnsupported
  • CBCentralManagerStateUnauthorized
  • CBCentralManagerStatePoweredOff
  • CBCentralManagerStatePoweredOn

Например, если вы запустите это приложение на устройстве, CBCentralManagerStateUnsupported от Bluetooth 4.0, вы получите код CBCentralManagerStateUnsupported . Здесь вы перейдете к CBCentralManagerStatePoweredOn и когда это произойдет, вы начнете сканирование устройств. Для этого используйте метод scanForPeripheralsWithServices . Если вы передадите nil в качестве первого аргумента, CBCentralManager начнет искать любую службу. Здесь вы будете использовать UUID, хранящийся в SERVICES.h .

Полный метод:

01
02
03
04
05
06
07
08
09
10
11
12
— (void)centralManagerDidUpdateState:(CBCentralManager *)central {
    // You should test all scenarios
    if (central.state != CBCentralManagerStatePoweredOn) {
        return;
    }
     
    if (central.state == CBCentralManagerStatePoweredOn) {
        // Scan for devices
        [_centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]] options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @YES }];
        NSLog(@»Scanning started»);
    }
}

В этот момент ваше приложение будет искать другие устройства. Но, несмотря на то, что какие-либо или нет доступны, вы не получите никакой информации. Мы можем это исправить. Вы должны добавить - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI метод - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI . Он будет вызываться при обнаружении устройства. Однако вы запрограммируете его так, чтобы он реагировал только на периферийные устройства, которые рекламируют TRANSFER_SERVICE_UUID .

Кроме того, мы будем использовать новую систему кэширования и хранить устройство для дальнейшего использования и более быстрой связи. Полный исходный код выглядит следующим образом:

01
02
03
04
05
06
07
08
09
10
11
12
13
— (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI {
     
    NSLog(@»Discovered %@ at %@», peripheral.name, RSSI);
     
    if (_discoveredPeripheral != peripheral) {
        // Save a local copy of the peripheral, so CoreBluetooth doesn’t get rid of it
        _discoveredPeripheral = peripheral;
         
        // And connect
        NSLog(@»Connecting to peripheral %@», peripheral);
        [_centralManager connectPeripheral:peripheral options:nil];
    }
}

Соединение с этим устройством может прерваться. Нам нужно разобраться с этим сценарием, используя специальный метод, называемый: - (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error . Добавьте его и сообщите пользователю об этой ошибке.

1
2
3
4
— (void)centralManager:(CBCentralManager *)central didFailToConnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    NSLog(@»Failed to connect»);
    [self cleanup];
}

Вы заметите предупреждение, так как метод cleanup еще не объявлен. Давайте объявим это! На этом этапе вы можете найти исходный код метода сложным. Однако мы объясним это позже. Вы должны вернуться к нему в конце урока для полного понимания.

Этот метод отменяет любые подписки на удаленное устройство (если они есть) или прямое отключение, если нет. Он перебирает сервисы, затем характеристики и удаляет привязки к ним. Полный метод:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
— (void)cleanup {
     
    // See if we are subscribed to a characteristic on the peripheral
    if (_discoveredPeripheral.services != nil) {
        for (CBService *service in _discoveredPeripheral.services) {
            if (service.characteristics != nil) {
                for (CBCharacteristic *characteristic in service.characteristics) {
                    if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]]) {
                        if (characteristic.isNotifying) {
                            [_discoveredPeripheral setNotifyValue:NO forCharacteristic:characteristic];
                            return;
                        }
                    }
                }
            }
        }
    }
 
    [_centralManager cancelPeripheralConnection:_discoveredPeripheral];
}

Принимая во внимание, что мы успешно подключились к устройству, теперь нам нужно узнать его сервисы и характеристики. Вы должны объявить - (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral . После установления соединения остановите процесс сканирования. Затем очистите данные, которые мы могли получить. Затем убедитесь, что вы получили обратные вызовы для обнаружения, и, наконец, выполните поиск служб, соответствующих вашему UUID ( TRANSFER_SERVICE_UUID ). Вот код:

01
02
03
04
05
06
07
08
09
10
11
12
— (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
    NSLog(@»Connected»);
     
    [_centralManager stopScan];
    NSLog(@»Scanning stopped»);
     
    [_data setLength:0];
     
    peripheral.delegate = self;
 
    [peripheral discoverServices:@[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]]];
}

В этот момент периферийное устройство начинает уведомлять своего делегата несколькими обратными вызовами. Одним из таких обратных вызовов является - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error . Он используется для определения характеристик данной услуги. Не то чтобы вы всегда проверяли, возвращает ли этот метод ошибку. Если ошибки не обнаружены, вы должны найти нужные характеристики, в данном случае TRANSFER_CHARACTERISTIC_UUID . Вот полный метод:

01
02
03
04
05
06
07
08
09
10
11
— (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
    if (error) {
        [self cleanup];
        return;
    }
 
    for (CBService *service in peripheral.services) {
        [peripheral discoverCharacteristics:@[[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]] forService:service];
    }
    // Discover other characteristics
}

В этот момент, если все правильно, передаточная характеристика была обнаружена. Еще раз, метод делегата вызывается: - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error . Как только это будет найдено, вы хотите подписаться на него, что позволит вашему CBCentralManager получать данные этого периферийного устройства.

Еще раз, вы должны иметь дело с ошибками (если есть). Вы можете сделать прыжок веры и напрямую подписаться на характеристику. Тем не менее, вы должны перебрать массив характеристик и проверить, является ли характеристика правильной. Если это так, то подпишитесь на него. Как только это завершится, вам просто нужно дождаться поступления данных (другой метод). Полный метод ниже.

01
02
03
04
05
06
07
08
09
10
11
12
— (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:(CBService *)service error:(NSError *)error {
    if (error) {
        [self cleanup];
        return;
    }
     
    for (CBCharacteristic *characteristic in service.characteristics) {
        if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]]) {
            [peripheral setNotifyValue:YES forCharacteristic:characteristic];
        }
    }
}

Каждый раз, когда периферийное устройство отправляет новые данные, периферийный делегат использует - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error метод - (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error . Второй аргумент содержит характеристику, которую вы можете прочитать.

Сначала вы создадите NSString для хранения значения признака. Затем вы проверите, полны ли полученные данные или будут доставлены дополнительные данные. Одновременно вы обновите textview как только будут textview новые данные. После завершения всех данных вы можете отключиться от характеристики и отключиться от устройства (хотя вы можете оставаться на связи).

Обратите внимание, что после входящих данных вы можете либо отключиться, либо дождаться других данных. Этот обратный вызов сообщает нам, поступило ли больше данных, посредством уведомления о характеристике. Полный источник ниже:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
— (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
    if (error) {
        NSLog(@»Error»);
        return;
    }
     
    NSString *stringFromData = [[NSString alloc] initWithData:characteristic.value encoding:NSUTF8StringEncoding];
     
    // Have we got everything we need?
    if ([stringFromData isEqualToString:@»EOM»]) {
     
        [_textview setText:[[NSString alloc] initWithData:self.data encoding:NSUTF8StringEncoding]];
         
        [peripheral setNotifyValue:NO forCharacteristic:characteristic];
         
        [_centralManager cancelPeripheralConnection:peripheral];
    }
     
    [_data appendData:characteristic.value];
}

Кроме того, существует метод, который гарантирует, что CBCentral знает, когда изменяется состояние уведомления для данной характеристики. Очень важно отслеживать его, чтобы понять, когда изменяется характерное состояние (обновить значения приложения). Метод: - (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error . Вы должны проверить, остановилось ли характерное уведомление. Если это так, вы должны отключиться от него:

01
02
03
04
05
06
07
08
09
10
11
12
13
— (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:(CBCharacteristic *)characteristic error:(NSError *)error {
     
    if (![characteristic.UUID isEqual:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID]]) {
        return;
    }
     
    if (characteristic.isNotifying) {
        NSLog(@»Notification began on %@», characteristic);
    } else {
        // Notification has stopped
        [_centralManager cancelPeripheralConnection:peripheral];
    }
}

Если происходит отключение между устройствами, вам необходимо очистить локальную копию периферийного устройства. Для этого используйте - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error метод - (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error . Этот метод прост и устанавливает периферийное устройство на ноль. Кроме того, вы можете перезапустить сканирование устройства или выйти из приложения (или другого). В этом примере вы перезапустите процесс сканирования.

1
2
3
4
5
— (void)centralManager:(CBCentralManager *)central didDisconnectPeripheral:(CBPeripheral *)peripheral error:(NSError *)error {
    _discoveredPeripheral = nil;
 
    [_centralManager scanForPeripheralsWithServices:@[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]] options:@{ CBCentralManagerScanOptionAllowDuplicatesKey : @YES }];
}

Наконец, требуется еще один дополнительный шаг. Каждый раз, когда вид исчезает, вы должны остановить процесс сканирования. В viewWillDisappear:(BOOL)animated метод viewWillDisappear:(BOOL)animated вы должны добавить:

1
[_centralManager stopScan];

Вы можете Run приложение, однако вам необходимо периферийное приложение для получения некоторых данных. Следующее изображение представляет окончательный интерфейс CBCentralManager .

iOS_CB_Image5

Иллюстрация CBCentralManager.

В этом руководстве вы будете CBPeripheralViewController класс CBPeripheralViewController . Первым шагом является добавление двух протоколов: CBPeripheralManagerDelegate и UITextViewDelegate. Теперь ваш interface должен выглядеть так:

1
@interface CBPeripheralViewController : UIViewController < CBPeripheralManagerDelegate, UITextViewDelegate>

Теперь вы должны определить четыре свойства: CBPeripheralManager , CBMutableCharacteristic , NSData и NSInterger . Первые два представляют диспетчер периферийных устройств и его характеристики, а третий — данные, которые будут отправлены. Последний представляет индекс данных.

1
2
3
4
@property (strong, nonatomic) CBPeripheralManager *peripheralManager;
@property (strong, nonatomic) CBMutableCharacteristic *transferCharacteristic;
@property (strong, nonatomic) NSData *dataToSend;
@property (nonatomic, readwrite) NSInteger sendDataIndex;

Теперь перейдите к файлу реализации. Наш первый шаг — _peripheralManager и настроить его для запуска рекламы. Реклама услуги должна начинаться с UUID вышеупомянутой услуги. Ваш viewDidLoad должен выглядеть так:

1
2
3
4
5
6
7
— (void)viewDidLoad {
    [super viewDidLoad];
 
    _peripheralManager = [[CBPeripheralManager alloc] initWithDelegate:self queue:nil];
     
    [_peripheralManager startAdvertising:@{ CBAdvertisementDataServiceUUIDsKey : @[[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID]] }];
}

Вы должны увидеть предупреждение. Чтобы исправить это, объявите метод - (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral протокола - (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral . Подобно CBCentralManager вы должны контролировать и тестировать все состояния приложения. Если состояние CBPeripheralManagerStatePoweredOn вы должны создать и определить свой сервис и характеристики (одна из истинных функций iOS 7).

Каждая услуга и характеристика должны идентифицироваться уникальным UUID. Обратите внимание, что третий аргумент метода init не имеет значения. При этом объявляется, что данные для обмена будут определены позже. Обычно это делается, когда вы хотите создать данные динамически. Если вы хотите иметь статическое значение для передачи, вы можете объявить его здесь.

Свойства определяют, как можно использовать значение признака, и существует несколько возможных значений:

  • CBCharacteristicPropertyBroadcast
  • CBCharacteristicPropertyRead
  • CBCharacteristicPropertyWriteWithoutResponse
  • CBCharacteristicPropertyWrite
  • CBCharacteristicPropertyWrite
  • CBCharacteristicPropertyNotify
  • CBCharacteristicPropertyIndicate
  • CBCharacteristicPropertyAuthenticatedSignedWrites
  • CBCharacteristicPropertyExtendedProperties
  • CBCharacteristicPropertyNotifyEncryptionRequired
  • CBCharacteristicPropertyIndicateEncryptionRequired

Для полного понимания этих свойств, вы должны проверить CBCharacteristic Class Reference .

Последний аргумент init — это разрешения на чтение, запись и шифрование для атрибута. Опять же, есть несколько возможных значений:

  • CBAttributePermissionsReadable
  • CBAttributePermissionsWriteable
  • CBAttributePermissionsReadEncryptionRequired
  • CBAttributePermissionsWriteEncryptionRequired

После того, как признак определил это, пришло время определить службу, используя CBMutableService . Обратите внимание, что служба должна быть определена с TRANSFER_CHARACTERISTIC_UUID . Добавьте характеристику в службу, а затем добавьте ее в диспетчер периферийных устройств. Полный метод ниже:

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
— (void)peripheralManagerDidUpdateState:(CBPeripheralManager *)peripheral {
    if (peripheral.state != CBPeripheralManagerStatePoweredOn) {
        return;
    }
     
    if (peripheral.state == CBPeripheralManagerStatePoweredOn) {
        self.transferCharacteristic = [[CBMutableCharacteristic alloc] initWithType:[CBUUID UUIDWithString:TRANSFER_CHARACTERISTIC_UUID] properties:CBCharacteristicPropertyNotify value:nil permissions:CBAttributePermissionsReadable];
         
        CBMutableService *transferService = [[CBMutableService alloc] initWithType:[CBUUID UUIDWithString:TRANSFER_SERVICE_UUID] primary:YES];
         
        transferService.characteristics = @[_transferCharacteristic];
         
        [_peripheralManager addService:transferService];
    }
}

Теперь, когда у нас есть сервис и его характеристики (в данном случае один), пришло время определить, когда устройство подключается к нему и реагирует соответствующим образом. Метод - (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic метод - (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic перехватывает, когда кто-то подписывается на наш признак, а затем начинает отправлять ему данные.

Приложение отправляет данные, доступные при просмотре textview . Если пользователь изменяет его, приложение отправляет его им в режиме реального времени в центральную подписку. Метод вызывает пользовательский метод с именем sendData .

1
2
3
4
5
6
7
8
— (void)peripheralManager:(CBPeripheralManager *)peripheral central:(CBCentral *)central didSubscribeToCharacteristic:(CBCharacteristic *)characteristic {
     
    _dataToSend = [_textView.text dataUsingEncoding:NSUTF8StringEncoding];
 
    _sendDataIndex = 0;
 
    [self sendData];
}

sendData — метод, который имеет дело со всей логикой относительно передачи данных. Он может выполнять несколько действий, таких как:

  • Отправить данные
  • Отправить флаг окончания связи
  • Проверьте, отправило ли приложение данные
  • Проверьте, все ли данные были отправлены
  • Реагировать на все предыдущие темы

Полный исходный код представлен ниже. Несколько комментариев были оставлены намеренно, чтобы облегчить его понимание.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
— (void)sendData {
 
    static BOOL sendingEOM = NO;
     
    // end of message?
    if (sendingEOM) {
        BOOL didSend = [self.peripheralManager updateValue:[@»EOM» dataUsingEncoding:NSUTF8StringEncoding] forCharacteristic:self.transferCharacteristic onSubscribedCentrals:nil];
         
        if (didSend) {
            // It did, so mark it as sent
            sendingEOM = NO;
        }
        // didn’t send, so we’ll exit and wait for peripheralManagerIsReadyToUpdateSubscribers to call sendData again
        return;
    }
     
    // We’re sending data
    // Is there any left to send?
    if (self.sendDataIndex >= self.dataToSend.length) {
        // No data left.
        return;
    }
     
    // There’s data left, so send until the callback fails, or we’re done.
    BOOL didSend = YES;
     
    while (didSend) {
        // Work out how big it should be
        NSInteger amountToSend = self.dataToSend.length — self.sendDataIndex;
         
        // Can’t be longer than 20 bytes
        if (amountToSend > NOTIFY_MTU) amountToSend = NOTIFY_MTU;
         
        // Copy out the data we want
        NSData *chunk = [NSData dataWithBytes:self.dataToSend.bytes+self.sendDataIndex length:amountToSend];
         
        didSend = [self.peripheralManager updateValue:chunk forCharacteristic:self.transferCharacteristic onSubscribedCentrals:nil];
         
        // If it didn’t work, drop out and wait for the callback
        if (!didSend) {
            return;
        }
         
        NSString *stringFromData = [[NSString alloc] initWithData:chunk encoding:NSUTF8StringEncoding];
        NSLog(@»Sent: %@», stringFromData);
         
        // It did send, so update our index
        self.sendDataIndex += amountToSend;
         
        // Was it the last one?
        if (self.sendDataIndex >= self.dataToSend.length) {
             
            // Set this so if the send fails, we’ll send it next time
            sendingEOM = YES;
 
            BOOL eomSent = [self.peripheralManager updateValue:[@»EOM» dataUsingEncoding:NSUTF8StringEncoding] forCharacteristic:self.transferCharacteristic onSubscribedCentrals:nil];
             
            if (eomSent) {
                // It sent, we’re all done
                sendingEOM = NO;
                NSLog(@»Sent: EOM»);
            }
             
            return;
        }
    }
}

Наконец, вы должны определить обратный вызов, который вызывается, когда PeripheralManager готов отправить следующую порцию данных. Это гарантирует, что пакеты поступают в порядке их отправки. Этот метод является - (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral и вызывает sendData метод sendData . Полная версия ниже:

1
2
3
— (void)peripheralManagerIsReadyToUpdateSubscribers:(CBPeripheralManager *)peripheral {
    [self sendData];
}

Теперь вы можете, наконец, Run приложение и проверить связь Bluetooth. Следующее изображение показывает интерфейс CBCentralManager .

iOS_CB_Image6

Иллюстрация периферийного интерфейса.

В конце этого урока вы должны понять основные характеристики ядра Bluetooth. Вы также должны иметь возможность определять и настраивать CBCentralManager и роль CBPeripheral, а также понимать и применять некоторые рекомендации при разработке с Core Bluetooth.

Если у вас есть какие-либо вопросы или комментарии, пожалуйста, оставьте их ниже!

Если вы часто работаете с iOS SDK, загляните на Envato Market, чтобы найти сотни полезных и экономящих время шаблонов приложений для iOS .