Ответ 1
Я предполагаю, что вы натыкаетесь на ограничение по 512 байт на характерную длину. Вам нужно перейти к подпискам на характеристики и обработку обновлений, чтобы обойти это:
В центре:
-
Подпишитесь на характеристику, вызвав
-[CBPeripheral setNotifyValue:forCharacteristic]
(с YES в качестве значения уведомления). -
В
-peripheral:didUpdateValueForCharacteristic:error
каждое обновление будет либо представлять собой данные для добавления, либо то, что вы решите использовать на периферийной стороне, чтобы указать конец данных (для этого я использую пустойNSData
). Обновите код-peripheral:didUpdateValueForCharacteristic:error
, чтобы:- Если вы начинаете читать значение, инициализируйте приемник для входящих байтов (например,
NSMutableData
). - Если вы находитесь в середине чтения значения, вы добавляете его в раковину.
- Если вы видите маркер EOD, вы считаете, что передача завершена. Вы можете отказаться от подписки на характеристику в этом состоянии, вызвав
-[CBPeripheral setNotifyValue:forCharacteristic]
со значением уведомления NO.
- Если вы начинаете читать значение, инициализируйте приемник для входящих байтов (например,
-
-peripheral:didUpdateNotificationStateForCharacteristic:error:
- хорошее место для управления инициализацией и последующим использованием раковины, в которую вы читаете куски. Еслиcharacteristic.isNotifying
обновлено доYES
, у вас есть новая подписка; если он обновлен доNO
, тогда вы закончите чтение. На данный момент вы можете использовать NSKeyedUnarchiver для разблокировки данных.
На периферии:
-
В
-[CBMutableCharacteristic initWithType:properties:value:permissions]
убедитесь, что значениеproperties
содержитCBCharacteristicPropertyNotify
. -
Используйте
-peripheralManager:central:didSubscribeToCharacteristic:
, чтобы начать отправку ваших данных, а не-peripheral:didReceiveReadRequest:result:
. -
При разбиении ваших данных убедитесь, что размер вашего куска не больше
central.maximumUpdateValueLength
. На iOS7, между iPad 3 и iPhone 5, я обычно видел 132 байта. Если вы отправляете несколько центров, используйте наименьшее общее значение. -
Вам нужно проверить код возврата
-updateValue:forCharacteristic:onSubscribedCentrals
; если базовая очередь поддерживает резервную копию, это вернетNO
, и вам придется дождаться обратного вызова на-peripheralManagerIsReadyToUpdateSubscribers:
, прежде чем продолжить (это, по-моему, одно из заусенцев в противном случае, гладкий API). В зависимости от того, как вы справляетесь с этим, вы можете рисовать себя в угол, потому что: -
Если вы создаете и отправляете свои куски в той же очереди, что периферийное устройство использует для своих операций, И, делая правильную вещь и проверяя возвращаемое значение из
-updateValue:forCharacteristic:onSubscribedCentrals:
, легко поддерживать себя в неочевидный тупик. Вы либо захотите удостовериться, что вы получаете очередь после каждого вызова-updateValue:forCharacteristic:onSubscribedCentrals:
, выполняете цикл chunking в другой очереди, чем в периферийной очереди (-updateValue:forCharacteristic:onSubscribedCentrals:
будет следить за тем, чтобы его работа была выполнена в нужном месте). Или вы могли бы стать фаворитом; просто помните об этом.
Чтобы увидеть это в действии, в видеообъявлении WWDC 2012 Advanced Core Bluetooth содержится пример (общий доступ к VCards), который охватывает большую часть этого. Однако он не проверяет возвращаемое значение для обновления, поэтому они избегают ошибок в # 4 вообще.
Надеюсь, что это поможет.