14 cosas que un desarrollador de iOS debe saber

Con el permiso del autor, publico la traducción del artículo de Norberto Gil Vasconcelos "14 debe saber para un desarrollador de iOS" ( enlace al original ). En el momento de la publicación del artículo, la versión de Swift 3. Era relevante.

Como desarrollador de iOS (actualmente absolutamente dependiente de Swift), creé aplicaciones desde cero, apoyé aplicaciones y trabajé en varios equipos. Durante todo el tiempo que he estado trabajando en esta industria, a menudo escuché la frase: "No puedes explicar, entonces no entiendes". Entonces, en un intento por comprender qué hago exactamente todos los días, creo una lista de lo que, en mi opinión, es importante para cualquier desarrollador de iOS. Trataré de explicar cada momento lo más claramente posible. [No dude en corregirme, expresar su opinión o sugerir sus adiciones a esta lista.]


Temas: [ control de versiones | patrones arquitectónicos | Objetivo-C vs. Swift | Reaccionar | gerente de dependencia | almacenamiento de información | CollectionViews y TableViews | UI | protocolos | cortocircuitos | esquemas | pruebas | geolocalización | cadenas localizables ]


Aquí está mi lista, sin más preámbulos, en orden aleatorio.

1 - Control de versiones


¡Felicidades, eres aceptado! Extrae el código del repositorio y ponte a trabajar. ¿Detener Qué?

El control de versiones es necesario para cualquier proyecto, incluso si solo es un desarrollador. Los sistemas más utilizados son Git y SVN.

SVN se basa en un sistema de control de versiones centralizado. Este es el repositorio donde se crean copias de trabajo, y para acceder a ellas necesita una conexión de red. La autorización de cambios se lleva a cabo de manera específica; el sistema monitorea los cambios registrando cada archivo, el historial completo de cambios solo se puede ver en el repositorio. Las copias de trabajo contienen solo la última versión.

Gitutiliza un sistema de control de versiones distribuido. Tendrá un repositorio local donde podrá trabajar, una conexión de red solo es necesaria para la sincronización. Cuando se cambia una copia de trabajo, se guarda el estado de todo el directorio, pero solo se registran los cambios realizados; Tanto el repositorio como las copias de trabajo tienen un historial de cambios completo.

2 - Patrones arquitectónicos


¡Tus dedos tiemblan de emoción, descubriste el control de versiones! ¿O es por el café? ¡No importa! ¡Estás al borde y ha llegado el momento de programar! No ¿Qué más esperar?
Antes de sentarse al teclado, debe elegir el patrón arquitectónico al que se adherirá. Si no ha comenzado el proyecto, debe coincidir con el patrón existente.
Existe una amplia gama de patrones utilizados en el desarrollo de aplicaciones móviles (MVC, MVP, MVVM, VIPER, etc.). Daré una breve descripción de los más utilizados en el desarrollo para iOS:

  • MVC — Model, View, Controller. Controller Model View, . View Controller , Controller . ? , View, (ViewController) . , MVC. MVC . ( !), , , Model, , . MVC , , iOS .


    MVC –
  • MVVMModel, View, ViewModel. ( ) View ViewModel, ViewModel , ViewModel, View - . ViewModel View, , .


    MVVM –


Para una comprensión más profunda e información sobre otros patrones, recomiendo leer el siguiente artículo .

Puede que esto no parezca mucho, pero un código bien estructurado y organizado puede evitar muchos dolores de cabeza. El gran error que comete cada desarrollador en algún momento es simplemente obtener el resultado deseado y negarse a organizar el código, creyendo erróneamente que ahorra tiempo. Si no está de acuerdo, escuche al viejo Benji:
Cada minuto que pasa organizando su negocio le ahorra una hora

- Benjamin Franklin

Nuestro objetivo es obtener un código intuitivo y fácil de leer que sea fácil de usar y mantener.

3 - Objetivo-C vs Swift


Al decidir en qué lenguaje de programación escribir su aplicación, debe saber qué capacidades tiene cada uno de ellos. Si es posible, prefiero usar Swift. ¿Por qué? Para ser honesto, Objective-C tiene muy pocas ventajas sobre Swift. La mayoría de los ejemplos y tutoriales están escritos en Objective-C, y Swift hace ajustes a los paradigmas con cada actualización, lo que puede ser desalentador. Sin embargo, estos problemas eventualmente desaparecerán.

