Quand utiliser un type swift ou Foundation ?

muqaddarmuqaddar Administrateur
juin 2014 modifié dans Objective-C, Swift, C, C++ #1

Je viens de lire que, par exemple, les strings et arrays en Swift sont bridgés avec leurs homologues Cocoa si on appelle des méthodes Foundation dessus.


 


Ainsi on peut appeler capitalizedString sur une bête string swift... On n'a pas à  convertir la string en NSString auparavant.


 


To enable string bridging, just import Foundation. For example, you can call capitalizedString"a method on the NSString class"on a Swift string, and Swift automatically bridges the Swift String to an NSStringobject and calls the method. The method even returns a Swift String type, because it was converted during import.

 


Idem pour les arrays.


Donc, j'ai l'impression que ça va être plus délicat de savoir quand utiliser NSArray ou [] selon les cas puisque les méthodes de Foundation sont accessibles "à  la volée" ?


 


Et quid des performances ?


J'ai toujours lu que les tableaux en C étaient bien plus rapide que leurs homologues Cocoa. Et maintenant ? Quels sont les choix à  faire ? Est-ce que le fait qu'il soient bridgés est gourmand en ressources ? Faut-il toujours utiliser un tableau swift en priorité si on n'a pas de méthodes de NSArray à  appeler dessus ?


Réponses

  • AliGatorAliGator Membre, Modérateur
    Les tableaux Swift sont logiquement plus rapides car ce sont des Generics optimisés par le compilateur selon le type des éléments qu'ils vont contenir. ça fait tout plein de tests en moins à  faire au Runtime. Swift powaaaa
  • muqaddarmuqaddar Administrateur


    Les tableaux Swift sont logiquement plus rapides car ce sont des Generics optimisés par le compilateur selon le type des éléments qu'ils vont contenir. ça fait tout plein de tests en moins à  faire au Runtime. Swift powaaaa




     


    Donc l'option tableau swift + for..in est à  préférer à  NSArray + NSEnumerator.


     


    D'après ce que j'ai compris, si on applique une méthode de NSArray sur un [], le bridge n'est que momentané ? La méthode renvoie bien un tableau swift quand-même, qu'on pourrait donc passer dans une boucle, même s'il a été "bridgé" en NSArray à  un instant T auparavant ?

  • AliGatorAliGator Membre, Modérateur
    Je pense, oui, un peu comme quand tu bridge-castes ces NSString en CFStringRef juste le temps de les passer en paramètre à  une méthode de CoreFoundation pour passer d'Objective-C à  du C. C'est un cast temporaire qui ne modifie pas l'objet lui-même, mais ne fait que l'interpréter comme un objet d'un autre type. Enfin bref, un cast, quoi !
  • muqaddarmuqaddar Administrateur

    OK merci.


     


    Il y a tant de choses à  savoir avant de convertir des classes, non pas que ça ne marcherait pas, mais pour essayer d'adopter les meilleurs "concepts" !


  • AliGatorAliGator Membre, Modérateur
    Oui après c'est sûr que je ne sais pas comment les APIs vont évoluer pour profiter de Swift tout en étant toujours compatible ObjC.

    Je veux dire, le bridging fait des choses assez magiques. Si dans le Playground on tape "NSString" et qu'on fait un Pomme-clic dessus, on arrive dans le header de NSStringà· traduit à  la volée par LLVM en une API Swift. Comme si NSString avait été réécrit en Swift (alors qu'Apple explique bien dans ses sessions que c'est juste traduit à  la volée). Ce qui permet entre autres de voir les conversions de nommage qu'il fait en jartant les "With" et répartissant les arguments nommés ("-(id)initWithFormat:(NSString*)]" de NSString en ObjC devient "init(format: String)" en Swift par exemple).

    Mais si on garde nos frameworks tierces (AFNetworking, FMDatabase, MagicalRecord, ...) en ObjC, on ne profitera pas des petits + de Swift.
    - Par exemple, une fonction qui retourne un NSString* en Objective-C retournera toujours un "String!" en Swift (implicitly unwrapped optional) pour indiquer une String qui peut être nil (puisqu'en Obj-C les NSString étant des NSObject peuvent être nil) mais qui n'a pas à  être unwrappée.
    - Ou encore la méthode "-rangeOfString:" de NSString retournera toujours un Int!, qui j'imagine vaudra toujours la valeur équivalente à  NSNotFound si la chaà®ne n'est pas trouvée (puisqu'ils n'ont pas changé l'implémentation de la méthode pour autant j'imagine) alors qu'en Swift on retournerait plutôt nil pour indiquer une valeur manquante (chose qu'on ne peut pas faire en ObjC pour un Int)
    - Ou encore une méthode qui prendrait un NSArray en argument sous ObjC serait traduite en une API Swift qui prend un "AnyObject[]!" soit un tableau de "on sait pas quoi" " encapsulé dans un "implicitly unwrapped optional" encore une fois car ce NSArray peut être nil en ObjC. Alors qu'en Swift on aurait certainement un type plus spécifique genre "String[]?"


    Bref c'est bien qu'il y ait le bridging ObjC -> Swift, mais comme ObjC n'a pas les Generics (avec les tableaux spécialisés, etc) ni les optionals pour les types Int, ni la possibilité d'indiquer si une méthode peut retourner nil ou retournera toujours un non-nil..., ces informations ne pourront pas transparaà®tre dans l'API traduite en Swift. "rangeOfString:" retournera toujours NSNotFound s'il ne trouve pas la chaà®ne. On devra typecaster les objets extraits d'un NSArray pour les utiliser, bref comme en ObjC.

    Alors que si on porte nos APIs en Swift, on pourra rajouter toutes ces précisions dans nos APIs. On pourra faire des fonctions qui prennent spécifiquement des Int[] et pas des NSArray* contenant on ne sait pas trop quoi au juste, ou des fonctions qui retournent des "Int?". Tant qu'on ne portera pas nos APIs en Swift, on ne profitera pas de toute la richesse que Swift peut nous apporter dans sa possibilité de spécification plus fine du langage.
  • muqaddarmuqaddar Administrateur

    Merci pour ces précisions.


     


    A terme, je pense que dans nos nouvelles classes Swift, on devrait beaucoup moins utiliser Foundation. Quand on voit la facilité avec laquelle ont peut modifier des tableaux en Swift, ça donne pas envie d'utiliser les méthodes "longues" d'obj-C qui faisaient ça avant.


Connectez-vous ou Inscrivez-vous pour répondre.