Devoxx France - Nouvelles du Front
-
Upload
xebia-france -
Category
Technology
-
view
213 -
download
5
Transcript of Devoxx France - Nouvelles du Front
Swift : Nouvelles du front
Swift : Nouvelles du front#Xebia #DevoxxFR
Fabien Mirault
Speakers
@viteinfinite
Simone Civetta@magici1
Swift ou pas ?
Swift : Nouvelles du front#Xebia #DevoxxFR
Swift ou pas ?
Septembre 2014
Novembre 2014Juin 2014
Apple annonce Swift
Swift 1.0
Première application SwiftXebia sur l’App Store
?
Février 2015
Nouvelles applications ?
Qu’est-ce que Swift ?
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 !
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
Swift ou pas ?
Swift : Nouvelles du front#Xebia #DevoxxFR
Swift ou pas ?
Juin 2014
Apple annonce Swift
Septembre 2014
Swift 1.0
Novembre 2014
Première application SwiftXebia sur l’App Store
?
Février 2015
Nouvelles applications !
Swift : Nouvelles du front#Xebia #DevoxxFR
Swift ou pas ?
Octobre 2014
Swift 1.1
September 2015
Swift 2.0Octobre 2014
Swift 2.1
April 2015
Swift 1.2
Juin 2014
Apple annonce Swift
Septembre 2014
Swift 1.0
Novembre 2014
Première application SwiftXebia sur l’App Store
?
Février 2015
Nouvelles applications !
Mars 2016
Swift 2.2
Swift c’est cool…
…utilisé dans de vrais projets !
Swift : Nouvelles du front#Xebia #DevoxxFR
TOC
Nos cas d’usage
Flux d’activitéCréation du projet et configuration
Produits et synchronisationLanguesCommentairesTesting
Suivre son applicationEt l’Objective-C ?
Création du projet
Swift : Nouvelles du front#Xebia #DevoxxFR
Les dépendances
Librairies dynamiques
Swift : Nouvelles du front#Xebia #DevoxxFRSlide Title
Title
Au revoir iOS 7
Swift : Nouvelles du front#Xebia #DevoxxFR
Les dépendances
Flux d’activités
Swift : Nouvelles du front#Xebia #DevoxxFR
Photos et vidéos
Fluidité
Des milliers de posts
Flux d’activités
Swift : Nouvelles du front#Xebia #DevoxxFRFlux 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
Swift : Nouvelles du front#Xebia #DevoxxFRFlux 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ésExemple de Struct
Swift : Nouvelles du front#Xebia #DevoxxFRFlux d’activités
Struct : Performances
Avec une méthode de shuffle sur 1.000.000 d’objets
Seco
ndes
0
0,325
0,65
0,975
1,3
NSObject Struct
0,064
1,152
Swift : Nouvelles du front#Xebia #DevoxxFRFlux d’activités
Struct VS Classes
Ne peut pas hériter d’objets
Pas de deinitializer
Référence unique d’une instance
Swift : Nouvelles du front#Xebia #DevoxxFRFlux 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 }
Swift : Nouvelles du front#Xebia #DevoxxFRFlux d’activités
Unbox
Conversion automatique
Génère des structs
Performances accrues
Swift : Nouvelles du front#Xebia #DevoxxFRFlux d’activités
Unbox par l’exemple
func buildUser(userData:[String: AnyObject]) -‐> User? { let user: User = Unbox(userData) ... return user }
Swift : Nouvelles du front#Xebia #DevoxxFRFlux d’activités
Performances
StructHéritage Rendu
Configurations
Swift : Nouvelles du front#Xebia #DevoxxFR
Analytics
Endpoints
Regroupement
Configurations
Profil
Swift : Nouvelles du front#Xebia #DevoxxFRConfigurations
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
Liste de produits
Swift : Nouvelles du front#Xebia #DevoxxFR
600.000+ lignes
Requêtes rapides
Liste de produits
Swift : Nouvelles du front#Xebia #DevoxxFRListe de produits
Stockage : Objective-C@implementation XBEntityStore
-‐ (void)addEntity:(id<XBEntity>)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]; }
Swift : Nouvelles du front#Xebia #DevoxxFRListe de produits
Stockage : Objective-C@implementation XBEntityStore
-‐ (void)addEntity:(id<XBEntity>)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]; }
Swift : Nouvelles du front#Xebia #DevoxxFRListe de produits
Generics
class EntityStore<T: Entity> { func addEntity(entity: T) { // Some implementation } }
...
func addSomeObjects() { let productStore = EntityStore<Product>() // 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>() // Product conforms to Entity let product = Product() productStore.addEntity(product) // Color conforms to Entity let color = Color() productStore.addEntity(color) }
Un peu de Swift
Swift : Nouvelles du front#Xebia #DevoxxFRListe de produits
Generics
Écrire du code facilement réutilisable
et sujet à des contraintes spécifiques
Swift : Nouvelles du front#Xebia #DevoxxFRListe de produits
TypeAlias
typealias ProductStore = EntityStore<Product>
func addSomeObjects() { let productStore = ProductStore() // ... }
Code plus expressif
Swift : Nouvelles du front#Xebia #DevoxxFRListe de produits
Protocols
Swift est un “langage orienté protocoles”Apple, 2015
protocol Loadable { static func load(id: String) -‐> Self? }
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
Swift : Nouvelles du front#Xebia #DevoxxFRListe 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 } }
Swift : Nouvelles du front#Xebia #DevoxxFRListe 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 } }
Swift : Nouvelles du front#Xebia #DevoxxFRListe 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 { /* ... */ }
Synchronisation
Swift : Nouvelles du front#Xebia #DevoxxFR
Synchronisation etmanipulation500 Mo de données
Performances
Synchronisation
Swift : Nouvelles du front#Xebia #DevoxxFRSynchronisation
Performances
déclarations final et static
Profiter pleinement du runtime de Swift
Swift : Nouvelles du front#Xebia #DevoxxFRSynchronisation
Performances
Attention aux casts entre Array ↔ NSArray
Dictionary ↔ NSDictionary
Tâches asynchrones
Swift : Nouvelles du front#Xebia #DevoxxFR
Librairie locale
Tâches asynchrones
Ecran personnalisé
Animation diaphragme
Appareil photo
Swift : Nouvelles du front#Xebia #DevoxxFRTâches asynchrones
Closure
Equivalent des blocks en Objective-C
Comprend un bloc de code à exécuter
Définition : { () -‐> () in }
Swift : Nouvelles du front#Xebia #DevoxxFRTâches asynchrones
Exemple de closure
self.closeDiaphragm { _ in self.openDiaphragm() }
Swift : Nouvelles du front#Xebia #DevoxxFRTâ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?
Swift : Nouvelles du front#Xebia #DevoxxFRTâches asynchrones
Exemple d’optionals
func setup(image:UIImage?) { guard let menuIcon = image else { return } let menuImageView = UIImageView(image: menuIcon) self.addSubview(menuImageView) }
Swift : Nouvelles du front#Xebia #DevoxxFRTâches asynchrones
Optionals : fiabilité !
Source : DevFee (Developers feeling)
Swift : Nouvelles du front#Xebia #DevoxxFR
Appels asynchrones
Tâches asynchrones
Sur n’importe quel post
Gestion des retours serveur
Poster un commentaire
Swift : Nouvelles du front#Xebia #DevoxxFRTâches asynchrones
Promise
Code plus lisible
Idéal pour les tâches asynchrones
Chaînage possible
Swift : Nouvelles du front#Xebia #DevoxxFRTâ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() }
Swift : Nouvelles du front#Xebia #DevoxxFRTâ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() } } }
Swift : Nouvelles du front#Xebia #DevoxxFR
SwiftTasks
Une des librairies principales
Mise en place simple…
…mais des erreurs dans Xcode
Swift : Nouvelles du front#Xebia #DevoxxFRTâ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 }
Disponibilité produit
Swift : Nouvelles du front#Xebia #DevoxxFR
Simple requête HTTP
Mise à jour de la UI
Disponibilité produit
Swift : Nouvelles du front#Xebia #DevoxxFRDisponibilité produit
Les étapes
Récupération
Déserialisation
UI
Swift : Nouvelles du front#Xebia #DevoxxFRDisponibilité produit
Functional Reactive Programming
Propagation de messages
Asynchronisme
Robustesse
Swift : Nouvelles du front#Xebia #DevoxxFRDisponibilité produit
Functional Reactive Programming
^{ available in guard let available = available as? Bool else { return } availabilitySpinner.stopAnimating() availabilityIndicator.textColor = colorForStatus(available) } <~ KVO.stream(viewModel, "status")
Swift : Nouvelles du front#Xebia #DevoxxFR
ReactiveCocoa
github.com/ReactiveCocoa/
Disponibilité produit
Swift : Nouvelles du front#Xebia #DevoxxFR
ReactKit
github.com/ReactKit/
Disponibilité produit
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
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
Swift : Nouvelles du front#Xebia #DevoxxFRDisponibilité produit
Opérateurs Custom^{ available in guard let available = available as? Bool else { return } availabilitySpinner.stopAnimating() availabilityIndicator.textColor = colorForStatus(available) } <~ KVO.stream(viewModel, "status")<~
Swift : Nouvelles du front#Xebia #DevoxxFRSlide Title
Title
Internationalisation
Swift : Nouvelles du front#Xebia #DevoxxFR
Changement de la langue
Traduction des contenus
Traduction de l’IHM
Internationalisation
Swift : Nouvelles du front#Xebia #DevoxxFRInternationalisation
Enumsenum Country {
case USA case China case Italy
}
Et finalement du Swift
Swift : Nouvelles du front#Xebia #DevoxxFRInternationalisation
Enumsenum Country {
case USA case China case Italy
static var preferred: Country { return Country.Italy }
}
Country.preferred // .Italy
Et finalement du Swift
Valeurs associées
Swift : Nouvelles du front#Xebia #DevoxxFRInternationalisation
Enumsenum 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
Swift : Nouvelles du front#Xebia #DevoxxFRInternationalisation
Switchenum Language {
case English case Italian // ...
var language: String { switch self { // ... } } }
Swift
Swift : Nouvelles du front#Xebia #DevoxxFRInternationalisation
Switchenum 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
Swift : Nouvelles du front#Xebia #DevoxxFRInternationalisation
Enums : it’s over 9000!!!
First-Class types
Méthodes et propriétés
Vérifiés à la compilation
Valeurs associées
Tests
Swift : Nouvelles du front#Xebia #DevoxxFR
Assurer le fonctionnementde l’application
Se protéger des régressions
Tests
Swift : Nouvelles du front#Xebia #DevoxxFRTests
Chargement des produits
Product.load("A00")
Comment tester ?
Swift : Nouvelles du front#Xebia #DevoxxFRSlide 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 } }
Swift : Nouvelles du front#Xebia #DevoxxFRSlide 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 } }
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")
Swift : Nouvelles du front#Xebia #DevoxxFRListe de produits
Swift VS Swiftclass Store { func addEntity(entity: Product) { // Some implementation } }
let entityStore = EntityStore() let product = Product() entityStore.addEntity(product)
Coder Swift != Penser Swift
class Store<T: Entity> { func addEntity(entity: T) { // Some implementation } }
let productStore = ProductStore() let product = Product() product.save(productStore)
Generics
Typealias
Protocol extensions
Swift : Nouvelles du front#Xebia #DevoxxFRSlide Title
Title
#DevoxxFRSwift : Nouvelles du front
Swift : Nouvelles du front#Xebia #DevoxxFRSlide Title
Title
#DevoxxFRSwift : Nouvelles du front
Swift : Nouvelles du front#Xebia #DevoxxFRTests
Mais aussi…
Swift : Nouvelles du front#Xebia #DevoxxFRFlux d’activités
Flux d’activitésCrash
Swift : Nouvelles du front#Xebia #DevoxxFRTests
Mais aussi…
Swift : Nouvelles du front#Xebia #DevoxxFRTests
Mais aussi…
Suivre son application
Swift : Nouvelles du front#Xebia #DevoxxFRSuivre son application
Fabric
Déploiement centralisé et versionné
Remontées de crashs
Statistiques d’utilisation
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
Swift : Nouvelles du front#Xebia #DevoxxFR
Fabric - Swift
WSClient.swift line 31 static MyLittlePony.WSClient.requestContent (MyLittlePony.WSClient.Type) parameters : Swift.Optional <Swift.Dictionary <Swift.String, Swift.AnyObject>
Crashed: com.apple.main-‐thread SIGABRT ABORT at 0x312a8df0
Suivre son application
Swift : Nouvelles du front#Xebia #DevoxxFRSuivre son application
Pourquoi ?
Évolution du langage constante
Rétrocompatibilité non assurée
Et l’Objective-C ?
Swift : Nouvelles du front#Xebia #DevoxxFR
Et l’Objective-C dans tout ça ?
Toujours valable
Mais développement plus lent
Migration progressive conseillée
Swift : Nouvelles du front#Xebia #DevoxxFR
Popu
larit
é de
s re
cher
ches
2014 2015 2016Objective-C Swift Objective-C Swift Objective-C Swift
Source : TIOBE
3 ème
19 ème
14 ème
15 ème 15 ème
14 ème
Et l’Objective-C dans tout ça ?
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 !
Swift : Nouvelles du front#Xebia #DevoxxFR
One more thing…
23-24 septembre
frenchkit.frBillets en vente dès aujourd’hui
CocoaHeads Paris
Rejoignez-nous [email protected]
blog.xebia.fr
Swift : Nouvelles du front#Xebia #DevoxxFR
Un peu de lecture
A Swift KickstartDaniel Steinberg
Functional Programming in SwiftChris Eidhof, Florian Kugler, and Wouter Swierstra
http://blog.xebia.fr/tag/swiftL’équipe iOS Xebia
Advanced SwiftChris Eidhof and Airspeed Velocity