Полный процесс построения приложения интерактивной переписки для iPhone

Создание впечатляющего приложения для iPhone и соответствующего серверного компонента для этого приложения

В статье последовательно описывается весь процесс построения приложения интерактивной переписки для iPhone – от серверного компонента и вплоть до пользовательского интерфейса на фронтальной части.

Джек Д Херрингтон, главный инженер-программист, Leverage Software Inc.

Джек Д. Херрингтон (Jack D. Herrington) - главный инженер-программист с более чем двадцатилетним опытом работы. Он автор трех книг: "Генерирование кода в действии", "Podcasting Hacks" и "PHP Hacks". Написал более 30 статей. Вы можете связаться с Джеком по адресу jherr@pobox.com.



20.05.2011

Разработка архитектуры приложения интерактивной переписки для iPhone

Часто используемые сокращения

  • DOM: Document Object Model
  • IDE: Integrated development environment (Интегрированная среда разработки)
  • SAX: Simple API for XML
  • SQL: Structured Query Language
  • UI: User interface (Интерфейс пользователя)
  • W3C: World Wide Web Consortium
  • XIB: Xml Interface Builder
  • XML: Extensible Markup Language (Расширяемый язык разметки)

В условиях, когда на руках у пользователей находится примерно 40 миллионов устройств iPhone, написание приложений для платформы iOS представляет огромный интерес. С чего начать? Большая часть этих приложений будет подключена к сети. Поэтому мы рассмотрим проект, который охватывает и клиентские, и серверные компоненты, - а именно приложение для интерактивной переписки. В этой статье я демонстрирую, как построить такое приложение, содержащее серверный и клиентский компоненты. Я гарантирую, что после освоения материала этой статьи вы сможете самостоятельно создать свое собственное приложение для iOS.

Построение приложения начинается с разработки архитектуры решения. На рисунке 1 показана архитектура, связывающая iOS-устройство (в данном случае iPhone) с сервером с помощью двух PHP-страниц.

Рисунок 1. Клиент-серверная архитектура приложения для интерактивной переписки
Diagram of iPhone client with add.php and messages.php pages connected to a database


Эти две PHP-страницы (add.php и messages.php) подключаются к базе данных с целью отправки и извлечения сообщений соответственно. В коде, который я предоставил для этой статьи, в качестве базы данных используется MySQL, однако вы можете использовать DB2 или любую другую базу данных.

Я использую протокол XML. Страница add.php возвращает XML-сообщение, которое говорит о том, была ли отправка сообщения успешной. Страница messages.php возвращает последние сообщения, отправленные на сервер.

Прежде чем переходить к основному материалу статьи, перечислю все рассматриваемые в ней темы.

  • Доступ к базе данных. Я показываю, как использовать PHP для добавления строк в базу данных и извлечения этих строк из базы данных.
  • Кодирование XML. Серверный код демонстрирует, как упаковывать сообщения в формат XML.
  • Построение интерфейса iOS. Я последовательно описываю построение пользовательского интерфейса для приложения.
  • Запросы к серверу. Код на языке Objective-C осуществляет запросы GET к странице messages.php с целью получения новых сообщений.
  • Разбор XML. С помощью XML-парсера для iOS разработчиков вы сможете разбирать XML-сообщения, возвращаемые страницей messages.php.
  • Отображение сообщений. Приложение использует пользовательский элемент list для демонстрации сообщений интерактивной переписки; этот подход позволит вам понять, как настроить облик своего iOS приложения.
  • Отправка сообщения. Приложение отправляет (POST) данные на сервер через страницу add.php.
  • Таймеры. Таймер используется для периодического опроса страницы messages.php на предмет поступления новых сообщений интерактивной переписки.

Применяемый в рассматриваемом примере набор инструментов позволит вам разрабатывать клиент-серверные iOS-приложения любого типа.


Построение серверного компонента

Для начала создадим базу данных. Я дал своей базе данных имя «chat», однако вы можете назвать свою базу данных любым именем. Для этого достаточно изменить связывающие строки в PHP в соответствии с этим именем базы данных. SQL-скрипт, используемый при построения единственной таблицы для описываемого приложения, показан в листинге 1.

