Pull to refresh

Введение в 3D Touch

Reading time 9 min
Views 26K
Original author: Maxime Defauw
С выходом iPhone 6s и iPhone 6s Plus компания Apple представила нам совершенно новый способ взаимодействия с нашими телефонами: жест сильного нажатия. Как вы знаете, эта функция уже доступна на Apple Watch и MacBook и в MacBook Pro под названием Force Touch. Это — буквально — добавило новое понятие к пользовательскому интерфейсу.

Если вы задаетесь вопросом, почему Force Touch было переименовано на 3D Touch для iPhone, тогда вы не одни такой. Вскоре после того, как Крейг Федериги (Craig Federighi), который также был явно озадачен названием, представил эту новую возможность, возникло много догадок. Чем не устроило название Force Touch? Слишком много шуток из Звездных войн?

Но есть разница! Очевидно, что Force Touch может распознать только сильное нажатие, тогда как функция 3D Touch более чувствительная и может выделить несколько уровней нажатий на основе того, как сильно вы нажимаете.

Введение в 3D Touch

Хотя изменения могут показаться незначительными, именно они позволяют разработчикам сделать измерения на iPhone более точными. Возьмите это приложение Gravity, например, которое превращает ваш iPhone в цифровые весы с помощью Force Touch. Хотя оно и было отклонено компанией Apple по неясным причинам, идея замечательная. Таким образом, чтобы показать вам, как работает 3D Touch, давайте попробуем сделать похожее приложение!

Давайте начнем


Для начала скачайте этот шаблон проекта, который я создал. По сути, это просто пустое приложение создание на основе шаблона Single View iPhone application. Я создал проект разместил (UILabels & UIImage) и подключил IBOutlets в ViewController.swift.

image

Дизайн нашего приложения довольно прост: у нас есть один контроллер с 2 метками: одна это заголовок и вторая метка, которая показывает процент силы нажатия на экран iPhone.

Давайте начнем разработку! На iPhone 6s и 6s Plus у объектов UITouch есть два новых свойства типа CGFloat, под названием force и maximumPossibleForce. Force представляет, то насколько сильным является касание, где 1.0 означает среднее касание. MaximumPossibleForce показывает максимальную силу для касания.

Всякий раз, когда пользователь нажимает на сенсор, вызывается метод touchesBegan, а затем touchesMoved, если пользователь водит своим пальцем по экрану, то тогда вызывается touchedCancelled или TouchesEnded в зависимости от ситуации. Для наших целей метод touchesMoved является единственным способом, который нам нужен. TouchesMoved имеет два параметра: touches (касания) и event (событие). Касания — набор (неупорядоченный набор различных объектов) объектов UITouch. Для касания должен быть точно один объект UITouch, но мы можем быть не достаточно осторожными, поэтому настоятельно рекомендуется проверить, равен ли touches.first (первый объект UITouch сенсорного набора) nil при помощи дополнительной привязки. Вставьте следующий метод в ViewController.swift:
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
    if let touch = touches.first {
        if #available(iOS 9.0, *) {
            if traitCollection.forceTouchCapability == UIForceTouchCapability.Available {
                // 3D Touch capable
            }
        }
    }
}

В помощью оператора if мы проверяем, поддерживает ли устройство 3D Touch. Эта часть необязательна, если вы делаете этот проект для удовольствия. Однако если вы собираетесь опубликовать приложение в App Store, это является обязательным требованием, выполнение проверки, так как более старые устройства такие как iPhone 6 не поддерживают 3D Touch.

Обратите внимание на то, что я также проверял, запускается ли устройство на iOS 9.0 или более поздних версиях. Я делаю это с помощью нового синтаксиса #available, представленного в Swift 2.0. Если Вы хотите узнать больше о новых функциях и возможностях в Swift 2.0, я рекомендую вам прочитать эту статью. Снова эта проверка необязательна, если ваша целевая платформа для приложения 9.0 или выше.

Чтобы получить силу нажатия в процентах, просто разделите силу касания на максимальную силу (т.е. touch.maximumPossibleForce), которая является максимально возможной силой нажатия. Тогда обновите текст метки. Вы можете обновить метод следующим образом:
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
    if let touch = touches.first {
        if #available(iOS 9.0, *) {
            if traitCollection.forceTouchCapability == UIForceTouchCapability.Available {
                // 3D Touch capable
                let force = touch.force/touch.maximumPossibleForce
                forceLabel.text = "\(force)% force"
            }
        }
    }
}

