Статьи

Bluetooth-соединение с GameKit

Из этого туториала iOS вы узнаете, как установить соединение Bluetooth между двумя устройствами iOS с помощью GKPeerPickerController , GKPeerPickerControllerDelegate , GKSession и GKSessionDelegate . Мы также рассмотрим, как отправлять данные туда и обратно через соединение, создавая простое приложение для обмена текстовыми сообщениями.


Запустите Xcode и нажмите « Файл»> «Создать»> «Проект» . Нажмите «Приложение» под панелью iOS слева. Нажмите значок «Одно приложение» и нажмите «Далее».

Соединение Bluetooth: скриншот экрана нового проекта

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

Соединение Bluetooth: скриншот 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 {}

Давайте создадим две кнопки, метку и текстовое поле для нашего текстового мессенджера. Нажмите на файл «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];

Две кнопки инициируют соединение и отправляют текстовое сообщение, в то время как текстовое поле содержит исходящее сообщение, а метка отображает входящее сообщение.


GameKit предоставляет простой способ подключения через Bluetooth. Используя GKPeerPickerControllerDelegate и GKSessionDelegate , все сложности соединения, такие как окна, чтобы показать соединения и кто находится рядом, делегатом автоматически решаются. Начните с импорта фреймворка GameKit. Нажмите на цель приложения, файл XCode указан в верхней части крайней левой панели. Прокрутите вниз до панели «Связанные фреймворки и библиотеки». Нажмите кнопку «плюс» и введите «GameKit». Нажмите «GameKit.framework», а затем нажмите «Добавить».

Bluetooth-соединение: добавление фреймворка GameKit

Нажмите на файл «ViewController.h» и отредактируйте следующий код, чтобы он соответствовал протоколам GKSessionDelegate и GKPeerPickerControllerDelegate .

1
@interface ViewController : UIViewController <GKSessionDelegate, GKPeerPickerControllerDelegate>

Каждый из двух классов выполняет разные задачи, связанные с соединением. 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.

Как только 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 для получения данных от его коллег, добавив следующий код.

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 . Далее текстовое свойство метки устанавливается как входящая строка.


Подключите устройство к вашему компьютеру. Нажмите Product> Run или стрелку Run в верхнем левом углу, чтобы создать и запустить приложение на устройстве. После запуска приложения на устройстве отключите его и подключите второе устройство к компьютеру. Создайте и запустите приложение на этом устройстве. Запустите приложение на обоих устройствах. Нажмите кнопку подключения на обоих устройствах и следуйте инструкциям для подключения ваших устройств. Введите сообщение и нажмите «Отправить», чтобы увидеть его на другом устройстве.


Следует иметь в виду, что соединение Bluetooth предназначено для отправки небольших фрагментов данных, таких как текст или набор чисел. Если вы планируете отправлять что-то большое, например фотографию, вам, вероятно, захочется использовать Wi-Fi или подключение к Интернету. Хотя это приложение, вероятно, не заставит вас отказаться от вашего любимого текстового мессенджера, оно показывает, как подключать и отправлять биты данных через Bluetooth, удобную функцию для любого приложения, которое может выиграть от обмена небольшими порциями данных между устройствами.