2017-09-26 3 views
1

Quelqu'un peut-il expliquer la meilleure meilleure façon de comprendre les types Int, puisque Swift 4 J'ai tant de problèmes avec JSON à cause de cettesystème bizarre de type Swift 4

enter image description here

cause de cela est la situation si courante lorsque J'essaie de la carte même objet JSON à des entités de données de base et PONSOs

donc,

id: Int = json["id"] as? Int // works 
id: Int32 = json["id"] as? Int32 // doesn't work 

par conséquent, je suis incapable de satisfaire à la fois exigences en même temps. Puis-je de toute façon éviter cette situation int absolument insensée dans Swift 4?

+1

Si vous avez des problèmes de JSON spécifiques, s'il vous plaît montrer le JSON et le code utilisons pour l'analyser. – Sulthan

+1

Le code ci-dessus ne montre rien concernant JSON. '[String: Any]' est "un dictionnaire de String pour absolument tout type de données qui peut être exprimé dans Swift."Ceci est souvent mal utilisé pour JSON, mais l'analyse de JSON avec NSJSONSerialization ne devrait jamais générer le dictionnaire que vous avez donné ici.Sans rien ci-dessus est" insensé ", il semble suivre exactement les règles, il peut donc être utile d'expliquer le problème JSON n'a pas de type entier 32 bits ou 64 bits –

+0

Notez que Int de Swift correspond à NSInteger de ObjC, et (comme dans ObjC) est le type recommandé pour presque toutes les choses "entières" dans Swift Les largeurs de bits spécifiques sont fortement déconseillées, sauf si elles sont requises pour des interactions de bas niveau ou pour garantir de très grands entiers sur une plate-forme 32 bits.Ils ne sont pas conçus pour être utilisés en général dans Swift. Vous voulez être averti lorsque vous ne respectez pas les exigences de taille. –

Répondre

5

La raison de cette confusion est que as? a deux significations complètement orthogonales dans Swift, selon le contexte. Lorsque vous traitez avec des types purement Swift, as? est une distribution dynamique qui retourne nil non seulement si le type est littéralement une instance du type sur le côté droit de l'opérateur as?:

import Foundation 

let dict: [String : Any] = ["Foo" : 3 as Int] 

print(dict["Foo"] as? Int) 
print(dict["Foo"] as? Int32) 
print(dict["Foo"] as? Int64) 

Ce retourne Optional(3) pour la premier journal, et nil pour les deux autres, car le type est un Int et non un Int32 ou un Int64.

Cependant, lorsque le type de l'élément en cours de coulée est un de type Objective-C, alors as? n'est plus une distribution dynamique stricte, mais provoque plutôt pont comportement:

import Foundation 

let dict: [String : Any] = ["Foo" : 3 as NSNumber] 

print(dict["Foo"] as? Int) 
print(dict["Foo"] as? Int32) 
print(dict["Foo"] as? Int64) 

Ce rendement Optional(3) pour les trois journaux, car il ne s'agit plus d'une distribution dynamique. En effet, une instance NSNumber ne fait partie d'aucun des trois types auxquels nous avons tenté de procéder. Au lieu de cela, as? provoque Swift à pont le type Objective-C, NSNumber, à un type Swift approprié si possible. Depuis que Swift a la logique pour combler NSNumber à Int, Int32, et Int64 (avec une foule d'autres types numériques), nous obtenons Optional(3) pour les trois journaux. Cependant, si vous tentez de lancer vers quelque chose comme Decimal pour lequel il n'y a pas de logique de pontage NSNumber, vous obtenez toujours nil.

Un intéressant effet secondaire de ceci est que as? ne suit pas la propriété transitive:

let foo: Int = 3 
print(foo as? NSNumber as? Int64) // Optional(3) 
print(foo as? Int64)    // nil 

Quoi qu'il en soit, si vous lancez vos valeurs NSNumber d'abord, vous devriez alors être en mesure de jeter de là à tout des types numériques que supporte le pont Objective-C, ce qui est probablement ce qui se passait sous le capot avec votre ancien code Swift 3. Par ailleurs, si vous connaissez réellement le type que la valeur est censée être, vous pouvez utiliser l'un des autres les initialiseurs de types entiers:

let dict: [String : Any] = ["Foo" : 3 as Int] 

let foo = (dict["Foo"] as? Int).map { Int32($0) }