Статьи

Обслуживание данных для Apple Watch с IBM MobileFirst

Если вы уже знакомы с использованием данных с помощью адаптеров MobileFirst , то догадайтесь , что … это * точно * то же самое, что использование адаптера в собственном проекте iOS. Поскольку логика для приложения WatchKit выполняется в расширении WatchKit, которое на самом деле является исполняемым файлом, работающим на телефоне, между ними нет никакой разницы.

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

В видео ниже я иду по процессу воссоздания приложения Apple Watch Stocks, используя данные, полученные с экземпляра сервера MobileFirst Platform Foundation. Данные моделируются, поэтому не используйте их для каких-либо инвестиций.:)

Основной процесс заключался в следующем: создать пользовательский интерфейс приложений Apple Watch в Xcode / Interface Builder, собрать адаптеры для предоставления данных, а затем начать использовать данные в расширении WatchKit для доставки их в интерфейс приложения наблюдения.

Полный исходный код этого проекта доступен по адресу:  https://github.com/triceam/MobileFirst-WatchKit/tree/master/Stocks.

Интерфейс пользователя

Итак, давайте сначала посмотрим на интерфейс приложения. У меня есть два представления, которые были построены в Интерфейсном Разработчике. Одна — это таблица, в которой отображаются строки данных, другая — подробный экран с множеством меток, используемых для отображения данных.

applewatch-щ

В главном интерфейсе у меня есть метка «загрузка…» (скрытая после загрузки данных) и таблица, которая используется для отображения данных. Для каждой строки в таблице есть 3 метки для отображения определенных полей данных. Они были связаны с ссылками IBOutlet в классе контроллера представления. Все это простые методы разработки WatchKit. Обязательно ознакомьтесь со ссылкой на класс WKInterfaceTable для более подробной информации о работе с таблицами WatchKit.

Xcode-Interface Builder для представления таблицы

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

Xcode-InterfaceBuilder Подробный вид

Обслуживание данных

Загрузка данных в расширение WatchKit идентична отправке запроса на серверный адаптер MobileFirst из собственного приложения iOS . Я использовал свой вспомогательный класс, чтобы использовать блоки кода вместо паттерна делегата, но реализация точно такая же.

Итак, вот как мы можем создать адаптер, используя интерфейс командной строки MobileFirst. Используйте команду «mfp add adapter» и следуйте инструкциям:

$ mfp add adapter
[?] What do you want to name your MobileFirst Adapter? StocksAdapter
[?] What type of adapter would you like?
 Cast Iron
 HTTP
 Java
 JMS
 SAP JCo
 SAP Netweaver Gateway
❯ SQL
 [?] Create procedures for offline JSONStore? No
 A new sql Adapter was added at /Users/andrewtrice/Documents/dev/MobileFirst-Stocks/server/MFStocks/adapters/StocksAdapter

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

Что еще хорошо в платформе MobileFirst, так это то, что вы получаете оперативную аналитику для всех адаптеров из коробки без дополнительной настройки. Вы можете увидеть количество запросов, размеры полезных данных, время отклика, устройства / платформы, используемые для потребления, и многое другое. Кроме того, вы также можете удаленно получать доступ к сообщениям журнала клиента с мобильных устройств. Взгляните на скриншоты ниже только для примера (это из моего примера на моем ноутбуке):

MobileFirst Remote LogsОбзорный обзор адаптеров MobileFirstОтчет об Отчет о запросах адаптера MobileFirstобзорах адаптеров MobileFirst Отчет о запросах адаптера MobileFirst Удаленные журналы MobileFirst

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

Я представил две довольно простые процедуры на сервере MobileFirst: getList — который возвращает урезанный список данных, и getDetail — который возвращает полные данные для биржевого символа:

function getList() {

  simulateData();

  var items = [];
  var trimmedProperties = ["symbol","price","change"];

  for (var i=0; i<data.length; i++) {
    var item = {};
    for (var j in trimmedProperties) {
      var prop = trimmedProperties[j];
      item[prop] = data[i][prop];
    }
    items.push(item);
  }

  return {
    "stocks":items
  };
}

function getDetail(symbol) {

  for (var i=0; i<data.length; i++) {
    if (data[i].symbol == symbol) {
      return data[i];
    }
  }
  return null;
}

Как только они развернуты на сервере с помощью команды CLI « mfp bd », вы можете вызывать процедуры адаптера из клиентского приложения, независимо от того, является ли это родной iOS, нативным Android или гибридным приложением.

Использование данных