Если запустите приложение на iPhone 6s/6s Plus, оно должно показать силу нажатия в процентах при нажатии на экран. Однако так как мы делаем шкалу, возможно вы захотите добавить количество граммов, которые вы взвешиваете на своем iPhone. Согласно Райану Маклиду, датчик взвесит максимальный веса ~385g. Таким образом maximumPossibleForce соответствует 385 граммам (приблизительно 3.8 Ньютона). Путем нехитрых вычислений, вы можете конвертировать % силы в граммы. Все, что нам нужно сделать, это умножить процент силы нажатия на 385. Для объектов весом 385 граммов или больше, мы просто изменяем метку на “385+ grams”.

Теперь обновите метод, используя следующий фрагмент кода:
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {        
    if let touch = touches.first {
        if #available(iOS 9.0, *) {
            if traitCollection.forceTouchCapability == UIForceTouchCapability.Available {
                if touch.force >= touch.maximumPossibleForce {
                    forceLabel.text = "385+ grams"
                } else {
                    let force = touch.force/touch.maximumPossibleForce
                    let grams = force * 385
                    let roundGrams = Int(grams)
                    forceLabel.text = "\(roundGrams) grams"
                }
            }
        }
    }
}

Круто! Вы сделали свое Digital Scale приложения.

image

На данный момент приложение не сбрасывает вес до нуля после того, как вы убираете предмет или прекращаете касаться вашего экрана. Вы можете реализовать touchesEnded метод, чтобы сбросить метку.
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
    forceLabel.text = "0 gram"
}


Быстрые действия на главном экране


Еще одно отличное использование 3D Touch — это быстрые действия на главном экране. Quick Actions дают пользователям меню для перехода к каталогу вашего приложения напрямую. Просто сильно нажмите на значок программы, и вы увидите меню. С появлением технологий 3D Touch, такие приложения как Twitter и Instagram и некоторые других приложения, показали как используют эту новую функцию.

image

Давайте добавим Quick Actions для нашего приложение которое мы только что сделали, с помощью которого мы будет открывает приложение с синим фоном вместо белого. Чтобы добавить Quick Actions, откройте файл info.plist Вашего проекта (Щелкните по рабочей области Scale в навигаторе проекта, выберите Scale target и перейдите на вкладку Info). В файле добавьте ‘UIApplicationShortcutItems’ тип выберите массив (Array). Каждый элемент массива представляет собой словарь, содержащий свойства одного быстрого действия:
  • UIApplicationShortcutItemType (обязательно): строка, которая идентифицирует быстрое действие. Обратите внимание, что эта строка должна быть уникальной, определенно для приложения. Хорошая идея состоит в том, чтобы добавить префикс с помощью Вашего идентификатора или некоторых других хитростями для того что бы сделать уникальную строку.
  • UIApplicationShortcutItemTitle (обязательно): строка, представляет заголовок для Quick Action который показывается пользователю. Примером может быть “Show last picture taken”.
  • UIApplicationShortcutItemSubtitle (необязательно): строка для названия вашего Quick Action. Примером может быть“Last picture taken yesterday”. Если вы хотите добавить иконку для Quick Action, у вас есть два варианта: системная иконка от Apple или пользовательская иконка.
  • UIApplicationShortcutItemIconType (необязательно): строка, указывающая, какая системная иконка будет отображаться рядом с Quick Action.
  • UIApplicationShortcutItemIconFile (необязательно): строка, указывающая, какая пользовательская иконка будет отображаться рядом с Quick Action.
  • UIApplicationShortcutItemUserInfo (необязательно): словарь, содержащий некоторую дополнительную информацию, которую вы хотите выполнить с помощью Quick Action.

В массиве мы определяем четыре элементов для настройки Quick Action «OpenBlue». Теперь info.plist должен выглядеть следующим образом:

image

Обратите внимание, что я использовал ‘$(PRODUCT_BUNDLE_IDENTIFIER)’ вместо ‘com.appcoda.Scale’ или любой другой идентификатор, который вы используете. Это в целях безопасности: если, по какой-либо причине, я изменю Bundle ID в ‘General’, то будет затронут весь проект и идентификатор будет изменен везде. В противном случае, мне придется менять его везде вручную. В вашем файле info.plist, вы можете увидеть, что ключ Bundle Identifier использует тот же подход: '$(PRODUCT_BUNDLE_IDENTIFIER)' описывает путь к идентификатору вашего проекта.

