10.08.2017
3328
Эта заметка писалась по итогам Всемирной конференции разработчиков WWDC. В ней представлена выжимка значимых обновлений для iOS, с примерами кодов. Мы вынесли за скобки другие новинки и заметные изменения: смарт-динамик HomePod, обновление процессоров, клавиатуры, и прочее. Обо всем этом и так достаточно публикаций в отраслевой прессе.
Одно из главных обновлений для облегчающих создание приложений для iOS — drag and drop . Теперь в iOS присутствует встроенная поддержка этой функции: мультивыбор, анимация по умолчанию и стандартные взаимодействия. На iPad «перетаскивание» работает между разными приложениями. Кому-то это покажется излишним, но ведь и возможность копипаста появилась только с выходом iPhone OS 3.
Еще одно новшество — файловая система. Теперь документы можно просматривать в отдельном приложении Files app.
Реализована новая система взаимодействий drag-and-drop: в любой вид добавляется UIDragInteraction, затем реализуются соответствующие делегаты. В месте переноса также должны быть реализованы делегаты для приема данных.
На iPad элементы можно переносить из одного приложения в другое, но drag and drop на iPhone работает только для файлов какого-то одного приложения.
Интересный нюанс: если вид уже «знает», как принимать скопированные данные, элементы такого же типа будут приниматься автоматически.
UITextView автоматически принимает текст, и не нужно добавлять в приложение что-либо еще.
Брюс Найло, один из технических директоров по UIKit наглядно продемонстрировал, как это работает:
Вы также можете скачать demo app .
В фотоальбоме drag and drop используется чтобы:
В том же приложении (которое вы можете скачать):
class PhotoCollectionViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout, UICollectionViewDragDelegate, UICollectionViewDropDelegate {
Дальше нужно определить делегаты drag and drop для self в viewDidLoad.
collectionView?.dragDelegate = self
collectionView?.dropDelegate = self
Единственный требующийся метод протокола делегатов для drop создает массив UIDragItem, когда начнется перетаскивание. Элемент, который перетаскивается, содержит данные.
func collectionView(_ collectionView: UICollectionView, itemsForBeginning
session: UIDragSession, at indexPath: IndexPath) -> [UIDragItem] {
let dragItem = self.dragItem(forPhotoAt: indexPath)
return [dragItem]
}
Что касается drop, вам нужно уточнить, возможно ли принимать данные:
func collectionView(_ collectionView: UICollectionView, canHandle session: UIDropSession) -> Bool {
guard album != nil else { return false }
return session.hasItemsConforming(
toTypeIdentifiers: UIImage.readableTypeIdentifiersForItemProvider)
}
В данном случае return true, если переносимый элемент можно превратить в изображение. При drop нужно скопировать и переместить фотографии в коллекцию элементов (collection view).
func collectionView(_ collectionView: UICollectionView, performDropWith coordinator: UICollectionViewDropCoordinator) {
guard album != nil else { return }
let destinationIndexPath = coordinator.destinationIndexPath ?? IndexPath(item: 0, section: 0)
switch coordinator.proposal.operation {
case .copy:
// Receiving items from another app.
loadAndInsertItems(at: destinationIndexPath, with: coordinator)
case .move:
move(items: coordinator.items, with: coordinator)
default: return
}
}
Если ваше iOS-приложение доступно и в качестве веб-приложения, у вас в распоряжении будут учетные данные пользователей, по которым они логинятся в приложение автоматически.
Для поддержки функций, которые были до iOS 11 (например, универсальные ссылки), у вас, вероятно, уже есть файл apple-app-site-association, чтобы связать веб-сайт и приложение (если нет, необходимо это сделать). Все, что нужно как дополнение, это установить тип контента имени пользователя и пароля UITextFields как .username и .password, соответственно.
self.userNameField.textContentType = .username
self.passwordField.textContentType = .password
Затем при появлении экрана для ввода данных iOS предложит вписать сохраненные данные пользователя.
Более подробно об этом в Introducing Password AutoFill for Apps .
Новое приложение Files дает возможность просмотра файлов. Но если для разработки приложений для iOS , нужны файлы из других приложений, можно выбрать вид для выбора документов (document-picker view), аналогично тому, как использовался нужный вид для выбора изображений.
let docs =
UIDocumentBrowserViewController(forOpeningFilesWithContentTypes: [kUTTypePDF])
docs.delegate = self // implement UIDocumentBrowserViewControllerDelegate
self.present(docs, animated: true)
Чтобы обработать выбранный документ, используйте метод протокола UIDocumentBrowserViewControllerDelegate
Этот аспект подробно освещался во время сессии File Provider Enhancements.
Swift 4 — язык программирования с открытым исходным кодом. Детали можно просмотреть в GitHub. На конференции WWDC Apple представила новую особенность — протокол Codable, который позволяет кодировать структуру посредством классов NSCoding.
Все, что нужно сделать, согласиться с протоколом Codable, и Swift реализует это по умолчанию:
struct WWDCVideo : Codable {
let title: String
let presenters: [String]
let videoURL: URL
}
Добавится автоматическая поддержка JSON.
Кодированная структура выглядит примерно так:
let swiftVideo = WWDCVideo(
title: «What’s New in Swift»,
presenters: [
«Doug Gregor»,
«Bob Wilson»,
«Ben Cohen»,
«John McCall»,
],
videoURL: URL(string: «https://developer.apple.com/videos/play/wwdc2017/402/»)!
)
let jsonData = try JSONEncoder().encode(swiftVideo)
Раскодирование:
let vid = try JSONDecoder().decode(WWDCVideo.self, from: jsonData)
Также Codable поддерживает специальное кодирование и раскодирование, если это требуется, есть простой способ сделать простые альтерации (CodingKeys).
Больше об этом по ссылке What’s New in Swift .
Одна из презентаций WWDC была посвящена вопросу о том, как Apple использует машинное обучение (ML) в системах и приложениях.
Siri watchface стал первым примером, но представители Apple анонсировали множество функций, в основе которых ML, в том числе и CoreML, новый фреймворк, который реализует фазу прогона ML-моделей, таких как нейронные сети.
На самом высоком уровне машинное обучение используется для реализации функций, которые отображают входные данные в выходной информации. Маппинг задается не напрямую, система этому «обучается» по образцам данных. В iOS машинное обучение используется для идентификации по чертам лица, OCR, распознавания рукописного текста, автоматического ввода текста, Siri и много другого.
CoreML задает спецификации файла специальной модели машинного обучения. Этот файл создается заранее с помощью обучающего ПО, чтобы задать множество примеров входной информации и получить ожидаемый результат на выходе. По прошествии времени софт может предсказывать выходные данные для новых входных значений. Можно сделать экспорт такого «понимания», чтобы моделировать файлы уже в других программах.
Файл модели помещается в проект Xcode, создается класс Swift, чтобы представить простую функцию, которая используется для управления моделью по входным значениям.
Примером входных значений служит фотография, а результат на выходе — прямоугольное пространство на фото.
Примерно так:
let kittenFinder = KittenFinder()
let r: CGRect = kittenFinder.findKitten(image: imageView.image)
Точный интерфейс генерируется из файла модели.
К примеру, моделям, в основе которых изображения, обычно необходим специфический размер и пиксельный формат (цвет или шкала уровней серого). CoreML автоматически превращает любое изображение, которое вы отправите, в то, что нужно для модели (поддерживаются все способы репрезентации изображений в iOS).
Модель проста в использовании. Разработчики могут создавать такие модели (это как упражнение для разработчика), существует и множество открытых моделей, у Apple также имеется ряд готовых моделей для приложений. Есть открытая библиотека Python , которая помогает конвертировать форматы. Судя по всему, ML-сообщество в ближайшее время разработает еще больше моделей в таком формате.
Больше информации по ссылке: Introducing Core ML .
Но Apple этого было мало. В довершение всего разработчики компании написали еще два фреймворка, которые упрощают некоторые простые задачи. Фреймворк Vision предназначен для распознавания объектов в потоковом видео, автоматически считывает изображения с помощью объекта AVCaptureSession. Разрабатываются другие модели, например более точный детектор лиц, который фиксирует детали лица (глаза, нос, рот).
Пока еще нет примера приложения или документации для распознавания лиц, но все-таки из представленного на конференции во время сессии Vision удалось кое-что собрать: GitHub .
В типичном приложении с объектом AVCaptureSession добавьте импорт Vision в свой View Controller.
import Vision
Добавьте свойство, чтобы создать запрос на распознавание лиц.
var requests: [VNDetectFaceRectanglesRequest] = []
Инициализируйте в этой функции, которая вызывается в viewDidLoad:
func setupVision() {
let faceDetectionRequest = VNDetectFaceRectanglesRequest(completionHandler: self.handleFaces)
self.requests = [faceDetectionRequest];
}
В реализации captureOutput добавьте код:
guard let imageBuffer = CMSampleBufferGetImageBuffer(sampleBuffer) else { return }
// Make the Face Detection Request
var requestOptions: [VNImageOption: Any] = [:]
if let cameraIntrinsicData = CMGetAttachment(sampleBuffer, kCMSampleBufferAttachmentKey_CameraIntrinsicMatrix, nil) {
requestOptions = [.cameraIntrinsics: cameraIntrinsicData]
}
// The orientation should be determined from the phone position, but assume portrait (1) for now
let imageRequestHandler =
VNImageRequestHandler(cvPixelBuffer:imageBuffer, orientation: 1, options: requestOptions)
do {
try imageRequestHandler.perform(self.requests)
} catch {
// handle this
}
После идентификации лица будет вызвана функция:
func handleFaces(request: VNRequest, error: Error?) {
DispatchQueue.main.async {
self.hideFaceBox()
guard let result = (request.results as? [VNFaceObservation])?.first else { return }
let bb = result.boundingBox
if let imgFrame = self.imageView?.frame {
// Bounding Box is a 0..<1.0 normlized to the size of the input image and
// the origin is at the bottom left of the image (so Y needs to be flipped)
let faceSize = CGSize(width: bb.width * imgFrame.width, height: bb.height * imgFrame.height)
self.drawFaceBox(frame:
CGRect(x: imgFrame.origin.x + bb.origin.x * imgFrame.width,
y: imgFrame.origin.y + imgFrame.height — (bb.origin.y * imgFrame.height) — faceSize.height,
width: faceSize.width,
height: faceSize.height)
)
}
}
}
У запроса есть массив результатов. С помощью его первого элемента мы сделали полупрозрачную рамку, чтобы показать распознанное изображение.
Приложение доступно на GitHub .
Этот девайс направлен на экран компьютера и фиксирует лицо Тима Кука:
Боле подробно об этом по ссылке Vision Framework: Building on CoreML и в документации Vision .
Также есть библиотека обработки естественного языка, которая не очень эффективна, но может распознавать естественные языки и адресные части речи в текстовом вводе. Эту библиотеку можно использовать, к примеру, для предикативной системы ввода на клавиатуре.
Подробно в презентации Natural Language Processing and Your Apps .
Еще одной новостью во время WWDC стал ARKit, новый фреймворк, который открывает для приложений возможности технологии дополненной реальности. Если вам приходилось создавать какой-то контент, используя SceneKit (для 3D-игр) или SpriteKit (для 2D), тогда вы оцените преимущества ARKit.
В Xcode сейчас присутствует шаблон приложения для дополненной реальности:
После выбора этого шаблона на следующем экране вам понадобится выбрать контентную технологию (SceneKit, SpriteKit or Metal). Выберите SceneKit, и приложение будет готово к запуску.
Код, который установлен по умолчанию, позволяет видеть космический корабль. Добавлять 3D-модели очень просто.
Сделайте импорт одной из них и обновите эту линию:
let scene = SCNScene(named: «art.scnassets/ship.scn»)!
sceneView.scene = scene
Вы можете добавить 3D-геометрию с помощью различных узлов SceneKit.
Например, замените две верхние линии этим:
self.sceneView.autoenablesDefaultLighting = true
let scene = SCNScene()
let sphereNodes = SCNNode()
scene.rootNode.addChildNode(sphereNodes)
addSphere(to: sphereNodes, pos: SCNVector3Make(0, 0, -2.0))
addSphere(to: sphereNodes, pos: SCNVector3Make(-0.3, 0.2, -2.4))
addSphere(to: sphereNodes, pos: SCNVector3Make(0.3, 0.2, -2.8))
AR-шаблон отключает стандартное освещение, но нужно, чтобы сферы зажигались таким же светом, как и освещение видеоряда, которое ARKit фиксирует. Все координаты в пределах одного метра действительного пространства.
Эта функция создает и добавляет сферы на экран:
func addSphere(to node: SCNNode, pos: SCNVector3) {
let sphere = SCNSphere(radius: 0.1)
let sphereNode = SCNNode(geometry: sphere)
sphereNode.position = pos
node.addChildNode(sphereNode)
}
Во время запуска сферы будут выглядеть примерно так:
Больше подробностей по ссылке Introducing ARKit: Augmented Reality for iOS и в документации по ARKit .
Итог
Xcode 9 существенно изменился по сравнению с Xcode 8.2 : полностью обновленный редактор, поддержка рефакторинга в Swift. Можно запускать множество эмуляторов, доступна столь необходимая функция отладки по Wi-Fi, поддержка языков с письмом справа налево и динамический тип размеров.
У Swift Playgrounds два обновления. Одно вы можете загрузить сейчас, но также есть бета-версия 2.0 в TestFlight . Новая версия позволяет экспериментировать со всеми функциями iOS 11, такими как ARKit и Swift 4.
В сентябре ожидается релиз всего этого, наряду с очередным iPhone. В общем, просматривайте видеоролики и готовьте свои приложения к iOS 11.
Подпишись на рассылку
29.12.2016
57470
Наш опыт работы на рынке мобильной разработки позволил структурировать типовые проблемы с которыми сталкиваются большинство заказчиков. Мы сталкивались с...
20.08.2020
4454
В чем разница между двумя популярными моделями управления проектами и какую выбрать для своего проекта