Листинг 1. Скрипт chat.sql
DROP TABLE IF EXISTS chatitems;
CREATE TABLE chatitems (
    id BIGINT NOT NULL PRIMARY KEY auto_increment,
    added TIMESTAMP NOT NULL,
    user VARCHAR(64) NOT NULL,
    message VARCHAR(255) NOT NULL
);

Эта простая база данных с единственной таблицей имеет всего четыре поля:

  • Идентификатор строки (id), представляющий собой целое число с автоматическим приращением
  • Дата добавления данного сообщения
  • Пользователь, добавивший данное сообщение
  • Текст самого сообщения

Вы можете изменять размеры этих полей в соответствии со своим контентом.

Весьма вероятно, что в системе производственного уровня вы захотите иметь таблицу пользователей с именами/паролями, а также интерфейс для входа пользователей в систему и т.д. В этом примере я хотел сохранить простоту базы данных, поэтому в ней лишь одна таблица.

Итак, сначала необходимо сконструировать скрипт add.php, показанный в листинге 2

Листинг 2. Скрипт add.php
<?php
header( 'Content-type: text/xml' );
mysql_connect( 'localhost:/tmp/mysql.sock', 'root', '' );
mysql_select_db( 'chat' );
mysql_query( "INSERT INTO chatitems VALUES ( null, null, '".
    mysql_real_escape_string( $_REQUEST['user'] ).
    "', '".
    mysql_real_escape_string( $_REQUEST['message'] ).
    "')" );
?>
<success />

Этот скрипт подключается к базе данных и сохраняет сообщение с помощью полей user и message. Это простой оператор INSERT, в котором эти два значения снабжаются escape-символами для правильной передачи специальных символов, таких как одинарные кавычки, которые могли бы нарушить синтаксис SQL.

Чтобы протестировать скрипт add, создадим страницу test.html, показанную в листинге 3, которая просто отправляет поля в скрипт add.php.

Листинг 3. Страница test.html
<html>
<head>
    <title>Chat Message Test Form</title>
</head>
<body>
    <form action="add.php" method="POST">
        User: <input name="user" /><br />
        Message: <input name="message" /><br />
        <input type="submit" />
    </form>
</body>
</html>

Эта простая страница имеет лишь одну форму, указывающую на add.php, с двумя текстовыми полями – User (пользователь) и Message (сообщение). Кроме того, на этой странице есть кнопка Submit, которая осуществляет отправку.

Страница test.html позволяет протестировать скрипт add.php. Открытая в браузере тестовая страница выглядит, как показано на рисунке 2. В поле User отображается значение «jack», в поле Message отображается «This is a test». Кроме того, присутствует кнопка Submit Query.

Рисунок 2. Тестовая страница для отправки сообщения
Screen capture of page with User and Message fields plus Submit Query button

На этой странице введите какие-либо значения, а затем нажмите на кнопку Submit Query. Если все работает хорошо, вы увидите следующую картину (см. рисунок 3).

Рисунок 3. Успешная отправка сообщения
Screen capture of XML file viewed in browser with a <success/> element

В противном случае вы, скорее всего, получите содержимое стека PHP, информирующее о неудачном подключении к базе данных или о несработавшем операторе INSERT.

Теперь, когда у нас есть работающий скрипт для добавления сообщений, создадим скрипт messages.php, который будет возвращать список сообщений. Этот скрипт показан в листинге 4.

Листинг 4. Скрипт messages.php
<?php
header( 'Content-type: text/xml' );
mysql_connect( 'localhost:/tmp/mysql.sock', 'root', '' );
mysql_select_db( 'chat' );
if ( $_REQUEST['past'] ) {
    $result = mysql_query('SELECT * FROM chatitems WHERE id > '.
        mysql_real_escape_string( $_REQUEST['past'] ).
        ' ORDER BY added LIMIT 50');
} else {
    $result = mysql_query('SELECT * FROM chatitems ORDER BY added LIMIT 50' );    
}
?>
<chat>
<?php
while ($row = mysql_fetch_assoc($result)) {
?>
<message added="<?php echo( $row['added'] ) ?>" id="<?php echo( $row['id'] ) ?>">
    <user><?php echo( htmlentities( $row['user'] ) ) ?></user>
    <text><?php echo( htmlentities( $row['message'] ) ) ?></text>
</message>
<?php
}
mysql_free_result($result);
?>
</chat>