Последнее, что осталось сделать, это реализовать Quick action, когда пользователь запускает его. Главная работа обрабатываются в AppDelegate.swift в методе performActionForShortcutItem. Когда Quick Action активируется, вызовется метод. Поэтому вы должны реализовывать этот метод для обработки быстрых действий:
func application(application: UIApplication, performActionForShortcutItem shortcutItem: UIApplicationShortcutItem, completionHandler: (Bool) -> Void) {
    
    // Handle quick actions
    completionHandler(handleQuickAction(shortcutItem))
}

Как ожидается, вызовите обработчик и передадите в него нулевое значение, в зависимости от успеха/отказа быстрого действия. Здесь мы создаем отдельную функцию handleQuickAction, чтобы обработать действие. Отличным способом для представления нескольких случаев Quick Action является использование перечислений с помощью ‘UIApplicationShortcutItemType’ в качестве необработанного значения. Объявите перечисление и реализуйте метод handleQuickAction, как показано ниже, чтобы задать цвет фона синим, когда приложение будет запущено посредством быстрого действия:
enum Shortcut: String {
    case openBlue = "OpenBlue"
}
 
func handleQuickAction(shortcutItem: UIApplicationShortcutItem) -> Bool {
    
    var quickActionHandled = false
    let type = shortcutItem.type.componentsSeparatedByString(".").last!
    if let shortcutType = Shortcut.init(rawValue: type) {
        switch shortcutType {
        case .openBlue:
            self.window?.backgroundColor = UIColor(red: 151.0/255.0, green: 187.0/255.0, blue: 255.0/255.0, alpha: 1.0)
            quickActionHandled = true
        }
    }
    
    return quickActionHandled
}

Это довольно просто. Если вы теперь запустите приложение и запустите его через быстрые действия, фон станет синим.

image

О чем же нужно не забыть?


Есть один моментом, который следует учитывать. С точки зрения последовательности запуска есть различие между приложением, которое запускается, и приложением, которое возобновляется с помощью Quick Action. Так как Вы знаете, когда приложение запускается, вызываются методы willFinishLaunchingWithOptions затем метод anddidFinishLaunchingWithOptions. Но когда приложение возобновляется путем Quick Actions, то он лишь провоцирует выполнение метода performActionForShortcutItem.

image

Если Вы посмотрите на метод didFinishLaunchingWithOptions, то вы увидите, что у нас есть строка кода, чтобы установить цвет фона белым. Он используется, когда приложение запускается обычно, через иконку приложения.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions:
    [NSObject: AnyObject]?) -> Bool {
    // Override point for customization after application launch.
    self.window?.backgroundColor = UIColor.whiteColor()
        
    return true
}

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

Чтобы решить эту проблему, мы должны осуществить проверку в методе didFinishLaunchingWithOptions:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions:
    [NSObject: AnyObject]?) -> Bool {
    print("didFinishLaunchingWithOptions called")
    var isLaunchedFromQuickAction = false
   
    // Check if it's launched from Quick Action
    if let shortcutItem = launchOptions?[UIApplicationLaunchOptionsShortcutItemKey] as? UIApplicationShortcutItem {
        
        isLaunchedFromQuickAction = true
        // Handle the sortcutItem
        handleQuickAction(shortcutItem)
    } else {
        self.window?.backgroundColor = UIColor.whiteColor()
    }
    
    // Return false if the app was launched from a shortcut, so performAction... will not be called.
    return !isLaunchedFromQuickAction
}

Чтобы определить, запущено ли приложение посредством Quick Action, Вы можете проверить функциональную клавишу запуска UIApplicationLaunchOptionsShortcutItemKey. Объект UIApplicationShortcutItem доступен как значение функциональной клавиши запуска. Если приложение запущено путем Quick Action, мы просто вызываем handleQuickAction, чтобы изменить фон на синий.

Поскольку мы уже обработали быстрое действие в didFinishLaunchingWithOptions, мы не хотим вызывать performActionForShortcutItem, чтобы выполнить handleQuickAction снова. Потому мы возвращаем значение false, сообщая системе не вызывать метод performActionForShortcutItem.

Вот и все! Вы можете теперь протестировать приложение. Quick Action должно работать отлично.

Итог


3D Touch — отличный способ добавления удобных и приятных функций к Вашему приложению. Однако Вы должны знать, что не все устройства поддерживают 3D Touch, хотя это может измениться в будущем.

После прочтения этой статьи вы сможете добавлять Quick Actions к вашему iOS приложению и определять силу касания.

Для сравнения вы можете загрузить полный проект Xcode. Не забудьте поделиться мыслями в комментариях об этом руководстве и 3D Touch.
Tags:
Hubs:
+8
Comments 7
Comments Comments 7

Articles