En comparación con Objective-C, Swift da un salto de muchas maneras. Es fácil de leer, parece un inglés natural y, dado que no está basado en C, esto le permite abandonar las convenciones tradicionales. Para aquellos que conocen Objective-C, esto significa que no habrá más puntos y comas, y que las llamadas a métodos y las condiciones de expresión no tendrán que estar entre corchetes. También es más fácil mantener su código: Swift solo necesita un archivo .swift en lugar de archivos .h y .m, porque Xcode y el compilador LLVM pueden detectar dependencias y realizar compilaciones incrementales automáticamente. En general, tendrá que preocuparse menos por crear código estandarizado, y encontrará que puede lograr los mismos resultados con menos líneas.

¿Aún tienes dudas? Swift es más seguro, más rápido y se encarga de la administración de la memoria (¡en su mayor parte!). ¿Sabes lo que sucede en Objective-C cuando llamas a un método con una variable de puntero no inicializada? Nada. La expresión se vuelve inactiva y se omite. Suena genial, porque no conduce a la caída de la aplicación, pero causa una serie de errores y un comportamiento inestable, por lo que querrás pensar en cambiar tu profesión. Seriamente. La idea de convertirse en un paseador de perros profesional brilló con nuevos colores. Al mismo tiempo, el contador Swift funciona con valores opcionales. No solo obtendrá una mejor idea de lo que puede ser nulo y establecerá condiciones para evitar el uso de valores nulos, sino que también obtendrá un bloqueo en tiempo de ejecución si todavía se usa nil opcional, lo que simplificará la depuración.ARC (conteo automático de referencias) lo ayuda a administrar mejor su memoria en Swift. En Objective-C, ARC no funciona con C de procedimiento o con una API como Core Graphics.

4 - ¿Reaccionar o no reaccionar? (Esa es la pregunta)


La programación reactiva funcional (FRP) es un nuevo éxito. Su objetivo es simplificar la compilación de operaciones asincrónicas y secuencias de datos / eventos. Para Swift, esta es una abstracción general de la computación expresada a través de la interfaz Observable.

La forma más fácil de ilustrar esto es con un pequeño código. Digamos que el bebé Timmy y su hermana Jenny quieren comprar una nueva consola de juegos. Timmy recibe 5 euros de sus padres cada semana, lo mismo ocurre con Jenny. Sin embargo, Jenny gana otros 5 euros entregando periódicos los fines de semana. Si ambos ahorran cada centavo, ¡podemos verificar cada semana si la consola está disponible! Cada vez que cambia el valor de sus ahorros, se calcula su valor agregado. Si esto es suficiente, el mensaje se almacena en la variable isConsoleAttainable. En cualquier momento, podemos verificar el mensaje suscribiéndonos.

// 
let timmySavings = Variable(5)
let jennySavings = Variable(10)

var isConsoleAttainable =
Observable
.combineLatest(timmy.asObservable(), jenny.asObservable()) { $0 + $1 }
.filter { $0 >= 300 }
.map { "\($0)    !" }

//  
timmySavings.value = 10
jennySavings.value = 20
isConsoleAttainable
   .subscribe(onNext: { print($0) }) //   

//  
timmySavings.value = 100
jennySavings.value = 200
isConsoleAttainable
   .subscribe(onNext: { print($0) }) // 300    !

Este es solo un ejemplo de lo que se puede hacer con FRP, una vez que lo domines, se abrirá un mundo completamente nuevo de posibilidades, hasta adoptar una arquitectura que no sea MVC ... ¡Sí, sí! MVVM!
Puede ver dos solicitantes principales para el título de jefe Swift FRP:


5 - Gerente de dependencia


CocoaPods y Carthage son los administradores de dependencia más comunes para los proyectos Cocoa Swift y Objective-C. Simplifican el proceso de implementación de la biblioteca y la mantienen actualizada.

CocoaPods tiene muchas bibliotecas creadas con Ruby y se puede instalar con el siguiente comando:

$ sudo gem install cocoapods

Después de la instalación, querrá crear un Podfile para su proyecto. Puede ejecutar el siguiente comando:

$ pod install

o cree un Podfile personalizado con esta estructura:

platform :ios, '8.0'
use_frameworks!

target 'MyApp' do
pod 'AFNetworking', '~> 2.6'
pod 'ORStackView', '~> 3.0'
pod 'SwiftyJSON', '~> 2.3'
end

Una vez creado, es hora de instalar sus nuevos módulos:

$ pod install

Ahora puede abrir el espacio de trabajo .xcworks de su proyecto, no olvide importar sus dependencias.