Этот скрипт несколько сложнее, чем предыдущий. Сначала он формирует запрос. В данном случае есть две возможности:

  • Если параметр past был специфицирован, то скрипт возвращает только отосланные сообщения с указанным идентификатором ID.
  • Если параметр past не был специфицирован, то скрипт возвращает все сообщения.

Смысл применения параметра past – повышение «разумности» клиента. Мы хотим, чтобы клиент помнил, какие сообщения он уже просмотрел, и запрашивал только новые сообщения. Логика клиента достаточно проста, она сохраняет только самое большое из найденных значений идентификатора ID и посылает его в виде параметра past. В начале работы может быть послано значение «0», что равносильно отсутствию значения.

Во второй половине скрипта осуществляется извлечение записей из результатов запроса и кодирование этих записей в формат XML. Если эта часть скрипта сработает успешно, то при открытии этой страницы в своем браузере вы увидите следующую картину (см. рисунок 4).

Рисунок 4. Список сообщений интерактивной переписки
Screen capture of short chat message coded in XML, includes timestamp, ID, user, and message text

Это все, что необходимо для нашего серверного компонента. Конечно, вы можете добавить любую логику, какую только захотите, дополнительные каналы, проверку пользователя при входе в систему и т.д. Тем не менее применительно к используемому в статье экспериментальному приложению интерактивной переписки данный скрипт работает прекрасно. Теперь мы можем построить приложение iOS, которое будет использовать этот сервер.


Построение клиентского компонента

Интегрированная среда разработки (IDE) для платформы iOS имеет название XCode. Если у вас нет этой IDE-среды, необходимо загрузить ее с сайта Apple Developer Site для разработчиков (см. раздел Ресурсы). Новая версия производственного уровня имеет номер XCode 3. Именно она использовалась при создании снимков экрана для данной статьи. Имеется более современная версия под номером XCode 4, в которой редактор User Interface интегрирован в среду IDE, однако на данный момент эта версия еще находится на стадии предварительного ознакомления.

При наличии установленной среды XCode можно приступить к построению приложения с помощью мастера New Project (см. рисунок 5).

Рисунок 5. Построение основанного на представлении приложения для iPhone
Screen capture of selected template options: iPhone OS > Application and Product > iPhone > View-based Application

Самым простым в освоении типом приложения является т.н. View-based Application (приложение на основе представления). Такое приложение позволяет разработчику помещать органы управления в любом месте и оставляет ему большую часть дизайна пользовательского интерфейса. После выбора органов управления выберите тип продукта: iPhone или iPad. Этот выбор определяет устройство, работу с которым вы собираетесь имитировать. Вы сможете написать программный код, который будет работать с iPhone или iPad или с любым другим устройством Apple серии i, если такое появится в будущем.

После того как вы нажмете на кнопку Choose, вам будет предложено дать имя приложению. Я назвал свое приложение «iOSChatClient», однако вы можете дать ему любое имя. После того как вы дадите имя приложению, интегрированная среда разработки XCode создаст для него базовые файлы. Теперь скомпилируйте и запустите приложение, чтобы убедиться в том, что все выглядит надлежащим образом.

Создание пользовательского интерфейса

После создания приложения можно приступать к разработке интерфейса. Сначала нам потребуется XIB-файл контроллера представления, который находится в папке Resources. Нажмите два раза на этой папке. Откроется инструмент Interface Builder, предназначенный для создания интерфейса пользователя.

Рисунок 6. Макет интерфейса
Screen capture of UI with a message text box, Send button, and list of chat items

На рисунке 6 показано, каким образом я разместил три органа управления. Текстовое окошко в верхней части предназначено для ввода сообщения, которое вы собираетесь отослать. Справа от этого текста окошка находится кнопка Send. И, наконец, ниже этого окошка находится объект UITableView, который отображает все элементы интерактивной переписки.

Я мог бы подробно рассказать о настройке вышеупомянутых органов в инструменте Interface Builder, однако я рекомендую вам загрузить код проекта и поработать с ним самостоятельно. Вы можете использовать данный проект в качестве шаблона для своего собственного приложения.

Создание контроллера представления

Пользовательский интерфейс практически готов. Теперь мы вернемся в IDE-среду XCode и добавим в определение класса контроллера представления необходимые переменные, свойства и методы (см. листинг 5).

Листинг 5. Определение класса iOSChatClientViewController.h
#import <UIKit/UIKit.h>

