14 choses qu'un développeur iOS doit savoir

Avec la permission de l'auteur, je poste la traduction de l'article de Norberto Gil Vasconcelos "14 must know pour un développeur iOS" ( lien vers l'original ). Au moment de la publication de l'article, la version Swift 3 était pertinente.

En tant que développeur iOS (actuellement absolument dépendant de Swift), j'ai créé des applications à partir de zéro, pris en charge les applications et travaillé dans différentes équipes. Pendant tout le temps que j'ai travaillé dans cette industrie, j'ai souvent entendu la phrase: "Vous ne pouvez pas expliquer, alors vous ne comprenez pas. Donc, pour essayer de comprendre exactement ce que je fais tous les jours, je crée une liste de ce qui, à mon avis, est important pour tout développeur iOS. Je vais essayer d'expliquer chaque instant aussi clairement que possible. [N'hésitez pas à me corriger, à exprimer votre opinion ou à suggérer vos ajouts à cette liste.]


Sujets: [ contrôle de version | motifs architecturaux | Objective-C contre Swift | Réagir | gestionnaire de dépendances | stockage d'informations | CollectionViews & TableViews | UI | protocoles | courts-circuits | régimes | tests | géolocalisation | chaînes localisables ]


Voici ma liste, sans plus tarder, dans un ordre aléatoire.

1 - Contrôle de version


Félicitations, vous êtes accepté! Extrayez le code du référentiel et mettez-vous au travail. Arrête quoi?

Le contrôle de version est nécessaire pour tout projet, même si vous n'êtes qu'un développeur. Les systèmes les plus couramment utilisés sont Git et SVN.

SVN est basé sur un système de contrôle de version centralisé. Il s'agit du référentiel où les copies de travail sont créées et pour y accéder, vous avez besoin d'une connexion réseau. L'autorisation des modifications s'effectue de manière spécifique; le système surveille les modifications en enregistrant chaque fichier, l'historique complet des modifications ne peut être consulté que dans le référentiel. Les copies de travail contiennent uniquement la dernière version.

Gitutilise un système de contrôle de version distribué. Vous aurez un référentiel local où vous pourrez travailler, une connexion réseau n'est nécessaire que pour la synchronisation. Lorsqu'une copie de travail est modifiée, l'état de l'ensemble du répertoire est enregistré, mais seules les modifications apportées sont enregistrées; Le référentiel et les copies de travail ont un historique complet des modifications.

2 - Modèles architecturaux


Vos doigts tremblent d'excitation, vous avez compris le contrôle de version! Ou est-ce à cause du café? Ça ne fait rien! Vous êtes à deux doigts et le moment est venu de programmer! Nan. Qu'attendre d'autre?
Avant de vous asseoir au clavier, vous devez choisir le modèle architectural auquel vous adhérez. Si vous n'avez pas démarré le projet, vous devez faire correspondre le modèle existant.
Il existe un large éventail de modèles utilisés dans le développement d'applications mobiles (MVC, MVP, MVVM, VIPER, etc.). Je vais donner un bref aperçu des plus fréquemment utilisés dans le développement pour 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 –


Pour une compréhension plus approfondie et des informations sur d'autres modèles, je vous recommande de lire l' article suivant .

Cela peut ne pas sembler beaucoup, mais un code bien structuré et organisé peut éviter beaucoup de maux de tête. La grosse erreur que chaque développeur commet à un moment donné est simplement d'obtenir le résultat souhaité et de refuser d'organiser le code, croyant à tort qu'il fait gagner du temps. Si vous n'êtes pas d'accord, écoutez le vieux Benji:
Chaque minute que vous passez à organiser votre entreprise vous fait gagner une heure

- Benjamin Franklin

Notre objectif est d'obtenir un code intuitif et facile à lire qui sera facile à utiliser et à entretenir.

3 - Objective-C vs Swift


Lorsque vous décidez dans quel langage de programmation écrire votre application, vous devez connaître les capacités de chacun d'eux. Si possible, je préfère utiliser Swift. Pourquoi? Pour être honnête, Objective-C a très peu d'avantages sur Swift. La plupart des exemples et des didacticiels sont écrits en Objective-C, et Swift apporte des ajustements aux paradigmes à chaque mise à jour, ce qui peut être décourageant. Cependant, ces problèmes finiront par disparaître.

Par rapport à Objective-C, Swift fait un bond à bien des égards. Il est facile à lire, il ressemble à l'anglais naturel, et comme il n'est pas construit sur C, cela vous permet d'abandonner les conventions traditionnelles. Pour ceux qui connaissent Objective-C, cela signifie qu'il n'y a plus de point-virgule, et les appels de méthode et les conditions d'expression n'auront pas besoin d'être mis entre crochets. Il est également plus facile de gérer votre code: Swift n'a besoin que d'un fichier .swift au lieu des fichiers .h et .m, car Xcode et le compilateur LLVM peuvent détecter les dépendances et effectuer des builds incrémentiels automatiquement. En général, vous devrez moins vous soucier de créer du code standardisé et vous constaterez que vous pouvez obtenir les mêmes résultats avec moins de lignes.

Toujours dans le doute? Swift est plus sûr, plus rapide et s'occupe de la gestion de la mémoire (pour la plupart!). Savez-vous ce qui se passe dans Objective-C lorsque vous appelez une méthode avec une variable de pointeur non initialisée? Rien. L'expression devient inactive et est ignorée. Cela semble génial, car il ne conduit pas au crash de l'application, mais il provoque un certain nombre de bugs et de comportements instables, à cause desquels vous voudrez penser à changer de profession. Sérieusement. L'idée de devenir un promeneur de chiens professionnel scintille de nouvelles couleurs. Dans le même temps, le compteur Swift fonctionne avec des valeurs facultatives. Vous aurez non seulement une meilleure idée de ce que peut être nil et définissez des conditions pour empêcher l'utilisation de valeurs nil, mais vous obtiendrez également un crash d'exécution si nil facultatif est toujours utilisé, ce qui simplifiera le débogage.ARC (comptage automatique des références) vous aide à mieux gérer votre mémoire dans Swift. Dans Objective-C, ARC ne fonctionne pas avec C procédural ou avec une API comme Core Graphics.

4 - Réagir ou non Réagir? (telle est la question)


La programmation fonctionnelle réactive (FRP) est un nouveau succès. Il est destiné à simplifier la compilation d'opérations asynchrones et de flux d'événements / de données. Pour Swift, il s'agit d'une abstraction générale du calcul exprimée via l'interface Observable.

La façon la plus simple d'illustrer cela est d'utiliser un petit code. Disons que bébé Timmy et sa sœur Jenny veulent acheter une nouvelle console de jeu. Timmy reçoit 5 euros de ses parents chaque semaine, il en va de même pour Jenny. Cependant, Jenny gagne encore 5 euros en livrant des journaux le week-end. Si les deux économisent chaque cent, nous pouvons vérifier chaque semaine si la console est disponible! Chaque fois que la valeur de leur épargne change, leur valeur globale est calculée. Si cela suffit, le message est stocké dans la variable isConsoleAttainable. A tout moment, nous pouvons vérifier le message en vous y abonnant.

// 
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    !

Ce n'est qu'un exemple de ce qui peut être fait avec FRP, une fois maîtrisé, il ouvrira un tout nouveau monde de possibilités, jusqu'à adopter une architecture autre que MVC ... Oui, oui! MVVM!
Vous pouvez regarder deux candidats principaux pour le titre de chef Swift FRP:


5 - Gestionnaire de dépendance


CocoaPods et Carthage sont les gestionnaires de dépendances les plus courants pour les projets Cocoa Swift et Objective-C. Ils simplifient le processus de mise en œuvre de la bibliothèque et de sa mise à jour.

CocoaPods possède de nombreuses bibliothèques construites à l'aide de Ruby et peut être installée à l'aide de la commande suivante:

$ sudo gem install cocoapods

Après l'installation, vous souhaiterez créer un Podfile pour votre projet. Vous pouvez exécuter la commande suivante:

$ pod install

ou créez un fichier pod personnalisé avec cette structure:

platform :ios, '8.0'
use_frameworks!

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

Une fois créé, il est temps d'installer vos nouveaux modules:

$ pod install

Vous pouvez maintenant ouvrir l' espace .xcwork de votre projet, n'oubliez pas d'importer vos dépendances.

Carthage est un gestionnaire de dépendance décentralisé, contrairement à CocoaPods. L'inconvénient est qu'il devient de plus en plus difficile pour les utilisateurs de trouver des bibliothèques existantes. En revanche, cette approche nécessite moins de travail de support et évite les perturbations dues au stockage centralisé.

Pour plus d'informations sur l'installation et l'utilisation, consultez le projet GitHub .

6 - Stockage de données


Commençons par la façon la plus simple de sauvegarder des données pour vos applications. NSUserDefaults , ainsi nommé car il est généralement utilisé pour enregistrer les données utilisateur par défaut affichées lors du premier chargement de l'application. Pour cette raison, il est rendu simple et facile à utiliser, mais cela implique également certaines limitations. L'un d'eux est le type d'objets que cette méthode accepte. Son comportement est très similaire à la liste des propriétés (Plist) , qui a la même restriction. Voici six types d'objets qu'ils peuvent stocker:

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

Pour la compatibilité avec Swift, NSNumber peut accepter les types suivants:

  • UInt
  • Int
  • Flotte
  • Double
  • Bool

Les objets peuvent être stockés dans NSUserDefaults comme suit (créez d'abord une constante qui stockera la clé de l'objet stocké):

let keyConstant = "objectKey"

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

Pour lire un objet à partir de NSUserDefaults, nous pouvons procéder comme suit:

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

Il existe plusieurs méthodes pratiques pour lire et écrire dans NSUserDefaults qui reçoivent des objets spécifiques au lieu d'AnyObject.

Le trousseau est un système de gestion de mot de passe et peut contenir des mots de passe, des certificats, des clés privées ou des notes personnelles. Le trousseau a deux niveaux de cryptage de l'appareil. Le premier niveau utilise le code de verrouillage de l'écran de verrouillage comme clé de cryptage. Le deuxième niveau utilise une clé générée et stockée sur l'appareil.

Qu'est-ce que ça veut dire? Ce n'est pas entièrement super sécurisé, surtout si vous n'utilisez pas de mot de passe sur l'écran de verrouillage. Il existe également des moyens d'accéder à la clé utilisée au deuxième niveau, car elle est stockée sur l'appareil.

La meilleure solution consiste à utiliser votre propre cryptage. (Ne stockez pas la clé sur l'appareil)

CoreData- Il s'agit d'un framework développé par Apple pour que votre application interagisse avec la base de données de manière orientée objet. Cela simplifie le processus en réduisant la quantité de code et en éliminant la nécessité de tester cette section.

Vous devez utiliser CoreData si votre application nécessite des données persistantes, cela simplifie considérablement le processus de les enregistrer et vous permet de ne pas créer / tester votre propre façon de communiquer avec la base de données.

7 - CollectionViews & TableViews


Presque chaque application a un ou plusieurs CollectionViews et / ou TableViews. Savoir comment ils fonctionnent et quand utiliser l'un ou l'autre empêchera à l'avenir des changements complexes dans votre application.

Les vues de tableau affichent une liste d'éléments dans une seule colonne verticalement et ne sont limitées que par le défilement vertical. Chaque élément est représenté par un UITableViewCell, qui peut être entièrement personnalisé. Ils peuvent être triés par sections et lignes.

CollectionViews affiche également une liste d'éléments, mais ils peuvent avoir plusieurs colonnes et lignes (par exemple, une grille). Ils peuvent défiler horizontalement et / ou verticalement, et chaque élément est représenté par un UICollectionViewCell. Comme UITableViewCells, ils peuvent être personnalisés comme vous le souhaitez et triés par section et ligne.

Ils ont tous deux des fonctionnalités similaires et utilisent des cellules réutilisables pour améliorer la mobilité. Le choix de ce dont vous avez besoin dépend de la complexité que vous souhaitez avoir sur la liste. CollectionView peut être utilisé pour représenter n'importe quelle liste et, à mon avis, est toujours le meilleur choix. Imaginez que vous souhaitez soumettre une liste de contacts. La liste est simple, vous pouvez l'implémenter avec une seule colonne, donc vous sélectionnez un UITableView. Tout fonctionne! Après quelques mois, votre concepteur décidera que les contacts doivent être affichés sous forme de grille, pas de liste. La seule façon de procéder consiste à remplacer l'implémentation de UITableView par l'implémentation de UICollectionView. J'essaie de dire que même si votre liste peut être simple et qu'une UITableView peut suffire s'il y a de fortes chances que la conception change, probablementil est préférable d'implémenter cette liste à l'aide d'un UICollectionView.

Quel que soit votre choix, c'est une bonne idée de créer un TableView / CollectionView générique. Cela facilite la mise en œuvre et permet la réutilisation de grandes quantités de code.

8 - Storyboards VS Xibs VS UI programmable


Chacune de ces méthodes peut être utilisée séparément pour créer une interface utilisateur, mais rien ne vous empêche de les combiner.

Les storyboards offrent une vue plus large du projet que les concepteurs apprécieront, vous permettant de voir le flux de l'application ainsi que ses fenêtres. L'inconvénient est qu'avec l'ajout de plus de fenêtres, les connexions deviennent plus confuses et le temps de chargement du Storyboard augmente. Les problèmes de fusion sont beaucoup plus courants car l'intégralité de l'interface utilisateur se trouve dans un seul fichier. Ils deviennent également beaucoup plus difficiles à résoudre.

Xibsfournir une visualisation visuelle des fenêtres ou des parties d'une fenêtre. Les avantages sont la facilité de réutilisation, moins de conflits de fusion que les storyboards et la facilité d'affichage du contenu de chaque fenêtre.

L' interface utilisateur de programmation vous donne plus de contrôle sur elle, réduit la fréquence des conflits de fusion, s'ils surviennent, ils sont plus faciles à supprimer. L'inconvénient est moins de visualisation et plus de temps requis pour l'écriture.

Les approches ci-dessus pour créer une interface utilisateur varient considérablement. Mais, à mon avis subjectif, la meilleure option est une combinaison des trois. Plusieurs Storyboards (maintenant nous pouvons basculer entre les Storyboards!), Avec Xibs pour tout objet visuel qui n'est pas la fenêtre principale, et, enfin, un peu de programmation pour un contrôle supplémentaire, si nécessaire dans certaines situations.

9 - Protocoles!


Dans la vie de tous les jours, des protocoles existent pour que dans une certaine situation nous sachions comment réagir. Supposons que vous soyez pompier et qu'une urgence se soit produite. Chaque pompier doit suivre un protocole qui définit les exigences d'une réponse réussie. La même chose s'applique aux protocoles dans Swift / Objective-C.

Un protocole définit une esquisse des méthodes, des propriétés et d'autres exigences pour les fonctions spécifiées. Il peut être adopté par une classe, une structure ou une énumération, qui aura alors la mise en œuvre réelle de ces exigences.

Voici un exemple de création et d'utilisation d'un protocole:

Pour mon exemple, j'aurai besoin d'une énumération qui répertorie les différents types de matériaux utilisés pour éteindre un incendie.

enum ExtinguisherType: String {

   case water, foam, sand

}

Ensuite, je vais créer un protocole d'intervention d'urgence.

protocol RespondEmergencyProtocol {

   func putOutFire(with material: ExtinguisherType)

}

Je vais maintenant créer une classe de pompier qui respecte le protocole.

class Fireman: RespondEmergencyProtocol {

    func putOutFire(with material: ExtinguisherType) {

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

    }

}

Bien! Et maintenant, nous utilisons notre pompier.

var fireman: Fireman = Fireman()

fireman.putOutFire(with: .foam)

Le résultat devrait être le suivant: "Le feu a été éteint avec de la mousse."

Les protocoles sont également utilisés dans la délégation. Cela permet aux classes ou aux structures de déléguer certaines fonctions à une instance d'un autre type. Un protocole est créé avec des responsabilités déléguées pour garantir que leur fonctionnalité est du type approprié.
Un petit exemple!

protocol FireStationDelegate: AnyObject {

func handleEmergency()

}

Le service d'incendie délègue aux mesures d'intervention d'urgence des pompiers.

class FireStation {
   weak var delegate: FireStationDelegate?

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

Cela signifie que le pompier devra également se conformer au protocole FireStationDelegate.

class Fireman: RespondEmergencyProtocol, FireStationDelegate {

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

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

}

Tout ce qui doit être fait est que le pompier sur appel soit désigné comme délégué à la caserne des pompiers, et il traitera les appels d'urgence reçus.

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

En conséquence, nous obtenons: "Le feu a été éteint avec de l'eau."

dix - Des courts-circuits


Il ne s'agira que de fermetures Swift. Ils sont principalement utilisés pour renvoyer un bloc de fin ou avec des fonctions d'ordre élevé. Les blocs finaux sont utilisés, comme son nom l'indique, pour exécuter un bloc de code une fois la tâche terminée.
Les fermetures dans Swift sont similaires aux blocs en C et Objective-C.

Les fermetures sont des objets de première classe *, ils peuvent donc être imbriqués et passés (comme des blocs dans Objective-C).

Dans Swift, les fonctions sont un cas particulier de fermetures.

Source - fuckingswiftblocksyntax.com **

Cette ressource est un excellent endroit pour apprendre la syntaxe de fermeture.

* Objets de première classe - objets qui peuvent être utilisés sans restrictions: assigner à une variable, passer / retourner d'une fonction, créer / détruire pendant l'exécution du programme, etc. Plus de détails . (ci-après - traducteur approximatif)
** Le site ne fonctionne pas, mais les images sont restées dans waybackmachine, un exemple .


Onze - Schème


En bref, les circuits sont un moyen facile de basculer entre les configurations. Commençons par les informations de base. L'espace de travail contient divers projets associés. Un projet peut avoir plusieurs cibles - les cibles déterminent le produit à assembler et la méthode d'assemblage. En outre, un projet peut avoir différentes configurations. Le schéma dans Xcode définit la collection de cibles pour l'assembly, la configuration utilisée pendant l'assembly et la collection de tests à exécuter.

Le violet montre un motif possible.

12 - Tests


Si vous prenez le temps de tester votre application, vous êtes sur la bonne voie. Bien sûr, ce n'est pas une panacée, vous ne pouvez pas résoudre tous les bogues, ni garantir que votre application sera exempte de tout problème; et pourtant je pense que les avantages l'emportent sur les inconvénients.

Commençons par les inconvénients des tests unitaires:

  • Augmentation du temps de développement;
  • Augmentez la quantité de code.

Avantages :

  • La nécessité de créer du code modulaire (pour simplifier les tests);
  • Détection évidente de la plupart des bogues avant la sortie;
  • Simplification du support.

En combinaison avec l'utilitaire Tools , vous aurez tout pour rendre l'application flexible et fonctionner sans erreurs ni plantages.

Il existe de nombreux outils que vous pouvez utiliser pour tester votre application. Selon ce que vous souhaitez suivre, vous pouvez en sélectionner un ou plusieurs. Les outils les plus couramment utilisés sont peut-être les fuites , le profileur de temps et les allocations .

13 - Géolocalisation


Dans de nombreuses applications, certaines fonctions nécessitent de localiser un utilisateur. Il serait donc agréable d'avoir une idée générale du fonctionnement de l'emplacement pour iOS.

Il existe un framework appelé Core Location, qui vous permet d'accéder à tout ce dont vous avez besoin:

Le framework Core Location vous permet de déterminer l'emplacement actuel ou la direction du mouvement d'un appareil. Le cadre utilise le matériel disponible pour déterminer la position et la direction de l'utilisateur. Vous pouvez utiliser les classes et les protocoles de ce cadre pour configurer et planifier des événements liés à l'emplacement et à la direction. Vous pouvez également utiliser Core Location pour suivre les mouvements à travers les régions géographiques. Sous iOS, vous pouvez également déterminer la distance par rapport à la balise Bluetooth *.

* Si je comprends bien, il s'agit de la technologie iBeacon

Cool, non? Consultez la documentation Apple et l'exemple pour mieux comprendre les capacités du framework.

14 - Chaînes localisables


Ce qui doit être implémenté dans n'importe quelle application. Cela vous permet de changer la langue en fonction de la région dans laquelle se trouve l'appareil. Même si votre application est dans une seule langue, il peut être nécessaire d'en ajouter de nouvelles à l'avenir. Si tout le texte est entré à l'aide de chaînes localisables, il vous suffit d'ajouter la version traduite du fichier Localizable.strings pour la nouvelle langue.

La ressource peut être ajoutée à la langue via l'inspecteur de fichiers. Pour obtenir une chaîne avec NSLocalizedString, vous devez écrire ce qui suit:

NSLocalizedString(key:, comment:)

Malheureusement, pour ajouter une nouvelle ligne au fichier localisable, cela doit être fait manuellement. Voici un exemple de structure:

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

Maintenant une autre langue (portugais), le fichier localisé:

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

Il existe même des moyens de mettre en œuvre le pluriel.

Partagez toujours ce que vous avez appris.

- Maître Yoda

J'espère que cet article vous a été utile!

All Articles