Содержание


Перевод iOS-приложения с языка Objective-C на язык Swift

Это легко сделать с помощью службы IBM Mobile Data на облачной платформе Bluemix

Comments

В июне 2014 года Apple анонсировала новый язык программирования Swift. Swift отбрасывает некоторый балласт Objective-C, сохраняя полную совместимость со старым кодом. Многие разработчики iOS интересуются использованием Swift в дополнение (или даже взамен) Objective-C, поэтому мы решили стряхнуть пыль со своего примера приложения Bluelist и показать, как легко перевести его на Swift.

Перевод нашего приложения Bluelist с Objective-C на Swift проходит относительно безболезненно. В большинстве случаев это почти взаимно-однозначное синтаксическое соответствие.

Инструкции этого руководства демонстрируют процесс перевода, уделяя особое внимание тому, как при переходе с Objective-C на Swift изменяется взаимодействие клиентского устройства со службой IBM Mobile Data в Bluemix. Имейте в виду, что язык Swift все еще находится в процессе разработки. Наш пример создавался на уровне Xcode 6 Beta 7, но мы продолжим его обновление, чтобы идти в ногу с языком Swift по мере его развития. Просто убедитесь, что у вас последняя бета-версия Xcode.

Перевести приложение Bluelist с Objective-C на Swift очень легко. В большинстве случаев практически взаимно-однозначное соответствие синтаксиса позволяет сохранить всю функциональность исходного приложения. Многие изменения — такие как способ управления переходами или способ передачи данных между различными компонентами модели MVC— универсальны для любых iOS-приложений. Для наших целей мы хотим сосредоточиться на тех частях приложения, которые непосредственно связаны со службой IBM Mobile Data и SDK Bluemix.

Что нужно для перевода приложения

  • Знакомство с разработкой iOS-приложений.
    Освойте традиционную разработку с помощью Xcode и Objective-C, пользуясь руководством Начните разрабатывать iOS-приложения сегодня из «Библиотеки разработчика Apple iOS». Нужно также ознакомиться с руководствами и документацией Swift на сайте Apple: Добро пожаловать в Swift.
  • Учетная запись в Bluemix для использования службы IBM Mobile Data.
  • Знакомство с проектом bluelist-mobiledata-ios.
    Приложение, которое мы переводим, подробно описано в оригинальном руководстве Создание iOS-приложения с использованием службы IBM Mobile Data для Bluemix, написанном Ником в соавторстве с Кевином Холдуэем и Белиндой Джонсон. Прочтите то руководство, прежде чем приступить к работе с этим.
  • Исходный код bluelist-mobiledata-swift.
    Поскольку это приложение представляет собой клиентский код iOS, для его редактирования или запуска в Xcode нужно загрузить исходный код в локальную среду разработки. Исходный код можно получить, нажав на расположенную ниже кнопку, которая ведет к проекту в DevOps Services. Там вы найдете URL-адрес Git-репозитория, который можно использовать в командной строке или даже во встроенном инструменте Xcode. Если же вы просто хотите видеть исходный код и следовать ему, нажмите кнопку Редактировать код, чтобы просматривать код непосредственно в DevOps Services.
  • Последняя бета-версия Xcode.
    Как уже упоминалось, мы использовали Xcode 6 уровня Beta 7.

 

Популярная облачная служба Bluemix: Mobile Data. Служба Mobile Data (на платформе Cloudant) содержит простые в применении SDK, которые обеспечивают доступ к масштабируемой, полностью управляемой базе данных посредством знакомых объектно-ориентированных API.

Шаг 1. Инициализация SDK

Для начала мы вводим класс Objective-C посредством связующего заголовка. Это короткий файл:

#import <IBMBluemix/IBMBluemix.h> 
#import <IBMData/IBMData.h>

Теперь у нас есть доступ ко всем функциям, представляемым SDK Bluemix и Mobile Data. Тот факт, что эти SDK написаны на Objective-C, – не проблема, так как Swift полностью совместим с командами и структурами Objective-C.

Как и в случае оригинального приложения на Objective-C, первые строки реального кода, которые мы напишем, инициализируют службу Bluemix (в данном случае, Mobile Data) и сам SDK, передав набор параметров конфигурации: идентификатор, секретный ключ и маршрут нашего приложения. Опять же, см. оригинальное руководство, содержащее подробные сведения об этих параметрах и их местонахождении на панели управления Bluemix.

Следующий фрагмент кода загружает эти значения из файла bluelist.plist и использует их для инициализации SDK. Для краткости из этого фрагмента исключена обработка ошибок; полную версию можно найти в исходном коде AppDelegate.swift.