@interface iOSChatClientViewController : UIViewController 
                             <UITableViewDataSource,UITableViewDelegate>    {
    IBOutlet UITextField *messageText;
    IBOutlet UIButton *sendButton;
    IBOutlet UITableView *messageList;

    NSMutableData *receivedData;
    NSMutableArray *messages;
    int lastId;

    NSTimer *timer;

    NSXMLParser *chatParser;
    NSString *msgAdded;
    NSMutableString *msgUser;
    NSMutableString *msgText;
    int msgId;
    Boolean inText;
    Boolean inUser;
}

@property (nonatomic,retain) UITextField *messageText;
@property (nonatomic,retain) UIButton *sendButton;
@property (nonatomic,retain) UITableView *messageList;

- (IBAction)sendClicked:(id)sender;

@end

В верхней части я добавил в определение класса код UITableViewDataSource и UITableViewDelegate. Этот код используется для отображения сообщения. В данном классе находятся методы, которые вызываются для доставки таблицы данных и информации о размещении в представление.

Переменные экземпляра делятся на пять групп. В верхней части находятся объектные ссылки на различные элементы пользовательского интерфейса, текстовое поле для отсылаемого сообщения, кнопка Send и список сообщений.

Ниже находятся буфер для возвращенного XML-контента, список сообщений и идентификатор последнего просмотренного сообщения lastID. Сначала значение идентификатора lastID равно нулю, однако затем ему присваивается максимальное значение идентификатора ID из просмотренных вами сообщений. Затем это значение отсылается обратно на сервер как значение параметра past.

Таймер каждые несколько секунд инициирует просмотр новых сообщений от сервера. И, наконец, в последнем разделе находятся рабочие переменные, необходимые для разбора XML-контента. Большое число этих переменных объясняется тем, что XML-парсер базируется на обратных вызовах (callback), поэтому ему необходимо множество состояний в классе.

Под рабочими переменными находятся свойства и обработчик нажатий (click handler). Инструмент Interface Builder использует их для подключения элементов интерфейса к описываемому классу контроллера. Теперь, когда мы имеем все необходимое для реализации контроллера представления, пришло время вернуться в инструмент Interface Builder и использовать его коннекторные механизмы для связывания текста сообщения, кнопки Send и списка сообщений с соответствующим свойствами, а также для связывания события Touch Inside с методом sendClicked.

Построение кода контроллера представления

Теперь мы можем перейти к сути нашего проекта и реализовать контроллер представления. Несмотря на то, что реализация представляет собой всего один файл, я разделил ее на несколько листингов – чтобы упростить пояснения по каждому разделу.

Первый раздел, показанный в листинге 6, охватывает запуск приложения и инициализацию контроллера представления.

Листинг 6. Определение класса iOSChatClientViewController.m - Начало
#import "iOSChatClientViewController.h"

@implementation iOSChatClientViewController

@synthesize messageText, sendButton, messageList;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
    if ((self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil])) {
        lastId = 0;
        chatParser = NULL;
    }
    return self;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:
                                       (UIInterfaceOrientation)interfaceOrientation {
    return YES;
}

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
}

- (void)viewDidUnload {
}

- (void)dealloc {
    [super dealloc];
}

Это совершенно стандартный код iOS. В нем присутствует несколько обратных вызовов для событий системных переменных, таких как предупреждения памяти и освобождение ресурсов. В приложении производственного уровня с этими элементами можно было бы обращаться более аккуратно, однако я не хотел чрезмерно усложнять наше учебное приложение.

Первая реальная задача – это подача запроса GET к скрипту messages.php. Соответствующий код показан в листинге 7.

Листинг 7. Определение класса iOSChatClientViewController.m – Получение сообщений
- (void)getNewMessages {
    NSString *url = [NSString stringWithFormat:
        @"http://localhost/chat/messages.php?past=%ld&t=%ld",
        lastId, time(0) ];

    NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] init] autorelease];
    [request setURL:[NSURL URLWithString:url]];
    [request setHTTPMethod:@"GET"];

    NSURLConnection *conn=[[NSURLConnection alloc] initWithRequest:request delegate:self];
    if (conn)
    {
        receivedData = [[NSMutableData data] retain];
    }
    else
    {
    }
}

- (void)connection:(NSURLConnection *)connection
  didReceiveResponse:(NSURLResponse *)response
{  
    [receivedData setLength:0];
}  