Хорошо, теперь мы вернулись к родному проекту iOS. В Objective-C или Swift вы можете вызывать адаптер напрямую, используя  механизмы WLResourceRequest или invokeProcedure . В моем примере я использовал вспомогательный класс, чтобы обернуть invokeProcedure для поддержки блоков кода , чтобы я мог определять обработчики ответа / сбоя непосредственно в своем коде. Итак, в моем коде я вызываю адаптеры так:

-(void) getList:(void (^)(NSArray*))callback{

  WLProcedureInvocationData *invocationData =
    [[WLProcedureInvocationData alloc]
      initWithAdapterName:@"StockAdapter"
          procedureName:@"getList"];

  [WLClientHelper invokeProcedure:invocationData successCallback:^(WLResponse *successResponse) {

    NSArray *responseData = [[successResponse responseJSON] objectForKey:@"stocks"];
    //do something with the response data

  } errorCallback:^(WLFailResponse *errorResponse) {

    //you should do better error handling than this
  }];
}

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

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

[self.dataTable setNumberOfRows:[self.stocks count] withRowType:@"stockTableRow"];

for (NSInteger i = 0; i < self.dataTable.numberOfRows; i++) {

  StockTableRow* row = [self.dataTable rowControllerAtIndex:i];
  NSDictionary* item = [self.stocks objectAtIndex:i];

  [row.stockLabel setText:[item valueForKey:@"symbol"]];

  NSNumber *price = [item valueForKey:@"price"];
  NSNumber *change = [item valueForKey:@"change"];
  [row.priceLabel setText:[NSString stringWithFormat:@"%-.2f", [price floatValue]]];
  [row.changeLabel setText:[NSString stringWithFormat:@"%-.2f", [change floatValue]]];

  if ([change floatValue] > 0.0) {
    [row.changeLabel setTextColor: [UIColor greenColor]];
    [row.containerGroup setBackgroundColor:[UIColor colorWithRed:0 green:0.2 blue:0 alpha:1]];
  } else if ([change floatValue] < 0.0) {
    [row.changeLabel setTextColor: [UIColor redColor]];
    [row.containerGroup setBackgroundColor:[UIColor colorWithRed:0.2 green:0 blue:0 alpha:1]];
  }
  else {
    [row.changeLabel setTextColor: [UIColor whiteColor]];
    [row.containerGroup setBackgroundColor:[UIColor colorWithRed:0.15 green:0.15 blue:0.15 alpha:1]];
  }
}

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

[self.nameLabel setText:[stockData objectForKey:@"name"]];

NSNumber *change = [stockData objectForKey:@"change"];
NSNumber *price = [stockData objectForKey:@"price"];
NSNumber *high = [stockData objectForKey:@"high"];
NSNumber *low = [stockData objectForKey:@"low"];
NSNumber *high52 = [stockData objectForKey:@"high52"];
NSNumber *low52 = [stockData objectForKey:@"low52"];
NSNumber *open = [stockData objectForKey:@"open"];
NSNumber *eps = [stockData objectForKey:@"eps"];

float percentChange = [change floatValue]/[price floatValue];

[self.priceLabel setText:[NSString stringWithFormat:@"%-.2f", [price floatValue]]];
[self.changeLabel setText:[NSString stringWithFormat:@"%.02f (%.02f%%)", [change floatValue], percentChange]];

if ([change floatValue] > 0.0) {
[self.changeLabel setTextColor: [UIColor greenColor]];
} else if ([change floatValue] < 0.0) {
[self.changeLabel setTextColor: [UIColor redColor]];
}
else {
[self.changeLabel setTextColor: [UIColor whiteColor]];
}

//update change with percentage

[self.highLabel setText:[NSString stringWithFormat:@"%-.2f", [high floatValue]]];
[self.lowLabel setText:[NSString stringWithFormat:@"%-.2f", [low floatValue]]];
[self.high52Label setText:[NSString stringWithFormat:@"%-.2f", [high52 floatValue]]];
[self.low52Label setText:[NSString stringWithFormat:@"%-.2f", [low52 floatValue]]];

[self.openLabel setText:[NSString stringWithFormat:@"%-.2f", [open floatValue]]];
[self.epsLabel setText:[NSString stringWithFormat:@"%-.2f", [eps floatValue]]];
[self.volLabel setText:[stockData objectForKey:@"shares"]];

Что дальше?

Готовы начать? Просто скачайте бесплатную версию MobileFirst Platform Server Developer Edition и приступайте к работе.

Полный исходный код этого проекта доступен в моей учетной записи на github:  https://github.com/triceam/MobileFirst-WatchKit/tree/master/Stocks.