Из этого туториала iOS вы узнаете, как установить соединение Bluetooth между двумя устройствами iOS с помощью GKPeerPickerController , GKPeerPickerControllerDelegate , GKSession и GKSessionDelegate . Мы также рассмотрим, как отправлять данные туда и обратно через соединение, создавая простое приложение для обмена текстовыми сообщениями.
Шаг 1: Настройка проекта
Запустите Xcode и нажмите « Файл»> «Создать»> «Проект» . Нажмите «Приложение» под панелью iOS слева. Нажмите значок «Одно приложение» и нажмите «Далее».

В поле «Имя продукта» введите «BluetoothTextMessenger» и введите имя для идентификатора вашей компании, например «com.mobiletuts». Выберите «iPhone» в меню «Семейство устройств». Снимите флажки «Использовать раскадровки» и «Включить модульные тесты», а затем установите флажок «Использовать автоматический подсчет ссылок». Нажмите «Далее», выберите место для сохранения вашего проекта и нажмите «Создать».

Шаг 2: Объявление методов
Начнем с объявления и определения методов подключения к устройству и отправки данных. В файле «ViewController.m» добавьте следующий код:
|
1
2
3
4
5
6
7
8
|
@interface ViewController ()
— (void)sendMessage:(id)sender;
— (void)connectToDevice:(id)sender;
@end
— (void)connectToDevice:(id)sender {}
— (void)sendMessage:(id)sender {}
|
Шаг 3: Настройка интерфейса
Давайте создадим две кнопки, метку и текстовое поле для нашего текстового мессенджера. Нажмите на файл «ViewController.h» и добавьте следующий код:
|
1
2
3
4
|
@property (strong, nonatomic) UILabel *messageReceivedLabel;
@property (strong, nonatomic) UITextField *messageToSendTextField;
@property (strong, nonatomic) GKSession *session;
@property (strong, nonatomic) UIButton *sendButton;
|
Нажмите на файл «ViewController.m» и добавьте следующий код для завершения свойств.
|
1
2
3
4
|
@synthesize messageReceivedLabel = _messageReceivedLabel;
@synthesize messageToSendTextField = _messageToSendTextField;
@synthesize session = _session;
@synthesize sendButton = _sendButton;
|
Находясь в файле ViewController.m, добавьте следующий код для программного создания интерфейса:
|
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
|
//Button to connect to other device
UIButton *connectButton = [UIButton buttonWithType:UIButtonTypeRoundedRect];
connectButton.frame = CGRectMake(20.0f, 20.0f, 80.0f, 40.0f);
[connectButton setTitle:@»Connect» forState:UIControlStateNormal];
connectButton.tintColor = [UIColor darkGrayColor];
[connectButton addTarget:self action:@selector(connectToDevice:) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:connectButton];
//Button to send message to other device
UIButton *sendButton_ = [UIButton buttonWithType:UIButtonTypeRoundedRect];
sendButton_.frame = CGRectMake(220.0f, 20.0f, 80.0f, 40.0f);
[sendButton_ setTitle:@»Send» forState:UIControlStateNormal];
sendButton_.tintColor = [UIColor darkGrayColor];
sendButton_.enabled = NO;
[sendButton_ addTarget:self action:@selector(sendMessage:) forControlEvents:UIControlEventTouchUpInside];
self.sendButton = sendButton_;
[self.view addSubview:self.sendButton];
//Label for message that is received
self.messageReceivedLabel = nil;
CGRect messageReceivedLabel_Frame = CGRectMake(20.0f, 80.0f, 280.0f, 44.0f);
UILabel *messageReceivedLabel_ = [[UILabel alloc] initWithFrame:messageReceivedLabel_Frame];
messageReceivedLabel_.textAlignment = UITextAlignmentCenter;
messageReceivedLabel_.font = [UIFont boldSystemFontOfSize:20.0f];
self.messageReceivedLabel = messageReceivedLabel_;
[self.view addSubview:self.messageReceivedLabel];
//Text field to input message to send
CGRect messageToSendTextField_Frame = CGRectMake(20.0f, 144.0f, 280.0f, 44.0f);
UITextField *messageToSendTextField_ = [[UITextField alloc] initWithFrame:messageToSendTextField_Frame];
messageToSendTextField_.font = [UIFont systemFontOfSize:20.0f];
messageToSendTextField_.backgroundColor = [UIColor whiteColor];
messageToSendTextField_.clearButtonMode = UITextFieldViewModeAlways;
messageToSendTextField_.placeholder = @»Enter a message to send»;
messageToSendTextField_.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter;
self.messageToSendTextField = messageToSendTextField_;
[self.view addSubview:self.messageToSendTextField];
|
Две кнопки инициируют соединение и отправляют текстовое сообщение, в то время как текстовое поле содержит исходящее сообщение, а метка отображает входящее сообщение.
Шаг 4: Добавление фреймворка
GameKit предоставляет простой способ подключения через Bluetooth. Используя GKPeerPickerControllerDelegate и GKSessionDelegate , все сложности соединения, такие как окна, чтобы показать соединения и кто находится рядом, делегатом автоматически решаются. Начните с импорта фреймворка GameKit. Нажмите на цель приложения, файл XCode указан в верхней части крайней левой панели. Прокрутите вниз до панели «Связанные фреймворки и библиотеки». Нажмите кнопку «плюс» и введите «GameKit». Нажмите «GameKit.framework», а затем нажмите «Добавить».