- (void)connection:(NSURLConnection *)connection 
  didReceiveData:(NSData *)data  
{  
    [receivedData appendData:data];
}  

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{  
    if (chatParser)
        [chatParser release];

    if ( messages == nil )
        messages = [[NSMutableArray alloc] init];

    chatParser = [[NSXMLParser alloc] initWithData:receivedData];
    [chatParser setDelegate:self];
    [chatParser parse];

    [receivedData release];

    [messageList reloadData];

    NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:
    [self methodSignatureForSelector: @selector(timerCallback)]];
    [invocation setTarget:self];
    [invocation setSelector:@selector(timerCallback)];
    timer = [NSTimer scheduledTimerWithTimeInterval:5.0 
        invocation:invocation repeats:NO];
}

- (void)timerCallback {
    [timer release];
    [self getNewMessages];
}

Код начинается с метода getNewMessages. Этот метод создает запрос и запускает его посредством построения NSURLConnection. Кроме того, он создает буфер, в котором содержатся ответные данные. Разные фазы загрузки данных обслуживаются соответствующими обработчиками событий: didReceieveResponse, didReceiveData, и connectionDidFinishLoading.

Самым важным является метод connectionDidFinishLoading - он запускает XML-парсер, который прочитывает данные и выбирает сообщения.

Заключительный метод в этом коде, timerCallback, используется таймером для запуска запроса нового сообщения. После завершения этого таймера вызывается метод getNewMessages, который снова запускает процесс, приводящий к созданию нового таймера, после завершения которого снова запускается процесс извлечения сообщения и т.д.

Следующий раздел, показанный в листинге 8, осуществляет разбор XML-контента.

Листинг 8. Определение класса iOSChatClientViewController.m – Разбор сообщений
- (void)parser:(NSXMLParser *)parser 
didStartElement:(NSString *)elementName 
namespaceURI:(NSString *)namespaceURI 
qualifiedName:(NSString *)qName 
attributes:(NSDictionary *)attributeDict {
    if ( [elementName isEqualToString:@"message"] ) {
        msgAdded = [[attributeDict objectForKey:@"added"] retain];
        msgId = [[attributeDict objectForKey:@"id"] intValue];
        msgUser = [[NSMutableString alloc] init];
        msgText = [[NSMutableString alloc] init];
        inUser = NO;
        inText = NO;
    }
    if ( [elementName isEqualToString:@"user"] ) {
        inUser = YES;
    }
    if ( [elementName isEqualToString:@"text"] ) {
        inText = YES;
    }
}

- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string {
    if ( inUser ) {
        [msgUser appendString:string];
    }
    if ( inText ) {
        [msgText appendString:string];
    }
}

- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName 
   namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName {
    if ( [elementName isEqualToString:@"message"] ) {
        [messages addObject:[NSDictionary dictionaryWithObjectsAndKeys:msgAdded,
            @"added",msgUser,@"user",msgText,@"text",nil]];

        lastId = msgId;

        [msgAdded release];
        [msgUser release];
        [msgText release];
    }
    if ( [elementName isEqualToString:@"user"] ) {
        inUser = NO;
    }
    if ( [elementName isEqualToString:@"text"] ) {
        inText = NO;
    }
}

Этот XML-парсер должен быть понятен каждому, кто знаком с технологией SAX. Вы отправляете в этот парсер какой-либо XML-контент, а он сообщает вам об открываемых и закрываемых тегах, о нахождении текста и т.д. Это управляемый событиями парсер, а не парсер на базе DOM. У парсеров на основе событий есть существенное преимущество – они занимают мало места в памяти. Однако у них имеется и недостаток – такие парсеры сложнее в использовании, поскольку в процессе разбора необходимо хранить все состояние в хост-объекте.

Процесс начинается с инициализации всех рабочих переменных (msgAdded, msgUser, inUser, и inText) посредством пустой строки или значения false. Затем, по мере запуска каждого тега в методе didStartElement, код смотрит на имя тега и устанавливает соответствующую логическую переменную inUser или inText. После этого метод foundCharacters обрабатывает текстовые данные, добавляемые в соответствующую строку. И, наконец, метод didEndElement осуществляет закрытие тега – при нахождении конца тега <message> этот метод добавляет разобранное сообщение к списку сообщений.

