Hello everyone , In my last blog Create BLE Peripheral - iOS We saw how to create BLE Peripheral to advertise data. Today we will see how to create a BLE Central to consume that advertisement data. Create a new Xcode project using the Single-View Application template. Name it BleCentral . Once the project is created, add the CoreBluetooth.framework to it. Then, open the ViewController.h file and add the following line:

#import <CoreBluetooth/CoreBluetooth.h>
As we are creating a BLE Central, you must implement protocols namely CBCentralManagerDelegate and CBPeripheralDelegate in your class.
@interface ViewController : UIViewController <CBCentralManagerDelegate, CBPeripheralDelegate>
Now add below properties
@property (strong, nonatomic) CBCentralManager *bleManager;
@property (strong, nonatomic) NSMutableData *data;
@property(nonatomic, strong) CBPeripheral *connectedPeripheral;
Initialize bleManager object in your ViewDidLoad
self.bleManager = [[CBCentralManager alloc] initWithDelegate:self queue:nil];
Passing 'nil' to parameter queue specifies CBPeripheralManager will run on main thread. If you want it to run on other thread , you can create and pass it to the parameter. Once we initialize central manager , we need to check its state. This will allow to verify that the device your application is running on is Bluetooth LE compliant. You do this implementing the following delegate method:
 - (void)centralManagerDidUpdateState:(CBCentralManager *)central {
    switch (central.state) {
        case CBCentralManagerStatePoweredOn:
            // Scans for any peripheral
            [self.bleManager scanForPeripheralsWithServices:
@[[CBUUID UUIDWithString:ADVERTISING_SERVICE_UUID_16]] 
options:@{CBCentralManagerScanOptionAllowDuplicatesKey : @YES }];
            break;
        default:
            NSLog(@"Central Manager did change state");
            break;
    }
}
The -scanForPeripheralsWithServices:options: method scans for peripherals that are advertising services. If you pass nil as first argument, the central manager starts to look for any service. The ADVERTISING_SERVICE_UUID_16 is the same UUID string I used for the Peripheral . Add below lines to your code before implementation
#define ADVERTISING_SERVICE_UUID_16 @"FFC0"
#define ADVERTISING_CHAR_UUID_16 @"b71e"
Here, ADVERTISING_SERVICE_UUID_16 is service UUID and ADVERTISING_CHAR_UUID_16 is a chracteristics UUID. Same like we defined in peripheral As soon as a Peripheral is discovered during the scanning, below method of the BLE Central delegate receives callback
 - (void)centralManager:(CBCentralManager *)central didDiscoverPeripheral:(CBPeripheral *)peripheral
 advertisementData:(NSDictionary *)advertisementData RSSI:(NSNumber *)RSSI
This call notifies the BLE Central Manager delegate (the view controller) that a peripheral with advertisement data and RSSI was discovered. RSSI stands for Received Signal Strength Indicator. It is used for finding proximity of the peripheral. One can use this for adding filter for any peripheral and service. Advertisement Data is received in the form of NSDictionary. Write below code for this method
- (void)centralManager:(CBCentralManager *)central
 didDiscoverPeripheral:(CBPeripheral *)peripheral
     advertisementData:(NSDictionary *)advertisementData
                  RSSI:(NSNumber *)RSSI {
    
  NSLog(@"peripheralUUID : %@",[advertisementData objectForKey:CBAdvertisementDataServiceUUIDsKey]);
  NSLog(@"local name : %@",[advertisementData objectForKey:CBAdvertisementDataLocalNameKey]);
  NSLog(@"Manufacturer : %@",[advertisementData objectForKey:CBAdvertisementDataManufacturerDataKey]);
  NSLog(@"RSSI: %@", RSSI);
  [self.bleManager stopScan];
  [self.bleManager connectPeripheral:peripheral options:nil];

}
The options parameter is an optional NSDictionary and can use the following keys if needed For more information you can refer this link. Depending on the result of the connection, the delegate can receive either centralManager:didFailToConnectPeripheral:error: or centralManager:didConnectPeripheral:. In case of success, you can ask the Peripheral which services is advertising. So, in the didConnectPeripheral callback like following:
- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
    // Clears the data that we may already have
    [self.data setLength:0];
    // Sets the peripheral delegate
    [self.connectedPeripheral setDelegate:self];
    // Asks the peripheral to discover the service
    [self.connectedPeripheral discoverServices:
@[[CBUUID UUIDWithString:ADVERTISING_SERVICE_UUID_16]]];
}