Шаг 5: Соответствие делегатам
Нажмите на файл «ViewController.h» и отредактируйте следующий код, чтобы он соответствовал протоколам GKSessionDelegate и GKPeerPickerControllerDelegate .
|
1
|
@interface ViewController : UIViewController <GKSessionDelegate, GKPeerPickerControllerDelegate>
|
Шаг 6: Добавление логики подключения
Каждый из двух классов выполняет разные задачи, связанные с соединением. GKPeerPickerController предоставляет интерфейс для установления соединения между двумя устройствами, а затем предоставляет объект GKSession в результате соединения. Затем объект GKSession обрабатывает соединение и любые передаваемые данные в зависимости от того, как настроено ваше приложение.
Установление соединения
Давайте добавим логику в том порядке, в котором это происходит. Сначала мы создадим соединение с помощью GKPeerPickerController . Вернитесь к ранее определенному методу connectToDevice: и добавьте следующую логику в фигурные скобки, чтобы попытаться подключиться к устройству при нажатии кнопки подключения.
|
1
2
3
4
5
6
7
|
if (self.session == nil) {
//create peer picker and show picker of connections
GKPeerPickerController *peerPicker = [[GKPeerPickerController alloc] init];
peerPicker.delegate = self;
peerPicker.connectionTypesMask = GKPeerPickerConnectionTypeNearby;
[peerPicker show];
}
|
В приведенном выше коде мы проверяем, нет ли сеанса, то есть устройство не подключено. Если сеанс отсутствует, создается GKPeerPickerController и ViewController назначается в качестве делегата, чтобы он мог реализовывать методы GKPeerPickerControllerDelegate . Наконец, на GKPeerPickerController отображается GKPeerPickerController со списком доступных близлежащих соединений Bluetooth.
Получение объекта GKSession
Как только peerPicker показан, вызывается серия методов делегата, которые обрабатывают соединение. Оставаясь в файле «ViewController.m», добавьте следующий код:
|
1
2
3
4
5
6
7
8
|
— (GKSession *)peerPickerController:(GKPeerPickerController *)picker sessionForConnectionType:(GKPeerPickerConnectionType)type
{
//create ID for session
NSString *sessionIDString = @»MTBluetoothSessionID»;
//create GKSession object
GKSession *session = [[GKSession alloc] initWithSessionID:sessionIDString displayName:nil sessionMode:GKSessionModePeer];
return session;
}
|
Этот метод делегата получает сеанс на основе указанного типа соединения. В этом случае используется GKSessionModePeer потому что мы хотим искать устройства подключения как клиент и объявлять подключение как сервер. Идентификатор sessionID необходим для идентификации сеанса и может иметь любое значение, соответствующее вашим потребностям. GKSession использует идентификатор sessionID качестве идентификатора, и новые одноранговые узлы могут использовать идентификатор для подключения к тому же GKSession
Увольнение сборщика
Затем вы захотите реализовать peerPickerController:didConnectPeer:toSession: для того, чтобы взять под контроль сеанс и отклонить peerPickerController:didConnectPeer:toSession: выбора. Введите следующий код в файле «ViewController.m».
|
1
2
3
4
5
6
7
8
|
— (void)peerPickerController:(GKPeerPickerController *)picker didConnectPeer:(NSString *)peerID toSession:(GKSession *)session
{
//set session delegate and dismiss the picker
session.delegate = self;
self.session = session;
picker.delegate = nil;
[picker dismiss];
}
|
Для делегата сеанса установлено значение self чтобы ViewController мог реализовывать методы GKSessionDelegate . Затем ViewController удаляется как делегат средства выбора, а ViewController выбора отклоняется, поскольку оно больше не требуется.
Установите ViewController для получения данных
Задайте объект ViewController для получения данных от его коллег, добавив следующий код.
|
01
02
03
04
05
06
07
08
09
10
11
12
|
— (void)session:(GKSession *)session peer:(NSString *)peerID didChangeState:(GKPeerConnectionState)state
{
if (state == GKPeerStateConnected){
[session setDataReceiveHandler:self withContext:nil];
self.sendButton.enabled = YES;
}
else {
self.sendButton.enabled = NO;
self.session.delegate = nil;
self.session = nil;
}
}
|
Каждый раз, когда состояние соединения изменяется, вызывается этот метод делегата. В коде мы проверяем, подключен ли сеанс, и, если это так, ViewController настроен на обработку данных, полученных от пиров, подключенных к сеансу. Если сеанс не подключен, делегат и сеанс устанавливаются равными nil, чтобы можно было установить другое соединение.
Отправка данных
Чтобы отправить содержимое текстового поля на подключенное устройство, вернитесь к ранее определенному методу sendMessage: и добавьте следующий код в фигурные скобки.
|
1
2
3
4
|
//package text field text as NSData object
NSData *textData = [self.messageToSendTextField.text dataUsingEncoding:NSASCIIStringEncoding];
//send data to all connected devices
[self.session sendDataToAllPeers:textData withDataMode:GKSendDataReliable error:nil];
|
Первая строка упаковывает текст текстового поля как объект NSData чтобы его можно было отправить через Bluetooth. Вторая строка указывает сеансу отправлять данные всем партнерам, подключенным к сеансу.
Получение данных
Данные, полученные от однорангового узла, поступают в форме объекта NSData . Чтобы распаковать текст, добавьте следующий код:
|
1
2
3
4
5
6
7
|
— (void)receiveData:(NSData *)data fromPeer:(NSString *)peer inSession:(GKSession *)session context:(void *)context
{
//unpackage NSData to NSString and set incoming text as label’s text
NSString *receivedString = [[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding];
self.messageReceivedLabel.text = receivedString;
}
|
Первая строка кода в этом методе распаковывает объект NSData , возвращая объект NSString . Далее текстовое свойство метки устанавливается как входящая строка.
Шаг 7: Тестирование соединения
Подключите устройство к вашему компьютеру. Нажмите Product> Run или стрелку Run в верхнем левом углу, чтобы создать и запустить приложение на устройстве. После запуска приложения на устройстве отключите его и подключите второе устройство к компьютеру. Создайте и запустите приложение на этом устройстве. Запустите приложение на обоих устройствах. Нажмите кнопку подключения на обоих устройствах и следуйте инструкциям для подключения ваших устройств. Введите сообщение и нажмите «Отправить», чтобы увидеть его на другом устройстве.
Вывод
Следует иметь в виду, что соединение Bluetooth предназначено для отправки небольших фрагментов данных, таких как текст или набор чисел. Если вы планируете отправлять что-то большое, например фотографию, вам, вероятно, захочется использовать Wi-Fi или подключение к Интернету. Хотя это приложение, вероятно, не заставит вас отказаться от вашего любимого текстового мессенджера, оно показывает, как подключать и отправлять биты данных через Bluetooth, удобную функцию для любого приложения, которое может выиграть от обмена небольшими порциями данных между устройствами.