Después de que el iPhone 6s y el iPhone 6s Plus ingresaron al mercado con pantallas compatibles con
la tecnología
3D Touch , una aplicación para pesar ciruelas y duraznos apareció casi de inmediato en la App Store.

No puedo decir con certeza por qué exactamente estas frutas, pero definitivamente puedo decir por qué precisamente las frutas. El hecho es que el sensor de pantalla del iPhone funciona según el principio de detectar fugas de corriente desde la superficie del sensor, y para esta fuga necesita un dedo vivo o algo que tenga capacidad eléctrica. Creo que todo el mundo sabe que las pantallas de los dispositivos i no funcionan en un lápiz óptico de plástico o una uña. Por eso fue imposible pesar algo metálico en esa aplicación. Pero las frutas tienen una capacidad eléctrica, el sensor se activa y el
3D Touch funciona directamente normalmente.
Muy rápidamente, esta aplicación fue eliminada de la App Store. Personalmente, me parece que esto se hizo debido a los usuarios de mente estrecha que intentaron pesar libras en sus dispositivos. Por supuesto, los dispositivos se averiaron y los llevaron a los centros de servicio. Y allí dijeron algo de la serie: "La aplicación se descargó de la tienda oficial, y no advirtieron allí que era imposible ...".
Como resultado, no existen tales aplicaciones en la tienda, pero nadie nos impedirá crearlas para nosotros.
Desafío
Necesitamos escribir una aplicación, que consta de un controlador, en el que habrá una inscripción atractiva, un círculo dibujado en el centro de la pantalla, indicadores de peso en gramos y porcentaje de la fuerza determinada (será más claro más adelante en el texto). Cuando haga clic en la pantalla, aparecerá un círculo en el punto de contacto, que aumentará o disminuirá según la presión. Debe decirse de inmediato que en un simulador no se puede probar una aplicación de este tipo. Por lo tanto, deberá ejecutar la aplicación en un dispositivo real. Al final, debe obtener una aplicación de este tipo:

Creación de proyectos
Abra Xcode, elija crear un nuevo proyecto, plantilla de
aplicación de vista única
Construyendo una interfaz en Xcode
Vaya al
Guión gráfico , arrastre varios
UILabels de la biblioteca de elementos al controlador, colóquelos más cerca de los bordes superior o inferior del controlador. Resultó así:

Por atractivo estético, destacaremos el lugar donde colocaremos los objetos en un círculo rojo. Puedes tomar una foto lista con un círculo, pero este no es nuestro método)). Dibujaremos los círculos utilizando los métodos de
Core Graphics . Será más conveniente crear una clase de herencia desde UIView y ya trabajar con ella.
Agregue un nuevo archivo al proyecto,
asígnele el nombre
ScaleView . Cree una clase
ScaleView en este archivo que herede de
UIView .

import UIKit class ScaleView: UIView { override func draw(_ rect: CGRect) { } }
Luego, vaya al
StoryBoard , transfiéralo al controlador desde la biblioteca de elementos
UIView y colóquelo en el centro de nuestro controlador. Seleccione el
UIView recién agregado y en el
Inspector de identidad configure la clase
ScaleView que creamos anteriormente.

Además, con la ayuda de constantes, puede establecer las reglas para la disposición relativa de los elementos en la pantalla. Se ve así para mí:

Dibujar círculos
Vaya al archivo
ScaleView.swift . En la clase
ScaleView, creamos el método
draw (_ rect :) , que usaremos para dibujar dentro del área de visualización de esta
UIView .
Agregue el siguiente código al método
draw (_ rect :) override func draw(_ rect: CGRect) { let context = UIGraphicsGetCurrentContext()
- Obtenemos el contexto gráfico en el que dibujaremos
- Establecemos el color con el que dibujaremos. En este caso Es rojo
- Establezca el ancho de la línea con la que dibujaremos.
- Establecemos el camino para dibujar en forma de arco, cuyo centro se encuentra en el centro de ScaleView, con un radio igual a la mitad del ancho de ScaleView menos 14 (esto es para ajustar el arco en la Vista visible), y un arco largo: 360 grados alrededor de toda la circunferencia. Tenga en cuenta que mis dígitos de ancho están codificados en el párrafo anterior usando constantes.
- Nos basamos en la ruta dada con los parámetros dados
Puede compilarlo para la verificación, pero también puede establecer una directiva para mostrar los cambios directamente en
Interface Builder .
Toda la magia en la directiva
@IBDesignable . Marque la clase
ScaleView con esta directiva
. import UIKit @IBDesignable class ScaleView: UIView { override func draw(_ rect: CGRect) { let context = UIGraphicsGetCurrentContext() context?.setStrokeColor(UIColor.red.cgColor) context?.setLineWidth(14.0) context?.addArc(center: CGPoint(x: 375 / 2, y: 375 / 2), radius: 375 / 2 - 14, startAngle: 0, endAngle: 2 * CGFloat(M_PI), clockwise: true) context?.strokePath() } }
Después de eso, vaya al
StoryBoard , espere un poco y verá un círculo rojo pintado en el centro del
ViewController
Practiquemos y dibujemos otro círculo más pequeño y delgado. Para hacer esto, agregue el siguiente código al método
draw (_ rect :) en el archivo
ScaleView :
context?.setLineWidth(1.0) context?.setStrokeColor(UIColor.lightGray.cgColor) context?.addArc(center: CGPoint(x: 375 / 2, y: 375 / 2), radius: 375 / 4 - 14, startAngle: 0, endAngle: 2 * CGFloat(M_PI), clockwise: true) context?.strokePath()
Creo que está claro, así que agregamos. De hecho, agregamos un círculo más, gris, radios un cuarto del ancho de
ScaleView y un ancho de un punto.
Resultados en
StoryBoard :

La parte final de nuestro trabajo preparatorio será la creación de salidas para
ScaleView y dos
UILabels , que mostrarán la fuerza de presionar la pantalla en porcentaje y el peso en gramos.
Ctrl- arrastrar elementos desde el
ViewController creará las salidas necesarias.
@IBOutlet weak var scaleView: ScaleView! @IBOutlet weak var forceLabel: UILabel! @IBOutlet weak var grammLabel: UILabel!
Directamente - escalas
Entonces, nos acercamos al momento de medir la fuerza de presionar la pantalla. Vaya a
ViewController y en el método
viewDidLoad () agregue valores de inicio para todos los
UILabel override func viewDidLoad() { super.viewDidLoad() forceLabel.text = "0% force" grammLabel.text = "0 " }
Al igual que todos los procesos asociados con los
toques de pantalla, en el controlador pueden capturarse con el
método touchesMoved (_: :) . Este método funciona cuando la pantalla toca a tiempo. Es decir Si el dedo está en la pantalla o se mueve sobre él, este método funciona y puede realizar un seguimiento de todos los toques y sus propiedades.
Agréguelo al
ViewController y escriba el siguiente código:
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) { if let touch = touches.first { // 1 if #available(iOS 9.0, *) { // 2 if traitCollection.forceTouchCapability == UIForceTouchCapability.available { // 3 if touch.force >= touch.maximumPossibleForce { // 4 forceLabel.text = "100%+ force" grammLabel.text = "385 " } else { let force = (touch.force / touch.maximumPossibleForce) * 100 // 5 let grams = force * 385 / 100 // 6 let roundGrams = Int(grams) // 7 forceLabel.text = "\(Int(force))% force" // 8 grammLabel.text = "\(roundGrams) " } } } } }
Toda la mecánica de la aplicación
Libra iOS es este método. Todo lo demás que haremos más adelante en esta lección son mejoras. Ya hemos hecho todo el trabajo básico. Vamos a desarmarlo
- De todo el conjunto de toques de la pantalla, elegimos el primero
- Esta directiva verifica el sistema operativo instalado en el dispositivo y omite aún más si la versión del sistema operativo es 9.0 o más. Trabajar con 3D Touch solo fue posible con la novena versión de iOS. Intentar manejarlo en el dolor de las versiones anteriores no tiene sentido
- Y en esta línea, se está probando que el dispositivo admite la pantalla con la función 3D Touch . Después de todo, la versión 10 de iOS también puede estar en el iPhone 6, pero a partir de esto, la pantalla de este teléfono inteligente no comenzará a distinguir la fuerza de presión. Esta inspección debe realizarse bajo estrictos requisitos de Apple.
- Un toque tiene una propiedad de fuerza en la cual la fuerza se transmite cada vez que funciona el método touchesMoved (_: :) . Y en esta línea comparamos el valor de la fuerza de presión actual y el valor máximo posible de la fuerza de presión. Y si la fuerza de presión es mayor que el máximo, entonces en nuestro UILabel transferimos los valores máximos, es decir, el 100 % de la fuerza y 385 gramos. Cabe señalar por qué es 385 gramos. El hecho es que la tecnología 3D Touch está hecha de tal manera que el 100% de la fuerza de prensado corresponde a 385 gramos. En consecuencia, obtenga un porcentaje de la fuerza de prensado, podemos calcular fácilmente el peso en gramos.
- Aquí hacemos estos cálculos. En esta línea calculamos el porcentaje de presión
- Aquí calculamos el peso en gramos, basado en la fórmula 100% = 385 gramos
- Este es un simple redondeo de gramos al conjunto
- Pasamos el porcentaje de fuerza y peso en gramos a nuestro UILabel
Antes de iniciar y verificar la aplicación, debe agregar otro método que funcione cuando todos los toques en la pantalla dejen de
toques Ended (: :) , para establecer la posición inicial de nuestros
UILabels y pasarles los valores 0% y 0 gramos. Agregue este método a la clase
ViewController .
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) { forceLabel.text = "0% force" grammLabel.text = "0 " }
Ahora puede compilar la aplicación y verificar. Por supuesto, debe hacer esto en un dispositivo real para ver el resultado. El simulador no puede emular forzar clics en la pantalla.

Mejoras
La funcionalidad principal está lista, pero cuando escribí esta aplicación, decidí agregar tres cosas:
- Al alcanzar el valor máximo, quiero que funcione la respuesta de vibración
- La actualización de los valores en UILabel ocurre muy rápidamente (creo que notó esto cuando realizó la prueba), por lo que debe agregar algo de suavidad.
- Debe aparecer un círculo semitransparente en el punto de presión. Su diámetro debe aumentar al aumentar la presión y disminuir al disminuir la presión.
Abordaremos estas adiciones en el
siguiente artículo :-)