Carthage es un administrador de dependencias descentralizado, a diferencia de CocoaPods. La desventaja de esto es que cada vez es más difícil para los usuarios encontrar bibliotecas existentes. Por otro lado, este enfoque requiere menos trabajo de soporte y evita interrupciones debido al almacenamiento centralizado.

Para obtener más información sobre la instalación y el uso, consulte el proyecto GitHub .

6 - Almacenamiento de datos


Comencemos con la forma más fácil de guardar datos para sus aplicaciones. NSUserDefaults , llamado así porque generalmente se usa para guardar los datos de usuario predeterminados que se muestran cuando se carga la aplicación por primera vez. Por esta razón, se hace simple y fácil de usar, pero esto también implica algunas limitaciones. Uno de ellos es el tipo de objetos que acepta este método. Su comportamiento es muy similar al de la Lista de propiedades (Plist) , que tiene la misma restricción. Aquí hay seis tipos de objetos que pueden almacenar:

  • NSData
  • NSDate
  • NSNumber
  • NSDictionary
  • Nsstring
  • NSArray

Para compatibilidad con Swift, NSNumber puede aceptar los siguientes tipos:

  • UInt
  • En t
  • Flotador
  • Doble
  • Bool

Los objetos se pueden almacenar en NSUserDefaults de la siguiente manera (Primero cree una constante que almacenará la clave para el objeto almacenado):

let keyConstant = "objectKey"

let defaults = NSUserDefaults.standardsUserDefaults()
defaults.setObject("Object to save", objectKey: keyConstant)

Para leer un objeto de NSUserDefaults, podemos hacer lo siguiente:

if let name = defaults.stringForKey(keyConstant) {
   print(name)
}

Existen varios métodos convenientes para leer y escribir en NSUserDefaults que reciben objetos específicos en lugar de AnyObject.

Keychain es un sistema de administración de contraseñas y puede contener contraseñas, certificados, claves privadas o notas personales. El llavero tiene dos niveles de encriptación del dispositivo. El primer nivel utiliza el código de bloqueo de la pantalla de bloqueo como clave de cifrado. El segundo nivel utiliza una clave generada y almacenada en el dispositivo.

Qué significa eso? Esto no es del todo seguro, especialmente si no está utilizando una contraseña en la pantalla de bloqueo. También hay formas de acceder a la clave utilizada en el segundo nivel, ya que está almacenada en el dispositivo.

La mejor solución es usar su propio cifrado. (No guarde la clave en el dispositivo)

CoreData- Este es un marco desarrollado por Apple para que su aplicación interactúe con la base de datos de manera orientada a objetos. Esto simplifica el proceso al reducir la cantidad de código y eliminar la necesidad de probar esta sección.

Debe usar CoreData si su aplicación necesita datos persistentes, esto simplifica enormemente el proceso de guardarlos y le permite no crear / probar su propia forma de comunicarse con la base de datos.

7 - CollectionViews & TableViews


Casi todas las aplicaciones tienen uno o más CollectionViews y / o TableViews. Saber cómo funcionan y cuándo usar uno u otro evitará cambios complejos en su aplicación en el futuro.

TableViews muestra una lista de elementos en una sola columna verticalmente y está limitada solo por el desplazamiento vertical. Cada elemento está representado por un UITableViewCell, que se puede personalizar completamente. Se pueden ordenar por secciones y filas.

CollectionViews también muestra una lista de elementos, pero pueden tener múltiples columnas y filas (por ejemplo, una cuadrícula). Se pueden desplazar horizontal y / o verticalmente, y cada elemento está representado por un UICollectionViewCell. Al igual que UITableViewCells, se pueden personalizar según se desee y ordenar por sección y fila.

Ambos tienen una funcionalidad similar y usan celdas reutilizables para mejorar la movilidad. La elección de lo que necesita depende de la complejidad que desee tener en la lista. CollectionView se puede utilizar para representar cualquier lista y, en mi opinión, siempre es la mejor opción. Imagine que desea enviar una lista de contactos. La lista es simple, puede implementarla con una sola columna, por lo que selecciona un UITableView. ¡Todo está funcionando! Después de unos meses, su diseñador decidirá que los contactos se muestren en formato de cuadrícula, no en una lista. La única forma de hacerlo es cambiar la implementación de UITableView a la implementación de UICollectionView. Estoy tratando de decir que, aunque su lista puede ser simple y un UITableView puede ser suficiente si hay una alta probabilidad de un cambio de diseño, probablementeLo mejor es implementar esta lista utilizando UICollectionView.

