[Swift]Conversion AnyObject? => UInt64
Draken
Membre
J'ai voulu récupérer une valeur stockée dans un AnyObject? et la convertir en UInt64, de cette manière (Swift 2.1 - Xcode 7.2.1) :
let test:AnyObject? = 1234
print ("Test : ", test)
if let valeur = test as? UInt64 {
print ("valeur : ", valeur)
} else {
print ("Pas de valeur !")
}
Cela ne fonctionne pas :
Test : Optional(1234)
Pas de valeur ..
J'ai dû passer par une syntaxe plus "rustique" pour y parvenir :
let test:AnyObject? = 1234
print ("Test : ", test)
if test != nil {
let v:UInt64 = test!.unsignedLongLongValue
print ("v : ", v)
}
Test : Optional(1234)
v : 1234
Quelqu'un sait-il pourquoi mon premier code est erroné ?
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
Après test, cela fonctionne avec UInit, mais pas UInt64 ou UInt32.
Après d'autres tests, on peut convertir un AnyObject? en Int ou UInt avec la syntaxe let var = var as? quelque chose.
Mais ne fonctionne pas avec Int32, Int64, UInt32, UInt64. Ou quelque chose m'échappe ..
J'ai pourtant vu des exemples de codes sur StackOverFlow convertissant des AnyObject? en UInt64. Soit les types ne testent pas les sources qu'ils tapent, soit il y a eu un changement dans Xcode.
A noter que l'utilisation de l'opérateur as! fonctionne très bien avec un AnyObject? => UInt
Et fait carrément planter l'application avec un UInt64 (normal, puisque le casting d'un AnyObject? en UInt64 retourne un nil).
Salut,
Tous ces types sont "bridged" automatiquement vers NSNumber : Int, UInt, Float, Double, Bool.
Par exemple on peut faire comme ça :
Par contre cette ligne ne compile pas, par ce que UInt64 n'est pas "bridged" vers NSNumber:
Donc to problème vient de la ( le fait que les types Int64, ... ne sont pas convertie automatiquement vers NSNUmber).
Ton code :
Cette ligne ne crée pas un Int pour le mettre dans AnyObject mais plutôt un NSNumber. C'est pour ça que la reconversion inverse ne marche pas. (ce que j'ai dit en haut)
Pourquoi Int64 par exemple ne supporte pas la convention automatique vers NSNumber ? Je ne sais pas vraiment , mais je pense qu'ils veulent mettre moins de conversions automatiques.
https://developer.apple.com/library/ios/documentation/Swift/Conceptual/BuildingCocoaApps/WorkingWithCocoaDataTypes.html#//apple_ref/doc/uid/TP40014216-CH6-XID_42
Un article intéressant sur le sujet (en anglais mais court) : http://blog.scottlogic.com/2014/09/24/swift-anyobject.html.
Je suis bien content d'avoir commencé swift sur Linux car, comme Foundation n'est pas encore complètement disponible, donc j'utilise principalement des types natifs de swift.
Or quand on utilise Foundation, on utilise parfois des types de Foundation sans vraiment s'en rendre compte, même si on n'utilise pas AnyObject.
Ce n'est pas très grave en soit, mais je pense que c'est bien de comprendre ce qui vient de Swift et ce qui vient de Foundation.
Merci de l'explication. A l'origine, je ne créais pas le AnyObject?. Je me suis inspiré d'un exemple de source Swift de SOF pour comprendre comment lire la taille d'un fichier disque en lisant son attribut NSFileSize (un AnyObject?). L'auteur le caste en UInt64, alors j'ai fait la même chose. Je présume qu'il n'a pas testé son code avant de le publier.
Sors de ce corps, Satan !
Le 10 Août c'est la fin pour toi .. (sortie de SOS Fantômes III au cinéma)
Ni UInt, ni UInt32, ni UInt64, ni Int, ni Int32, ni Int64 peuvent être trouvés dans un AnyObject (sauf dans un NSNumber) parce qu'ils sont tous les structs. On peut, cependant, les tenir dans un Any.
Si tu lisais les docs sur l'attribut NSFileSize, tu y trouverais que la valeur tenue est un String, pas un NSNumber.
Du coup, pour la convertir, il faudrait faire plus qu'un cast. Je suis d'accord avec toi que l'auteur avait tort.
Oki, merci nounours !
Au final j'ai fais comme ça :
EDIT : En relisant le code, je me rend compte que cela vas planter en testant la taille d'un fichier inexistant. Nouvelle version, avec un try? pour obtenir un fileAttr optional et éviter le crash.
Le mieux c'est de faire une fonction qui te propage une erreur en cas d'échec et non pas retourner 0.
Si la taille de ton fichier est égale 0 ( possible ?), tu considères que c'est ton URL qui n'est pas bonne, ... ?
Aussi, ne pas forcer tes optionnels (path!), il vaut mieux les "binder" ou utiliser un guard.
Après quelques expériences :
C'est utile les poneys. On fait de la colle avec les cadavres ..
Tu pourrais m'éclaircir ?
http://alisoftware.github.io/swift/2015/09/06/thinking-in-swift-1/
Je pense que cela m'était destiné. Traduction : "Arrête de tuer des poneys et vas lire mon blog Crunchy Développement".
Plutôt ça :
http://alisoftware.github.io/swift/2015/09/06/thinking-in-swift-1/
ou encore :
http://alisoftware.github.io/2015/12/17/let-it-throw/
C'est triste, à une époque on avait droit à une page d'explications compléte. Maintenant juste une référence sibylline que seuls les gens parlant le Ali peuvent comprendre.
MODERATION : Une bonne âme peut-elle séparer ce topic en deux parties ?
- [Swift] Conversion AnyObject? => UInt64
- Boucherie chevaline [Swift] Lecture de la taille d'un fichier avec gestion des erreurs
OK. Ayant relu ton article Ali, je voudrais te demander ou se trouvent ces fameux poneys ?
Ce, c'est garanti à réussir.
Ici, fileURL.path est simplement les composants de l'URL en String. ça peut échouer ?
Ici, j'utilise un do...catch pour attraper des soucis avec attributesOfItemAtPath; et fileURL.path est comme ci-dessus.
Je rate quelque chose d'autre ?
Petite variante de ma méthode, plus dans l'esprit Swift, retournant un Uint64?, afin d'avoir un nil en cas d'erreur. Ce n'est pas aussi complet que le code de Joanna, mais c'est toujours mieux qu'avant.
Est-ce que tu sais que tu puisses écrire encore moins de code que ça ?
Ou, encore moins que ça :
J'aime le minimalisme .. tant que cela ne nuit pas à la lisibilité du code. Là c'est parfait. Merci Nounours !
EDIT : Pourquoi ta première version cherche le fichier dans .DocumentDirectory et la seconde dans .PicturesDirectory ?
Quid de
C'est .. illisible !
T'as oublié les balises de code du forum ?
EDIT : c'est mieux comme ça.
L'instruction guard est bien sympathique.
Quand même ça marche bien