var configPath = NSBundle.mainBundle().pathForResource("bluelist", ofType: "plist") 
if (configPath != nil)  { 
	config = NSDictionary(contentsOfFile: configPath) 
	applicationId = configPath["applicationId"] as String 
	applicationSecret = configPath["applicationSecret"] as String 
	applicationRoute = configPath["applicationRoute"] as String 
} 
 
IBMBluemix.initializeWithApplicationId(applicationId, andApplicationSecret: applicationSecret,  
andApplicationRoute: applicationRoute) 
IBMData.initializeService() 
IBM_Item.registerSpecialization()

Последние три команды выполняют следующие действия:

  • инициализация общего SDK Bluemix с нашей персонализированной конфигурацией;
  • инициализация SDK конкретной службы для Mobile Data;
  • регистрация класса IBM_Item в качестве специализации IBMDataObject.

Примечание к этому последнему пункту: если вы просмотрите пример Objective-C, то заметите, что первоначально вызов registerSpecialization() выполнялся в функции инициализации класса IBM_Item. В версии на языке swift мы делаем его здесь, в AppDelegate, как показано выше. Попытка имитировать Objective-C путем переопределения функции класса +initialize в нашем классе IBM_Item Swift и вызова оттуда registerSpecialization() на самом деле может привести к ошибке. Почему? Swift инициализирует классы не так, как Objective-C. Вызов registerSpecialization() произойдет раньше, чем закончится установка SDK Mobile Data.

Как бы то ни было, мы готовы начать программирование для Bluemix.

Шаг 2. Расширение IBMDataObject

На Objective-C мы написали свой собственный класс IBM_Item и сделали его соответствующим протоколу IBMDataObjectSpecialization SDK Mobile Data. Swift-версия IBM_Item похожа, но в ней есть дополнительный момент – вычисляемые свойства. Эти свойства приводят наш код в порядок, скрывая функции взаимодействия с облаком setObject() и objectForKey() за точечной записью. Вот Swift-реализация класса IBM_Item:

class IBM_Item: IBMDataObject, IBMDataObjectSpecialization { 
	let nameKey = "name" 
	var name: String { 
		get { 
	if let nameStr = super.objectForKey(nameKey) as? String { 
		return nameStr 
	} 
	else { 
		return "" 
	} 
		} 
		set { 
			super.setObject(newValue, forKey: nameKey) 
		} 
	} 

	required override init() { 
		super.init() 
    } 

    override init(`class` classname: String!) { 
    	super.init(`class`:classname) 
    } 

    class func dataClassName() -> String! { 
    	return "Item" 
    } 
}

