Au cours de "Swift dans la vraie vie" vous assisterez à un retour d'expérience concernant l'utilisation du dernier langage d'Apple - maintenant Open Source - dans deux projets mobiles utilisés en production par quelques milliers d'utilisateurs.
À travers une analyse des points de force et faiblesse de ce langage, vous comprendrez pourquoi il n'est pas trop osé de commencer tout de suite à développer votre prochaine application iOS en Swift.
Par Simone Civetta et Fabien Mirault, consultants chez Xebia
La vidéo de la conférence est à retrouver sur : http://www.xebicon.fr/programme.html
2. #XebiConFr
Swift dans la vraie vie
Fabien Mirault
Développeur Objective-C / Swift
Speakers
@viteinfinite
Simone Civetta
Développeur Objective-C / Swift
@magici1
4. #XebiConFr
Swift dans la vraie vie
Septembre 2014
Octobre 2014
Novembre 2014
Juin 2014
Apple annonce Swift
!
Swift 1.0
!
Première application Swift
Xebia sur l’App Store
Swift 1.1
?
Janvier 2015
Nouvelles applications ?
Swift ou pas ?
6. #XebiConFr
Swift dans la vraie vie
Nouveau langage de développement
Code plus lisible et moins verbeux
Donc plus simple à maintenir !
Qu’est-ce que Swift ?
7. #XebiConFr
Swift dans la vraie vie
Qu’est-ce que Swift ?
Transition Objective-C → Swift aisée
Moins de tolérance sur les erreurs de code
Rapidité de développement accrue
9. #XebiConFr
Swift dans la vraie vie
Septembre 2014
Octobre 2014
Novembre 2014
Juin 2014
Apple annonce Swift
!
Swift 1.0
!
Première application Xebia
sur l’App Store
Swift 1.1
?
Janvier 2015
Nouvelles applications !
!
Swift ou pas ?
11. #XebiConFr
Swift dans la vraie vie
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 ?
17. #XebiConFr
Swift dans la vraie vie
Photos et vidéos
Fluidité
Des milliers de posts
Flux d’activités
18. #XebiConFr
Swift dans la vraie vie
Ne contient que ce qui a été défini
Meilleures performances
Stockage de type valeur et non référence
Struct
Flux d’activités
19. #XebiConFr
Swift dans la vraie vie
Flux d’activités
Exemple de Struct
public struct Attachment {
public let id: Int
public let url: String
public let type: String
public let name: String
public let objectId: Int
public let mimeType: String
public let objectType: String
}
Flux d’activités
20. #XebiConFr
Swift dans la vraie vie
Struct : Performances
Flux d’activités
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
21. #XebiConFr
Swift dans la vraie vie
Flux d’activités
Struct VS Classes
Ne peut pas hériter d’objets
Pas de deinitializer
Référence unique d’une instance
22. #XebiConFr
Swift dans la vraie vie
Mapping automatique
Génère des structs
Performances accrues
JSONJoy
Flux d’activités
23. #XebiConFr
Swift dans la vraie vie
Flux d’activités
JSONJoy par l’exemple
private static func buildUser(userData:[String: AnyObject]) -> User? {
...
let user = User(JSONDecoder(userData))
return user
}
28. #XebiConFr
Swift dans la vraie vie
Configurations
struct Tags {
struct Page {
static let Login = "Login"
static let Camera = "Camera"
static let Newsfeed = "Newsfeed"
static let Favorites = "Favorites"
static let MyProfile = "MyProfile"
static let OtherProfile = "OtherProfile"
static let LiveSessions = "LiveSessions"
static let CreateAccount = "CreateAccount"
static let ForgottenPassword = "ForgottenPassword"
}
}
Configurations
31. #XebiConFr
Swift dans la vraie vie
Liste de produits
@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];
}
Stockage : Objective-C
32. #XebiConFr
Swift dans la vraie vie
- (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];
}
32
Liste de produits
Stockage : Objective-C
@implementation XBEntityStore
- (void)addEntity:(id<XBEntity>)entity {
// Some implementation
}
@end
...
Un peu d’Objective-C
33. #XebiConFr
Swift dans la vraie vie
33
Liste 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)
}
Un peu de Swift
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) // Ne compile pas !
}
34. #XebiConFr
Swift dans la vraie vie
34
Liste de produits
Generics
Écrire du code facilement réutilisable
et sujet à des contraintes spécifiques
35. #XebiConFr
Swift dans la vraie vie
35
Liste de produits
TypeAlias
typealias ProductStore = EntityStore<Product>
func addSomeObjects() {
let productStore = ProductStore()
// Product conforms to Entity
let product = Product()
productStore.addEntity(product)
}
typealias ColorStore = EntityStore<Color>
func addSomeObjects() {
let colorStore = ColorStore()
// Color conforms to Entity
let color = Color()
colorStore.addEntity(product)
}
Code plus expressif
36. #XebiConFr
Swift dans la vraie vie
36
Liste de produits
Protocols
Swift est un “langage orienté protocoles”
Apple, 2015
protocol Entity { }
class EntityStore<T: Entity> {
func addEntity(entity: T) {
// Some implementation
}
}
37. #XebiConFr
Swift dans la vraie vie
37
Liste de produits
Swift VS Swift
class EntityStore {
func addEntity(entity: Entity) {
// Some implementation
}
}
func addSomeObjects() {
let productStore = EntityStore()
let product = Product()
productStore.addEntity(product)
}
Coder Swift != Penser Swift
class EntityStore<T: Entity> {
func addEntity(entity: T) {
// Some implementation
}
}
func addSomeObjects() {
let productStore = ProductStore()
let product = Product()
productStore.addEntity(product)
}
Generics
Typealias
43. #XebiConFr
Swift dans la vraie vie
Librairie locale
Appareil photo
Ecran personnalisé
Animation diaphragme
Tâches asynchrones
44. #XebiConFr
Swift dans la vraie vie
Tâches asynchrones
Equivalent des blocks en Objective-C
Comprend un bloc de code à exécuter
Définition : {
()
-‐>
()
in
}
Closure
45. #XebiConFr
Swift dans la vraie vie
Tâches asynchrones
Exemple de closure
self.closeDiaphragm(duration:0.3, completionBlock: { finished in
self.openDiaphragm(duration:0.3)
})
46. #XebiConFr
Swift dans la vraie vie
Tâches asynchrones
Optional
Possède une valeur ou non
Sécurise le code
Tester la non nullité : if
let
Définition : var
delegate:CameraDelegate?
47. #XebiConFr
Swift dans la vraie vie
Tâches asynchrones
Exemple d’optionals
func setup(image:UIImage?) {
if let menuIcon = image {
let menuImageView = UIImageView(image: menuIcon)
self.addSubview(menuImageView)
}
}
49. #XebiConFr
Swift dans la vraie vie
Appels asynchrones
Poster un commentaire
Sur n’importe quel post
Gestion des retours serveur
Tâches asynchrones
50. #XebiConFr
Swift dans la vraie vie
Tâches asynchrones
Promise
Code plus lisible
Idéal pour les tâches asynchrones
Chaînage possible
51. #XebiConFr
Swift dans la vraie vie
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()
}
52. #XebiConFr
Swift dans la vraie vie
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()
}
}
}
53. #XebiConFr
Swift dans la vraie vie
SwiftTasks
Librairie principale
Mise en place simple…
…mais des erreurs dans Xcode
54. #XebiConFr
Swift dans la vraie vie
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
}
56. #XebiConFr
Swift dans la vraie vie
Disponibilité produit
Simple requête HTTP!
Mise à jour de la UI!
57. #XebiConFr
Swift dans la vraie vie
Disponibilité produit
Alamofire
Alamofire.request(URLRequest)
.validate()
.response { (request, response, data, error) in
print(request)
print(response)
print(data)
print(error)
}
58. #XebiConFr
Swift dans la vraie vie
Disponibilité produit
Les étapes
WebService
Déserialisation
UI
59. #XebiConFr
Swift dans la vraie vie
59
Disponibilité produit
Functional Reactive Programming
Propagation des changements
Flux de données
Asynchronisme
62. #XebiConFr
Swift dans la vraie vie
Disponibilité produit
Functional Reactive Programming
^{
let available = $0 as! Bool
self.availabilitySpinner.stopAnimating()
self.availabilityIndicator.textColor = self.colorForStatus(available)
} <~ KVO.signal(viewModel, "status")
63. #XebiConFr
Swift dans la vraie vie
[[[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];
Disponibilité produit
FRP - Objective-C
64. #XebiConFr
Swift dans la vraie vie
Disponibilité produit
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)
65. #XebiConFr
Swift dans la vraie vie
Disponibilité produit
Opérateurs Custom
^{
self.availabilitySpinner.stopAnimating()
self.availabilityIndicator.textColor = self.colorForStatus($0)
} <~ availabilitySignal<~
68. #XebiConFr
Swift dans la vraie vie
Internationalisation
Changement de la langue!
Traduction des contenus!
Traduction de l’IHM!
69. #XebiConFr
Swift dans la vraie vie
Internationalisation
self.headerLabel.text = NSLocalizedString("Header.Title", comment: "Header Title")
extension UILabel {
var localizedText: String {
set {
self.text = NSLocalizedString(newValue, comment: newValue)
}
/* ... */
}
}
self.headerLabel.localizedText = "Header.Title"
Extensions
70. #XebiConFr
Swift dans la vraie vie
70
Internationalisation
Enums
typedef enum : NSUInteger {
XBCountryUSA,
XBCountryChina,
XBCountryItaly
} XBCountry;
Un peu d’Objective-C
71. #XebiConFr
Swift dans la vraie vie
71
Internationalisation
Enums
enum Country: String {
case USA = "US"
case China = "CN"
case Italy = "IT"
}
Et finalement du Swift
Valeurs associées
72. #XebiConFr
Swift dans la vraie vie
72
Internationalisation
Enums
enum Country: String {
case USA = "US"
case China = "CN"
case Italy = "IT"
static var defaultCountry: Country {
return Country.Italy
}
}
Country.defaultCountry
Et finalement du Swift
Valeurs associées
Propriétés
73. #XebiConFr
Swift dans la vraie vie
73
Internationalisation
Switch
enum Language {
case English(region: String)
case Italian
var name: String {
switch self {
case .English(let region):
return "English " + region
case .Italian:
return "Italian"
}
}
}
Swift
74. #XebiConFr
Swift dans la vraie vie
74
Internationalisation
Switch
enum Language {
case English(region: String)
case Italian
var name: String {
switch self {
case .English(let region):
return "English " + region
case .Italian:
return "Italian"
}
}
}
Swift
Pattern matching
75. #XebiConFr
Swift dans la vraie vie
enum Language {
case English(region: String)
case Italian
var name: String {
switch self {
case .English(let region)
where region == "US":
return "English Default”
case .English(let region):
return "English " + region
case .Italian:
return "Italian"
}
}
75
Internationalisation
Switch
Swift
Pattern matching
Switch exhaustif
76. #XebiConFr
Swift dans la vraie vie
Internationalisation
Enums : it’s over 9000!!
First-Class citizens
Méthodes et propriétés
Valeurs associées
86. #XebiConFr
Swift dans la vraie vie
Suivre son application
Déploiement centralisé et versionné
Remontées de crashs
Statistiques d’utilisation
Fabric
87. #XebiConFr
Swift dans la vraie vie
Suivre son application
Fabric - Objective-C
RTSViewController.m line 1310
-[RTSViewController getCurrentUDPValues]
Fatal Exception: NSRangeException
*** -[__NSArrayM objectAtIndex:]
index 4294967292 beyond bounds [0 .. 511]
88. #XebiConFr
Swift dans la vraie vie
Suivre son application
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
89. #XebiConFr
Swift dans la vraie vie
Suivre son application
Reveal
Vue éclatée
Fonctionne sur simulateur ou device
Édition à la volée des propriétés
93. #XebiConFr
Swift dans la vraie vie
Toujours valable
Mais développement plus lent
Migration progressive conseillée
Et l’Objective-C dans tout ça ?
94. #XebiConFr
Swift dans la vraie vie
Popularitédesrecherches
2014 2015
Objective-C Swift Objective-C Swift
Source : TIOBE
3 ème
19 ème
14 ème
15 ème
Et l’Objective-C dans tout ça ?
95. #XebiConFr
Swift dans la vraie vieNouveaux Repositories entre Q3 et Q4 2014
Swift Objective-C
97
3757
Source : http://githut.info
Et l’Objective-C dans tout ça ?
96. #XebiConFr
Swift dans la vraie vie
Les avantages de Swift
Plus facile à maintenir et plus robuste
Demande moins de code
Soyez acteur des évolutions d’Apple !
98. #XebiConFr
Swift dans la vraie vie
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