Теперь нам необходим программный код для отображения сообщений. Этот код показан в листинге 9

Листинг 9. Определение класса iOSChatClientViewController.m – Отображение сообщений
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 1;
}

- (NSInteger)tableView:(UITableView *)myTableView numberOfRowsInSection:
                                       (NSInteger)section {
    return ( messages == nil ) ? 0 : [messages count];
}


- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:
                                       (NSIndexPath *)indexPath {
    return 75;
}

- (UITableViewCell *)tableView:(UITableView *)myTableView 
   cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    UITableViewCell *cell = (UITableViewCell *)[self.messageList 
        dequeueReusableCellWithIdentifier:@"ChatListItem"];
    if (cell == nil) {
        NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"ChatListItem" 
            owner:self options:nil];
        cell = (UITableViewCell *)[nib objectAtIndex:0];
    }

    NSDictionary *itemAtIndex = (NSDictionary *)[messages objectAtIndex:indexPath.row];
    UILabel *textLabel = (UILabel *)[cell viewWithTag:1];
    textLabel.text = [itemAtIndex objectForKey:@"text"];
    UILabel *userLabel = (UILabel *)[cell viewWithTag:2];
    userLabel.text = [itemAtIndex objectForKey:@"user"];

    return cell;
}

В листинге 9 представлены методы, заданные интерфейсами UITableViewDataSource и UITableViewDelegate. Самым важным является метод cellForRowAtIndexPath, который создает специальный интерфейс пользователя для элемента list и заполняет его текстовые поля соответствующим текстом для текущего сообщения.

Этот пользовательский элемент list задается в новом файле ChatListItem.xib, который мы должны создать в папке Resources. В этом файле мы создадим новый элемент UITableViewCell, имеющий две метки (1 и 2). Этот файл содержится в предлагаемом для загрузки проекте вместе со всем остальным программным кодом (см. раздел Загрузка).

Код в методе cellForRowAtIndexPath назначает одну из ячеек ChatListItem, а затем настраивает текстовое поле для меток данного текста и для пользовательских значений, которые мы нашли для вышеуказанного сообщения.

Итак, мы почти достигли финиша. У нас уже есть код для запуска представления, для получения XML-сообщения, для разбора этого сообщения и для его отображения. Нам остается лишь написать код, который будет отсылать сообщение.

Сначала необходимо создать настройку для имени пользователя. Приложения iOS позволяют задавать пользовательские настройки, отображаемые на панели управления Settings. С помощью мастера New File создайте в папке Resources пакет настроек. Затем сверните его до единственного параметра настройки с помощью редактора настроек, показанного на рисунке 7.

Рисунок 7. Настройка параметров
Screen capture of the settings editor

Теперь дайте этому параметру настройки имя User и ключ user_preference. После этого вы можете использовать эту настройку при получении имени пользователя для кода, отсылающего сообщение (см. листинг 10).

Листинг 10. Определение класса iOSChatClientViewController.m – Отсылка сообщения
- (IBAction)sendClicked:(id)sender {
    [messageText resignFirstResponder];
    if ( [messageText.text length] > 0 ) {
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

        NSString *url = [NSString stringWithFormat:
            @"http://localhost/chat/add.php"];

        NSMutableURLRequest *request = [[[NSMutableURLRequest alloc] 
            init] autorelease];
        [request setURL:[NSURL URLWithString:url]];
        [request setHTTPMethod:@"POST"];

        NSMutableData *body = [NSMutableData data];
        [body appendData:[[NSString stringWithFormat:@"user=%@&message=%@", 
             [defaults stringForKey:@"user_preference"], 
             messageText.text] dataUsingEncoding:NSUTF8StringEncoding]];
        [request setHTTPBody:body];

        NSHTTPURLResponse *response = nil;
        NSError *error = [[[NSError alloc] init] autorelease];
        [NSURLConnection sendSynchronousRequest:request 
            returningResponse:&response error:&error];

        [self getNewMessages];
    }

    messageText.text = @"";
}

- (void)viewDidLoad {
        [super viewDidLoad];

    messageList.dataSource = self;
    messageList.delegate = self;

    [self getNewMessages];
}

@end

Это код обработчика нажатий для кнопки Send Message. Он создает запрос NSMutableURLRequest, имеющий URL-адрес для скрипта add.php. Затем он представляет тело сообщения в виде строки, в которой данные пользователя и сообщения закодированы в формате POST. После этого описываемый код использует NSURLConnection для синхронной пересылки данных сообщения на сервер и запускает извлечение сообщения с помощью getNewMessages.

