Devoxx France - Nouvelles du Front

Post on 09-Jan-2017

213 views 5 download

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 !recrutement@xebia.fr

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