Independientemente de la elección que haga, es una buena idea crear un TableView / CollectionView genérico. Esto facilita la implementación y permite la reutilización de grandes cantidades de código.

8 - Storyboards VS Xibs VS IU programable


Cada uno de estos métodos se puede usar por separado para crear una interfaz de usuario, pero nada le impide combinarlos.

Los guiones gráficos proporcionan una vista más amplia del proyecto que les gustará a los diseñadores, permitiéndole ver el flujo de la aplicación y sus ventanas. La desventaja es que con la adición de más ventanas, las conexiones se vuelven más confusas y aumenta el tiempo de carga del Storyboard. Los problemas de combinación son mucho más comunes porque toda la interfaz de usuario está en un solo archivo. También se vuelven mucho más difíciles de resolver.

XibsProporcionar visualización visual de ventanas o partes de una ventana. Las ventajas son la facilidad de reutilización, menos conflictos de fusión que Storyboards y la facilidad de ver el contenido de cada ventana.

La interfaz de usuario de programación le da más control sobre ella, reduce la frecuencia de los conflictos de fusión, si surgen, son más fáciles de eliminar. La desventaja es menos visualización y tiempo adicional requerido para escribir.

Los enfoques anteriores para crear una interfaz de usuario varían mucho. Pero, en mi opinión subjetiva, la mejor opción es una combinación de los tres. Varios Storyboards (¡ahora podemos cambiar entre Storyboards!), Con Xibs para cualquier objeto visual que no sea la ventana principal y, finalmente, una pequeña programación para un control adicional, tan necesario en ciertas situaciones.

9 - Protocolos!


En la vida cotidiana, existen protocolos para que en una determinada situación sepamos cómo responder. Suponga que es un bombero y que ha ocurrido una emergencia. Cada bombero debe seguir un protocolo que establece los requisitos para una respuesta exitosa. Lo mismo se aplica a los protocolos en Swift / Objective-C.

Un protocolo define un bosquejo de métodos, propiedades y otros requisitos para funciones específicas. Puede ser adoptado por una clase, estructura o enumeración, que luego tendrá la implementación real de estos requisitos.

Aquí hay un ejemplo de creación y uso de un protocolo:

para mi ejemplo, necesitaré una enumeración que enumere los diferentes tipos de materiales utilizados para extinguir un incendio.

enum ExtinguisherType: String {

   case water, foam, sand

}

A continuación, crearé un protocolo de respuesta de emergencia.

protocol RespondEmergencyProtocol {

   func putOutFire(with material: ExtinguisherType)

}

Ahora crearé una clase de bombero que obedezca el protocolo.

class Fireman: RespondEmergencyProtocol {

    func putOutFire(with material: ExtinguisherType) {

       print("Fire was put out using \(material.rawValue).")

    }

}

¡Multa! Y ahora usamos a nuestro bombero.

var fireman: Fireman = Fireman()

fireman.putOutFire(with: .foam)

El resultado debería ser el siguiente: "El fuego se apagó con espuma".

Los protocolos también se utilizan en la delegación. Esto permite que las clases o estructuras deleguen ciertas funciones a una instancia de otro tipo. Se crea un protocolo con responsabilidades delegadas para garantizar que su funcionalidad sea del tipo apropiado.
Un pequeño ejemplo!

protocol FireStationDelegate: AnyObject {

func handleEmergency()

}

El departamento de bomberos delega a los bomberos las medidas de respuesta de emergencia.

class FireStation {
   weak var delegate: FireStationDelegate?

   func emergencyCallReceived() {
      delegate?.handleEmergency()
   }
}

Esto significa que el bombero también tendrá que cumplir con el protocolo FireStationDelegate.

class Fireman: RespondEmergencyProtocol, FireStationDelegate {

   func putOutFire(with material: ExtinguisherType) {
      print("Fire was put out using \(material.rawValue).")
   }

   func handleEmergency() {
      putOutFire(with: .water)
   }

}

Todo lo que hay que hacer es que el bombero en las llamadas sea designado como delegado de la estación de bomberos, y se encargará de las llamadas de emergencia recibidas.

let firestation: FireStation = FireStation()
firestation.delegate = fireman
firestation.emergencyCallReceived()

Como resultado, obtenemos: "El fuego se apagó con agua".

10 - Corto circuitos


