Search code examples
objective-cobjective-c-blocksdo-whilelivelock

Blocks and do-while loop in objective-c


I have a Problem working with Blocks in Objective-C. My Problem is, that the completion block from the function readDataFromCharactUUID is never called using the do-while-loop. Without using the do-while-loop it is called once.

What i want to do with my code is to read a value from a BLE characteristic so often as the value is 0x01.

My Question: Why is the completion block never executed? What can I do, that the completion block is getting executed in my case?

Used Code:

static bool dataReady = false;

-(IBAction)Buttonstartpressed:(UIButton *)sender{

LGLog(@"start pressed");

NSData *data = [NSData dataWithBytes:(unsigned char[]){CMD_Control_Learn} length:1];
[LGUtils writeData   :data
         charactUUID :CHARACTERISTIC_UUID_REMOTEBUDDYControl
         serviceUUID :SERVICE_UUID_REMOTEBUDDY
        peripheral   :_mBuddy completion:^(NSError *error)
        {
            // Befehl wurde übermittelt
            NSLog(@"Einlernen gesendet => Error : %@", error);

            do
            {
                // RB_Notification Data Ready auslesen
                [LGUtils readDataFromCharactUUID:CHARACTERISTIC_UUID_REMOTEBUDDYNotification
                                     serviceUUID:SERVICE_UUID_REMOTEBUDDY
                                      peripheral:_mBuddy
                                      completion:^(NSData *data, NSError *error)
                 {

                     NSLog(@"Data : %@ Error : %@", data, error);


                     const uint8_t *bytes = [data bytes]; // pointer to the bytes in data
                     int data_int = bytes[0]; // first byte

                     switch(data_int)
                     {
                         case 0x01:
                             NSLog(@"Data ready!");
                             dataReady = true;
                             break;
                         case 0x02:
                             NSLog(@"Data Transimission Error!");
                             break;
                         case 0x00:
                             NSLog(@"No Notification! => check again");
                             break;
                         default:
                             break;
                     }
                 }
                 ];
            }
            while(!dataReady);

        }];}

Thank you in advance!


Solution

  • That execution block is async - meaning it will execute on different thread. I would create function for reading from peripheral and after you read and results are 0x01 then call another function, else call that function with recursion.

    Something like this (not 100% sure about compiling - not at the mac right now) :

    NSData *data = [NSData dataWithBytes:(unsigned char[]){CMD_Control_Learn} length:1];
    [LGUtils writeData   :data
             charactUUID :CHARACTERISTIC_UUID_REMOTEBUDDYControl
             serviceUUID :SERVICE_UUID_REMOTEBUDDY
        peripheral   :_mBuddy completion:^(NSError *error)
        {
            // Befehl wurde übermittelt
            NSLog(@"Einlernen gesendet => Error : %@", error);
            // RB_Notification Data Ready auslesen
            [self checkForStatus:CHARACTERISTIC_UUID_REMOTEBUDDYNotification andServiceUUID: SERVICE_UUID_REMOTEBUDDY andPeripheral:_mBuddy];
    }];
    }
    
    -(void) checkForStatus:(NSString*)characteristic andServiceUUID:(NSString*) service andPeripheral:(CBPeripheral*) _mBuddy{
        [LGUtils readDataFromCharactUUID:CHARACTERISTIC_UUID_REMOTEBUDDYNotification
                                 serviceUUID:SERVICE_UUID_REMOTEBUDDY
                                  peripheral:_mBuddy
                                  completion:^(NSData *data, NSError *error)
             {
    
                 NSLog(@"Data : %@ Error : %@", data, error);
    
    
                 const uint8_t *bytes = [data bytes]; // pointer to the bytes in data
                 int data_int = bytes[0]; // first byte
    
                 switch(data_int)
                 {
                     case 0x01:
                         NSLog(@"Data ready!");
                         [self dataReady]; // some of yours functions
    
                         break;
                     case 0x02:
                         [self checkForStatus:CHARACTERISTIC_UUID_REMOTEBUDDYNotification andServiceUUID: SERVICE_UUID_REMOTEBUDDY andPeripheral:_mBuddy];
                         break;
                     case 0x00:
                         [self checkForStatus:CHARACTERISTIC_UUID_REMOTEBUDDYNotification andServiceUUID: SERVICE_UUID_REMOTEBUDDY andPeripheral:_mBuddy];
                         break;
                     default:
                         break;
                 }
             }
         ];
    
    }