At this point, the Peripheral starts notifying its delegate.The Peripheral delegate receives -peripheral:didDiscoverServices:. If there is no error, the Peripheral can be asked to discover the characteristics for a given service. You can do it in this way:

 - (void)peripheral:(CBPeripheral *)peripheral didDiscoverServices:(NSError *)error {
    if (error) {
        NSLog(@"Error while discovering services: %@", error);
        return;
    }
 
    for (CBService *service in peripheral.services) {
        // Discovers the characteristics for a given service
        if ([service.UUID isEqual:[CBUUID UUIDWithString:ADVERTISING_SERVICE_UUID_16]]) {
            [self.peripheral discoverCharacteristics:
@[[CBUUID UUIDWithString:ADVERTISING_CHAR_UUID_16]] forService:service];
        }
    }
}
Now, if a characteristic is discovered, the Peripheral delegate receives -peripheral:didDiscoverCharacteristicsForService:error:. At this point, the Peripheral can be asked to notify its delegate as soon as the characteristic value is updated using -setNotifyValue:forCharacteristic: Below is the code for same
 - (void)peripheral:(CBPeripheral *)peripheral didDiscoverCharacteristicsForService:
(CBService *)service error:(NSError *)error {
    if (error) {
        NSLog(@"Error while discovering characteristic: %@", error);
        return;
    }
    if ([service.UUID isEqual:[CBUUID UUIDWithString:ADVERTISING_SERVICE_UUID_16]]) {
        for (CBCharacteristic *characteristic in service.characteristics) {
            if ([characteristic.UUID isEqual:[CBUUID UUIDWithString:ADVERTISING_CHAR_UUID_16]]) {
                [peripheral setNotifyValue:YES forCharacteristic:characteristic];
            }
        }
    }
}
Here, if the value of a characteristic is updated, then the Peripheral delegate receives -peripheral:didUpdateNotificationStateForCharacteristic: error:. Here, you can read the new value using -readValueForCharacteristic:
 - (void)peripheral:(CBPeripheral *)peripheral didUpdateNotificationStateForCharacteristic:
(CBCharacteristic *)characteristic error:(NSError *)error {
    if (error) {
        NSLog(@"Error while updating notification state: %@", error);
    }
 
    // Exits if it\'s not the transfer characteristic
    if (![characteristic.UUID isEqual:[CBUUID UUIDWithString:ADVERTISING_CHAR_UUID_16]]) {
        return;
    }
 
    // Notification has started
    if (characteristic.isNotifying) {
        NSLog(@"Notification began on %@", characteristic);
        [peripheral readValueForCharacteristic:characteristic];
    } else { // Notification has stopped
        // so disconnect from the peripheral
        NSLog(@"Notification stopped on %@.  Disconnecting", characteristic);
        [self.bleManager cancelPeripheralConnection:self.connectedPeripheral];
    }
}
When the BLE Peripheral sends the new value, the Peripheral delegate receives -peripheral:didUpdateValueForCharacteristic:error:. The second argument of this method contains the characteristic. You can then read its value using the -value property. This is a NSData containing the value of the characteristic. At this point, you can either disconnect or wait for other data.

Conclusion : In this blog I have described how to create a basic BLE Central Application consuming advertise using Core Bluetooth Framework. I hope this tutorial will help you for creating simple BLE Central and Peripheral. Happy Coding....