Solo se tratará de cierres rápidos. Se utilizan principalmente para devolver un bloque final o con funciones de orden superior. Los bloques finales se utilizan, como su nombre lo indica, para ejecutar un bloque de código una vez que se completa la tarea.
Los cierres en Swift son similares a los bloques en C y Objective-C.

Los cierres son objetos de primera clase *, por lo que pueden anidarse y pasarse (como bloques en Objective-C).

En Swift, las funciones son un caso especial de cierres.

Fuente - fuckingswiftblocksyntax.com **

Este recurso es un gran lugar para aprender la sintaxis de cierre.

* Objetos de primera clase: objetos que se pueden usar sin restricciones: asignar a una variable, pasar / devolver desde una función, crear / destruir durante la ejecución del programa, etc. Más detalles . (en adelante, aprox. traductor)
** El sitio no funciona, pero todavía hay imágenes en waybackmachine, un ejemplo .


once - Esquema


En resumen, los circuitos son cualquier forma fácil de cambiar entre configuraciones. Comencemos con la información básica. El espacio de trabajo contiene varios proyectos relacionados. Un proyecto puede tener varios objetivos: los objetivos determinan el producto que se ensamblará y el método de ensamblaje. Además, un proyecto puede tener varias configuraciones. El esquema en Xcode define la recopilación de objetivos para el ensamblaje, la configuración utilizada durante el ensamblaje y la recopilación de pruebas para ejecutar.

El morado muestra un posible patrón.

12 - Pruebas


Si se toma el tiempo de probar su aplicación, está en el camino correcto. Esto, por supuesto, no es una panacea, no puede solucionar todos los errores, ni puede garantizar que su aplicación esté libre de problemas; y, sin embargo, creo que los profesionales superan a los contras.

Comencemos con las desventajas de las pruebas unitarias:

  • Mayor tiempo de desarrollo;
  • Aumenta la cantidad de código.

Pros :

  • La necesidad de crear código modular (para simplificar las pruebas);
  • Obviamente, detectar la mayoría de los errores antes del lanzamiento;
  • Simplificación del soporte.

En combinación con la utilidad Herramientas , tendrá todo para hacer que la aplicación sea flexible y funcione sin errores y fallas.

Hay muchas herramientas que puede usar para probar su aplicación. Dependiendo de lo que quiera rastrear, puede seleccionar uno o más de ellos. Quizás las herramientas más utilizadas son las fugas , el generador de perfiles de tiempo y las asignaciones .

13 - Geolocalización


En muchas aplicaciones, algunas funciones requieren localizar a un usuario. Por lo tanto, sería bueno tener una idea general de cómo funciona la ubicación para iOS.

Hay un marco llamado Core Location, que le permite acceder a todo lo que necesita:

El marco de ubicación central le permite determinar la ubicación actual o la dirección de movimiento de un dispositivo. El marco utiliza hardware disponible para determinar la posición y dirección del usuario. Puede usar las clases y protocolos de este marco para configurar y programar eventos relacionados con la ubicación y la dirección. También puede usar la Ubicación central para rastrear movimientos en regiones geográficas. En iOS, también puede determinar la distancia a la baliza Bluetooth *.

* Según tengo entendido, se trata de la tecnología iBeacon

Genial, ¿no es así? Consulte la documentación de Apple y el ejemplo allí para comprender mejor las capacidades del marco.

14 - Cadenas localizables


Lo que debe implementarse en cualquier aplicación. Esto le permite cambiar el idioma según la región en la que se encuentre el dispositivo. Incluso si su aplicación está en un solo idioma, puede ser necesario agregar otros nuevos en el futuro. Si todo el texto se ingresa utilizando cadenas localizables, todo lo que tiene que hacer es agregar la versión traducida del archivo Localizable.strings para el nuevo idioma.

El recurso se puede agregar al idioma a través del inspector de archivos. Para obtener una cadena con NSLocalizedString, debe escribir lo siguiente:

NSLocalizedString(key:, comment:)

Desafortunadamente, para agregar una nueva línea al archivo Localizable, esto debe hacerse manualmente. Aquí hay una estructura de ejemplo:

{
"APP_NAME" = "MyApp"
"LOGIN_LBL" = "Login"
...
}

Ahora otro idioma (portugués), el archivo localizado:

{
"APP_NAME" = "MinhaApp"
"LOGIN_LBL" = "Entrar"
...
}

Incluso hay formas de implementar el plural.

Siempre comparte lo que has aprendido.

- Maestro Yoda

¡Espero que este artículo haya sido útil!

All Articles