2017-02-09 4 views
1

私は現在、iOSデバイスとBluetooth Low Energy USBドングルの間でメッセージを交換するためにCBPeripheralDelegateと協力しています。私はシリアルエミュレーションサービスを使用してデータバイトを書き込むsendMessage:メソッドを実装する必要があります。この方法では、その時点で15バイト(またはそれ以下)のフレームを送信し、次のフレームを送信する前にドングルからのACKを待つ必要があります。以下はデリゲートメソッドが起動するまでforループをブロックする

は私のコードです:

- (void)sendMessage:(NSData *)message { 
    NSArray *chuncks = [self splitMessage:message]; 
    for (NSUInteger i = 0; i < chunks.count; i++) { 
     NSData *chunk = [chunks objectAtIndex:i]; 
     [self sendChunk:chunk withId:i ofChunks:chances.count]; 
     // Wait for the ack to be received 
    } 
} 

- (void)sendChunk:(NSData *)chunk withId:(NSInteger)id ofChunks:(NSInteger)count { 
    NSMutableData *frame = [NSMutableData new]; 
    // Here I build my frame, adding header, current chunk ID and total number of chunks, then I call... 
    [serialEmulationService writeValue:frame forCharacteristic:serialEmulationServiceCharacteristic type:CBCharacteristicWriteWithResponse]; 
} 

今問題:sendMessage:メソッド内forループは、周辺はおそらくタイムアウトで、ACKを受信しなくなるまでブロックされることがあります。このACKはデリゲートメソッド- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(nonnull CBCharacteristic *)characteristic error:(nullable NSError *)errorの中で受信されますので、ここで私はforループを以前にブロックし直さなければなりません。

この特定の状況のベストプラクティスは何ですか?私はGCDのセマフォを使いたいと思いますが、同期呼び出しを実装する方法を理解することはできず、このテクニックを説明する多くのオンラインの例を理解することはできません。

誰かが私に手を貸してくれますか?

答えて

1

どのように完全にforループをスキップについて...

@property (nonatomic) NSMutableArray *chunks; 
@property (nonatomic) NSInteger chunkId; 

- (void)sendMessage:(NSData *)message { 
    self.chunks = [[self splitMessage:message] mutableCopy]; 
    self.chunkId = 0; 

    [self sendNextChunk]; 
} 

- (void sendNextChunk { 

    NSData * chunk = self.chunks.firstObject; 

    if chunk == nil { 
     return 
    } 

    [self.chunks removeObjectAtIndex: 0]; 
    [self sendChunk:chunk withId:chunkId++ ofChunks:chances.count]; 
}  


- (void)sendChunk:(NSData *)chunk withId:(NSInteger)id ofChunks:(NSInteger)count { 
    NSMutableData *frame = [NSMutableData new]; 
    // Here I build my frame, adding header, current chunk ID and total number of chunks, then I call... 
    [serialEmulationService writeValue:frame forCharacteristic:serialEmulationServiceCharacteristic type:CBCharacteristicWriteWithResponse]; 
} 

- (void)peripheral:(CBPeripheral *)peripheral didUpdateValueForCharacteristic:(nonnull CBCharacteristic *)characteristic error:(nullable NSError *)error { 
    [self sendNextChunk]; 
} 
+0

十分に簡単、ありがとうございました。最もシンプルで簡単なアプローチ。ちょっとした発言:元の 'chunks'配列サイズのプロパティを定義する必要がありました。なぜなら、それはすべてのチャンク送信時に減少するからです。 – Dree

0

アプローチはNotificationを使用することです。 for loopを実行するにはseparate methodを作成してください。この方法では、Notificationののメソッドdelegateの内側にあるNotificationを観察します。 sendMessage:には、プロパティにメッセージを追加し続けます。

関連する問題