Из этого туториала 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, удобную функцию для любого приложения, которое может выиграть от обмена небольшими порциями данных между устройствами.