Несколько слов об инициализаторах: здесь присутствует «обязательная» функция init(), требуемая протоколом IBMDataObjectSpecialization. А обратные апострофы (`) в другом нашем методе, init, нужны потому, что class – это зарезервированное слово в Swift.

Обратите особое внимание на переменную экземпляра name. Благодаря вычисляемым свойствам Swift, нам достаточно получить или задать эту переменную точно так же, как если бы это был примитив. За кулисами, чтобы обновить наш объект в облаке, Swift выполняет соответствующие вызовы к SDK Mobile Data. Вот пример того, как легко создать IBM_Object, а затем получить или задать свойство name в Swift:

var item: IBM_Item? 
self.textField.text = item?.name 
item?.name = self.itemTextField.text

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

Более простая альтернатива

Но что если нам нужно минимизировать объем работы, необходимой для создания нашего списка приложений? Что если мы не хотим возиться с выделением специального класса, способного обрабатывать более сложную логику?

Swift позволяет использовать службу Mobile Data гораздо более компактным способом, чем с помощью класса IBM_Item. Вместо создания специального класса, который должен соответствовать протоколу IBMDataObjectSpecialization, и расширения IBMDataObject, можно просто создать переменные vars и дать им надлежащую аннотацию:

var item: IBMDataObject?

Вот и все! Если нужно установить в UI свойство name для нашего объекта item с помощью текстового поля, то мы делаем это непосредственно:

item.setObject(textField.text, forKey:"name")

Если же нужно, напротив, считать то же самое свойство из объекта и вставить его в текстовое поле:

if (item.objectForKey("name") != nil) 
	textField.text = item.objectForKey("name") as String 
}

Swift позволяет делать эти вызовы, потому что мы аннотировали объект item как соответствующий протоколу IBMDataObject – и нам не нужно создавать специальный класс или регистрировать его в своем AppDelegate.

Опять же, этот подход проще, но обеспечивает меньше возможностей, чем приведенный выше класс IBM_Item. В остальной части этого руководства мы оставим в своих фрагментах кода IBM_Item, чтобы сохранить максимальное сходство с оригинальным приложением на языке Objective-C и продемонстрировать характерные вычисляемые свойства Swift.

Шаг 3. Взаимодействие с IBM Mobile Data в Bluemix

Теперь, когда мы инициализировали свои SDK и рассмотрели два подхода к использованию IBMDataObject на языке Swift, обратимся к фактическому взаимодействию с облаком. Для начала, вот функция listItems() из IBM_ListViewController.swift, которая показывает, как мы загружаем данные из облака. Эта функция выполняется при запуске приложения и при каждом обновлении основного представления:

func listItems(callback: () -> Void) 
{ 
	var query = IBMQuery(forClass: "Item") 
	query.find().continueWithBlock{ task in 
		if(task.error() != nil) { 
			// обработка ошибок 
		} 
		else { 
			self.itemList = [] 
			if let result = task.result() as? NSArray { 
				for i in 0..<result.count { 
					self.itemList.append(result[i] as IBM_Item) 
				} 
                	} 
			self.reloadLocalTableData() 
			callback() 
		} 
		return nil 
	} 
}

В предыдущем фрагменте мы использовали класс IBMQuery из SDK Mobile Data для создания объекта поиска. Этот объект поиска возвращает все документы из нашего облачного хранилища, для которых указан тип класса Item.

Стоит отметить, что для организации асинхронного кода SDK Mobile Data используют структуру Bolts. Bolts нужно предоставить объект запроса с блоком кода, который будет выполняться при возврате функции find().

Для проверки ошибок в запросе достаточно функции error(), которая проверяет, что он не пустой. Если в запросе нет ошибок, то список элементов можно загрузить в представление таблицы, используя цикл for.

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

self.listItems({ 
	self.refreshControl.endRefreshing() 
})

Другие операции CRUD – создание, редактирование, удаление – очень похожи на приведенную выше функцию listItems().

Все, что нужно сделать для нашей Swift-версии createItem(), – это взять объект IBM_Item и вызвать его функцию save(). Как и в случае функции IBMQuery.find(), для сглаживания асинхронной обработки в функции save() используется структура Bolts. По завершении операции вызывается код continueWithBlock, а объект проверки ошибок укажет нам, успешно ли выполнена операция сохранения. Вот эта функция:

func createItem(item: IBMDataObject) 
{ 
	self.itemList.addObject(item) 
	self.reloadLocalTableData() 

	item.save().continueWithBlock{ task in 
		if (task.error() != nil) { 
			// обработка ошибок 
		} 
		return nil 
	} 
}

С точки зрения клиента функция updateItem(), по существу, идентична функции createItem(), поэтому мы пропустим ее. Функция deleteItem() отличается всего одним вызовом, но ее мы все же приведем:

func deleteItem(item : IBMDataObject) 
{ 
	self.itemList.removeObject(item) 
	self.reloadLocalTableData() 

	item.delete().continueWithBlock{ task in 
		if (task.error() != nil) { 
			//обработка ошибок 
		} 
		return nil 
	} 
	self.setEditing(false, animated: true) 
}

Вот и все. Мы инициализировали SDK Bluemix, увидели, как легко создать объект, соответствующий протоколу IBMDataObject, и рассмотрели некоторые Swift-реализации основных операций CRUD.

Заключение

Теперь у вас есть представление о том, как использовать Swift для программирования взаимодействия со службами Bluemix. Хотя общие алгоритмы и формы взаимодействия между клиентом и службой в основном идентичны их реализации на языке Objective-C, новый язык, такой как Swift, ставит свои собственные характерные задачи.

Мы призываем вас бросить более пристальный взгляд на наш пример и вынести все вопросы, которые при этом возникнут, на обсуждение в раздел Bluemix Q&A developerWorks. Не стесняйтесь задавать вопросы, делиться знаниями и участвовать в обсуждениях в кругу нашего растущего сообщества разработчиков Bluemix.

 

СЛУЖБА BLUEMIX, КОТОРУЮ МЫ ИСПОЛЬЗОВАЛИ
  • Mobile Data содержит простые в применении SDK, которые обеспечивают доступ к масштабируемой, полностью управляемой базе данных посредством знакомых объектно-ориентированных API.

Ресурсы для скачивания


Похожие темы


Комментарии

Войдите или зарегистрируйтесь для того чтобы оставлять комментарии или подписаться на них.

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=40
Zone=Мобильные приложения, Облачные вычисления
ArticleID=1020091
ArticleTitle=Перевод iOS-приложения с языка Objective-C на язык Swift
publish-date=11052015