Swift : Nouvelles du front
#Xebia #DevoxxFR
Fabien Mirault
Speakers
@viteinfinite
Simone Civetta
@magici1
Slide 3
Slide 3 text
Swift ou pas ?
Slide 4
Slide 4 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Swift ou pas ?
Septembre 2014
Novembre 2014
Juin 2014
Apple annonce Swift
Swift 1.0
"
Première application Swift
Xebia sur l’App Store
?
Février 2015
Nouvelles applications ?
Slide 5
Slide 5 text
Qu’est-ce que Swift ?
Slide 6
Slide 6 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Qu’est-ce que Swift ?
Nouveau langage de développement
Code plus lisible et moins verbeux
Donc plus simple à maintenir !
Slide 7
Slide 7 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Qu’est-ce que Swift ?
Transition Objective-C → Swift aisée
Moins de tolérance sur les erreurs de
programmation
Rapidité de développement accrue
Slide 8
Slide 8 text
Swift ou pas ?
Slide 9
Slide 9 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Swift ou pas ?
Juin 2014
Apple annonce Swift
Septembre 2014
Swift 1.0
Novembre 2014
"
Première application Swift
Xebia sur l’App Store
?
Février 2015
Nouvelles applications !
Slide 10
Slide 10 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Swift ou pas ?
Octobre 2014
Swift 1.1
September 2015
Swift 2.0
Octobre 2014
Swift 2.1
April 2015
Swift 1.2
Juin 2014
Apple annonce Swift
Septembre 2014
Swift 1.0
Novembre 2014
"
Première application Swift
Xebia sur l’App Store
?
Février 2015
Nouvelles applications !
Mars 2016
Swift 2.2
Slide 11
Slide 11 text
Swift c’est
cool…
…utilisé dans
de vrais
projets !
Slide 12
Slide 12 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
TOC
Nos cas d’usage
Flux d’activité
Création du projet et configuration
Produits et synchronisation
Langues
Commentaires
Testing
Suivre son application
Et l’Objective-C ?
Slide 13
Slide 13 text
Création du projet
Slide 14
Slide 14 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Les dépendances
Librairies dynamiques
Slide 15
Slide 15 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Slide Title
Title
Au revoir iOS 7
Slide 16
Slide 16 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Les dépendances
Slide 17
Slide 17 text
Flux d’activités
Slide 18
Slide 18 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Photos et vidéos
Fluidité
Des milliers de posts
Flux d’activités
Slide 19
Slide 19 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Flux d’activités
Struct
Ne contient que ce qui a été défini
Meilleures performances
Stockage de type valeur et non référence
Passage par copie
Slide 20
Slide 20 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Flux d’activités
struct Attachment {
let id: Int
let url: String
let type: String
let name: String
let objectId: Int
let mimeType: String
let objectType: String
}
Flux d’activités
Exemple de Struct
Slide 21
Slide 21 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Flux d’activités
Struct : Performances
Avec une méthode de shuffle sur 1.000.000 d’objets
Secondes
0
0,325
0,65
0,975
1,3
NSObject Struct
0,064
1,152
Slide 22
Slide 22 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Flux d’activités
Struct VS Classes
Ne peut pas hériter d’objets
Pas de deinitializer
Référence unique d’une instance
Slide 23
Slide 23 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Flux d’activités
JSON -> Struct
func buildUser(jsonData:[String: AnyObject]) -> User? {
if let userData = jsonData["user"] as? [String: AnyObject] {
return User(id: userData["id"]!,
firstname: userData["firstname"]!,
lastname: userData["lastname"]!)
}
return nil
}
Slide 24
Slide 24 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Flux d’activités
Unbox
Conversion automatique
Génère des structs
Performances accrues
Slide 25
Slide 25 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Flux d’activités
Unbox par l’exemple
func buildUser(userData:[String: AnyObject]) -> User? {
let user: User = Unbox(userData)
...
return user
}
Slide 26
Slide 26 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Flux d’activités
Performances
Struct
Héritage Rendu
Slide 27
Slide 27 text
Configurations
Slide 28
Slide 28 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Analytics
Endpoints
Regroupement
Configurations
Profil
Slide 29
Slide 29 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Configurations
Toujours les Structs !
struct Tags {
struct Page {
static let Login = "Login"
static let Camera = "Camera"
static let Newsfeed = "Newsfeed"
static let Favorites = "Favorites"
static let MyProfile = "MyProfile"
}
}
Tags.Page.Login // Login
Slide 30
Slide 30 text
Liste de produits
Slide 31
Slide 31 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
600.000+ lignes
#
Requêtes rapides
$
Liste de produits
Slide 32
Slide 32 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Liste de produits
Stockage : Objective-C
@implementation XBEntityStore
- (void)addEntity:(id)entity {
// Some implementation
}
@end
...
Un peu d’Objective-C
- (void)addSomeObjects {
XBEntityStore *productStore = [XBEntityStore new];
// XBProduct conforms to XBEntity
XBProduct *product = [XBProduct new];
[productStore addEntity:product];
}
Slide 33
Slide 33 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Liste de produits
Stockage : Objective-C
@implementation XBEntityStore
- (void)addEntity:(id)entity {
// Some implementation
}
@end
...
Un peu d’Objective-C
- (void)addSomeObjects {
XBEntityStore *productStore = [XBEntityStore new];
// XBProduct conforms to XBEntity
XBProduct *product = [XBProduct new];
[productStore addEntity:product];
// XBColor conforms to XBEntity
XBColor *color = [XBColor new];
[productStore addEntity:color];
}
Slide 34
Slide 34 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Liste de produits
Generics
class EntityStore {
func addEntity(entity: T) {
// Some implementation
}
}
...
func addSomeObjects() {
let productStore = EntityStore()
// Product conforms to Entity
let product = Product()
productStore.addEntity(product)
// Color conforms to Entity
let color = Color()
productStore.addEntity(color)
}
func addSomeObjects() {
let productStore = EntityStore()
// Product conforms to Entity
let product = Product()
productStore.addEntity(product)
// Color conforms to Entity
let color = Color()
productStore.addEntity(color)
}
Un peu de Swift
Slide 35
Slide 35 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Liste de produits
Generics
Écrire du code facilement réutilisable
et sujet à des contraintes spécifiques
Slide 36
Slide 36 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Liste de produits
TypeAlias
typealias ProductStore = EntityStore
func addSomeObjects() {
let productStore = ProductStore()
// ...
}
Code plus expressif
Slide 37
Slide 37 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Liste de produits
Protocols
Swift est un “langage orienté protocoles”
Apple, 2015
protocol Loadable {
static func load(id: String) -> Self?
}
Slide 38
Slide 38 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Protocols
protocol Loadable {
static func load(id: String) -> Self?
}
class Product : Loadable {
static func load(id: String) -> Self? {
// Open the default database store
// Look for the id
// etc
}
}
Liste de produits
Slide 39
Slide 39 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Liste de produits
Protocols
protocol Loadable {
static func load(id: String) -> Self?
}
class Color : Loadable {
static func load(id: String) -> Self? {
// Open the default database store
// Look for the id
// etc
}
}
Slide 40
Slide 40 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Liste de produits
Protocols Extensions
protocol Loadable {
static func load(id: String) -> Self?
}
extension Loadable {
static func load(id: String) -> Self? {
// Open the default database store
// Look for the id
// etc
}
}
Slide 41
Slide 41 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Liste de produits
Protocols Extensions
protocol Loadable {
static func load(id: String) -> Self?
}
extension Loadable {
static func load(id: String) -> Self? {
// ...
}
}
class Product : Loadable { /* ... */ }
class Color : Loadable { /* ... */ }
Slide 42
Slide 42 text
Synchronisation
Slide 43
Slide 43 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Synchronisation et
manipulation
500 Mo de données
%
Performances
$
Synchronisation
Slide 44
Slide 44 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Synchronisation
Performances
déclarations final et static
Profiter pleinement du runtime de Swift
Slide 45
Slide 45 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Synchronisation
Performances
Attention aux casts entre
Array 㲗 NSArray
Dictionary 㲗 NSDictionary
Slide 46
Slide 46 text
Tâches asynchrones
Slide 47
Slide 47 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Librairie locale
Tâches asynchrones
Ecran personnalisé
Animation diaphragme
Appareil photo
Slide 48
Slide 48 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Tâches asynchrones
Closure
Equivalent des blocks en Objective-C
Comprend un bloc de code à exécuter
Définition : { () -> () in }
Slide 49
Slide 49 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Tâches asynchrones
Exemple de closure
self.closeDiaphragm { _ in
self.openDiaphragm()
}
Slide 50
Slide 50 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Tâches asynchrones
Optionals
Possède une valeur ou non
Rend le code plus expressif
Tester la non nullité : guard let
Définition : var delegate:CameraDelegate?
Slide 51
Slide 51 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Tâches asynchrones
Exemple d’optionals
func setup(image:UIImage?) {
guard let menuIcon = image else { return }
let menuImageView = UIImageView(image: menuIcon)
self.addSubview(menuImageView)
}
Slide 52
Slide 52 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Tâches asynchrones
Optionals : fiabilité !
Source : DevFee (Developers feeling)
Slide 53
Slide 53 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Appels asynchrones
Tâches asynchrones
Sur n’importe quel post
Gestion des retours serveur
Poster un commentaire
Slide 54
Slide 54 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Tâches asynchrones
Promise
Code plus lisible
Idéal pour les tâches asynchrones
Chaînage possible
Slide 55
Slide 55 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Tâches asynchrones
Exemple de Promise
// Parameters
var parameters = Parameters()
parameters["content"] = view.textView.text
PostRequest.getHeaders()
.success { token in
return PostRequest.postContent(token, parameters)
}
.success { data in
sendComplete()
}
.failure { (error, isCancelled) -> Void in
sendFailed()
}
Slide 56
Slide 56 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Tâches asynchrones
Sans Promise
// Parameters
var parameters = Parameters()
parameters["content"] = view.textView.text
PostRequest.getHeaders() { [weak self] (token: String, error: NSError) -> Void in
if token != nil {
PostRequest.postContent(token, parameters) { [weak self] (result: Bool, error: NSError) -> Void in
if result == true {
if let strongSelf == self {
strongSelf.sendComplete()
}
} else {
if let strongSelf == self {
strongSelf.sendFailed()
}
}
}
} else {
if let strongSelf == self {
strongSelf.sendFailed()
}
}
}
Slide 57
Slide 57 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
SwiftTasks
Une des librairies principales
Mise en place simple…
…mais des erreurs dans Xcode
Slide 58
Slide 58 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Tâches asynchrones
Erreurs avec Xcode
if let colorsFilePath = syncDataConfiguration.colorsFile, data = NSData(contentsOfFile:colorsFilePath) {
MetadataJSONDeserializer.deserialize(data, keyPath: "colors.color")
.success { color -> ColorDuplicateRemovalTask in
return self.removeDuplicateIdentifiers(colors)
}
.success { colors -> JSONInsertTask in
return entityStore.replaceAllObjects(colors, transformer: Color.tranform)
}
.success { JSONs -> Void in
taskTuple.fulfill(JSONs)
}
.failure { (error, isCancelled) in
if let error = error {
taskTuple.reject(error)
}
}
return taskTuple.task
}
Slide 59
Slide 59 text
Disponibilité produit
Slide 60
Slide 60 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Simple requête HTTP
&
Mise à jour de la UI
'
Disponibilité produit
Slide 61
Slide 61 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Disponibilité produit
Les étapes
Récupération
Déserialisation
UI
Slide 62
Slide 62 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Disponibilité produit
Functional Reactive Programming
Propagation de messages
Asynchronisme
Robustesse
Slide 63
Slide 63 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Disponibilité produit
Functional Reactive Programming
^{ available in
guard let available = available as? Bool else { return }
availabilitySpinner.stopAnimating()
availabilityIndicator.textColor = colorForStatus(available)
} <~ KVO.stream(viewModel, "status")
Slide 64
Slide 64 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
ReactiveCocoa
github.com/ReactiveCocoa/
Disponibilité produit
Slide 65
Slide 65 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
ReactKit
github.com/ReactKit/
Disponibilité produit
Slide 66
Slide 66 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
[[[RACObserve(viewModel.status)
map:^id(NSString *status) {
if ([status isKindOfClass:[NSString class]]) {
return status;
}
return nil;
}]
map:^id(NSString *status) {
return @([status isEqualToString:@"available"]);
}]
delay:1.0];
[[[RACObserve(viewModel.status)
map:^id(NSString *status) {
if ([status isKindOfClass:[NSString class]]) {
return status;
}
return nil;
}]
map:^id(NSString *status) {
return @([status isEqualToString:@"available"]);
}]
delay:1.0];
FRP - Objective-C
Disponibilité produit
Slide 67
Slide 67 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
FRP - Swift
let availabilitySignal = KVO.signal(viewModel, "status")
.map { status -> String? in
return status as? String
}
.map { status -> Bool in
return status == "available"
}
.delay(1.0)
Disponibilité produit
Slide 68
Slide 68 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Disponibilité produit
Opérateurs Custom
^{ available in
guard let available = available as? Bool else { return }
availabilitySpinner.stopAnimating()
availabilityIndicator.textColor = colorForStatus(available)
} <~ KVO.stream(viewModel, "status")
<~
Slide 69
Slide 69 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Slide Title
Title
Slide 70
Slide 70 text
Internationalisation
Slide 71
Slide 71 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Changement de la langue
(
Traduction des contenus
)
Traduction de l’IHM
'
Internationalisation
Slide 72
Slide 72 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Internationalisation
Enums
enum Country {
case USA
case China
case Italy
}
Et finalement du Swift
Slide 73
Slide 73 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Internationalisation
Enums
enum Country {
case USA
case China
case Italy
static var preferred: Country {
return Country.Italy
}
}
Country.preferred // .Italy
Et finalement du Swift
Valeurs associées
Slide 74
Slide 74 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Internationalisation
Enums
enum Country: String {
case USA
case Italy
var name: String {
switch self {
case USA:
return "United States"
case Italy:
return "Italia!"
}
}
}
Country.Italy.name // .Italia!
Et finalement du Swift
Propriétés
Slide 75
Slide 75 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Internationalisation
Switch
enum Language {
case English
case Italian
// ...
var language: String {
switch self {
// ...
}
}
}
Swift
Slide 76
Slide 76 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Internationalisation
Switch
enum Language {
case English(country: Country)
case Italian
var language: String {
switch self {
case .English(let country):
return "English \(country.name)"
// ...
}
}
Language.English(country: .USA).name // English (United States)
Swift
Value
binding
Slide 77
Slide 77 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Internationalisation
Enums : it’s over 9000!!!
First-Class types
Méthodes et propriétés
Vérifiés à la compilation
Valeurs associées
Slide 78
Slide 78 text
Tests
Slide 79
Slide 79 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Assurer le fonctionnement
de l’application
Se protéger des régressions
Tests
Slide 80
Slide 80 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Tests
Chargement des produits
Product.load("A00")
Comment tester ?
Slide 81
Slide 81 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Slide Title
Protocols Extensions
protocol Loadable {
static func load(id: String) -> Self?
}
extension Loadable {
static func load(id: String) -> Self? {
// Open the default database store
// Look for the id
// etc
}
}
Slide 82
Slide 82 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Slide Title
Protocols Extensions
protocol Loadable {
static func load(id: String, store: Store) -> Self?
}
extension Loadable {
static func load(id: String, store: Store = Stores.DefaultStore) -> Self? {
// Open the default database store
// Look for the id
// etc
}
}
Slide 83
Slide 83 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
func testDoSomething() {
// Setup
let mockStore = Store(products: [Product(id: "A00")])
// Run
let product = Product.load("A00", store: mockStore)
// Verify
XCTAssertNotNil(product)
}
Tests
Chargement des produits
Product.load("A00")
Slide 84
Slide 84 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Liste de produits
Swift VS Swift
class Store {
func addEntity(entity: Product) {
// Some implementation
}
}
let entityStore = EntityStore()
let product = Product()
entityStore.addEntity(product)
Coder Swift != Penser Swift
class Store {
func addEntity(entity: T) {
// Some implementation
}
}
let productStore = ProductStore()
let product = Product()
product.save(productStore)
Generics
Typealias
Protocol extensions
Slide 85
Slide 85 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Slide Title
Title
#DevoxxFR
Swift : Nouvelles du front
Slide 86
Slide 86 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Slide Title
Title
#DevoxxFR
Swift : Nouvelles du front
Slide 87
Slide 87 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Tests
Mais aussi…
Slide 88
Slide 88 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Flux d’activités
Flux d’activités
Crash
Slide 89
Slide 89 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Tests
Mais aussi…
Slide 90
Slide 90 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Tests
Mais aussi…
Slide 91
Slide 91 text
Suivre son application
Slide 92
Slide 92 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Suivre son application
Fabric
Déploiement centralisé et versionné
Remontées de crashs
Statistiques d’utilisation
Slide 93
Slide 93 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Fabric - Objective-C
RTSViewController.m line 1310
-[RTSViewController getCurrentUDPValues]
Fatal Exception: NSRangeException
*** -[__NSArrayM objectAtIndex:]
index 4294967292 beyond bounds [0 .. 511]
Suivre son application
Slide 94
Slide 94 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Fabric - Swift
WSClient.swift line 31
static MyLittlePony.WSClient.requestContent
(MyLittlePony.WSClient.Type) parameters : Swift.Optional
Crashed: com.apple.main-thread
SIGABRT ABORT at 0x312a8df0
Suivre son application
Slide 95
Slide 95 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Suivre son application
Pourquoi ?
Évolution du langage constante
Rétrocompatibilité non assurée
Slide 96
Slide 96 text
Et l’Objective-C ?
Slide 97
Slide 97 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Et l’Objective-C dans tout ça ?
Toujours valable
Mais développement plus lent
Migration progressive conseillée
Slide 98
Slide 98 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Popularité des recherches
2014 2015 2016
Objective-CSwift Objective-CSwift Objective-CSwift
Source : TIOBE
3 ème
19 ème
14 ème
15 ème 15 ème
14 ème
Et l’Objective-C dans tout ça ?
Slide 99
Slide 99 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Les avantages de Swift
Plus facile à maintenir et plus robuste
Demande moins de code
Ouverture vers du développement back
Soyez acteur des évolutions d’Apple !
Slide 100
Slide 100 text
Swift : Nouvelles du front
#Xebia #DevoxxFR
Slide 101
Slide 101 text
One more thing…
Slide 102
Slide 102 text
No content
Slide 103
Slide 103 text
23-24 septembre
frenchkit.fr
Billets en vente dès aujourd’hui
CocoaHeads Paris
Swift : Nouvelles du front
#Xebia #DevoxxFR
Un peu de lecture
A Swift Kickstart
Daniel Steinberg
Functional Programming in Swift
Chris Eidhof, Florian Kugler, and Wouter Swierstra
http://blog.xebia.fr/tag/swift
L’équipe iOS Xebia
Advanced Swift
Chris Eidhof and Airspeed Velocity