Вызов метод viewDidLoad, показанного в нижней части листинга 10, осуществляется при загрузке представления. Он запускает процесс извлечения сообщения и связывает список сообщений с этим объектом, благодаря чему список сообщений «знает», откуда получать соответствующие данные.

Итак, мы завершили создание программного кода. Теперь пришло время протестировать наше приложение. Начнем с задания имени пользователя на странице Settings (см. рисунок 8).

Рисунок 8. Страница Settings
Screen capture of Setting page with General, Safari, Photos, and iOSChatClient options

Нажмите на название приложения iOSChatClient, будет отображена страница его параметров настройки (см. рисунок 9).

Рисунок 9. Задание имени пользователя
Screen capture of iOSChatClient settings page with value of 'Megan' in the User field

Теперь вернемся к приложению и введем сообщение с помощью имитатора клавиатуры телефона (см. рисунок 10).

Рисунок 10. Ввод нового сообщения
Screen capture of QWERTY keyboard, message text box, Send button, and a test message from user jack

После нажатия на кнопку Send мы увидим, что сообщение ушло на сервер, затем было отправлено, и, наконец, возвратилось из messages.php (см. рисунок 11).

Рисунок 11. Приложение интерактивной переписки готово
Screen capture of message text box, Send button, and two test messages from users jack and megan

При рассмотрении программного кода можно заметить отсутствие непосредственной связи между кнопкой Send и списком сообщений. Таким образом, единственный способ попадания сообщения в список – это его прохождение через сервер, который успешно вставит соответствующие данные в базу данных. Затем код message.php успешно возвратит это сообщение с целью его отображения в списке сообщений.


Заключение

Вы многому научились из этой статьи. Вы проделали определенную работу с XML-контентом базы данных на серверном компоненте. Вы создали iOS-приложение с индивидуализированным пользовательским интерфейсом, который отсылает данные на сервер и извлекает данные с сервера. Вы применили XML-парсер для разбора XML-ответа от сервера. И, наконец, вы создали собственный элемент list для пользовательского интерфейса, чтобы сделать облик сообщений более привлекательным.

Теперь вы можете самостоятельно выбрать направление своей дальнейшей деятельности. Компания Apple предоставила вам инструменты для реализации любых идей для iPhone или iPad. Кроме того, эта статья показала вам, как создавать собственные сетевые приложения. Я настоятельно рекомендую вам воспользоваться полученными знаниями на практике. Если вы действительно создадите нечто выдающееся, пожалуйста, сообщите мне об этом. Я обязательно проверю ваш продукт и размещу его на ресурсе App Store.


Загрузка

ОписаниеИмяРазмер
Исходный код к статьеChatProject.zip29 KБ

Ресурсы

Научиться

Получить продукты и технологии

Обсудить

Комментарии

developerWorks: Войти

Обязательные поля отмечены звездочкой (*).


Нужен IBM ID?
Забыли Ваш IBM ID?


Забыли Ваш пароль?
Изменить пароль

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Профиль создается, когда вы первый раз заходите в developerWorks. Информация в вашем профиле (имя, страна / регион, название компании) отображается для всех пользователей и будет сопровождать любой опубликованный вами контент пока вы специально не укажите скрыть название вашей компании. Вы можете обновить ваш IBM аккаунт в любое время.

Вся введенная информация защищена.

Выберите имя, которое будет отображаться на экране



При первом входе в developerWorks для Вас будет создан профиль и Вам нужно будет выбрать Отображаемое имя. Оно будет выводиться рядом с контентом, опубликованным Вами в developerWorks.

Отображаемое имя должно иметь длину от 3 символов до 31 символа. Ваше Имя в системе должно быть уникальным. В качестве имени по соображениям приватности нельзя использовать контактный e-mail.

Обязательные поля отмечены звездочкой (*).

(Отображаемое имя должно иметь длину от 3 символов до 31 символа.)

Нажимая Отправить, Вы принимаете Условия использования developerWorks.

 


Вся введенная информация защищена.


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=XML, Open source
ArticleID=660051
ArticleTitle=Полный процесс построения приложения интерактивной переписки для iPhone
publish-date=05202011