2015-11-02 2 views
1

Le code suivant fonctionne parfaitement bien, mais je suis surpris, car je pensais que NSCache nécessiterait des valeurs d'objets clés &, et ne prendrait pas CGFloat s. Quelqu'un peut-il m'expliquer ce qui se passe?Comportement NSCache avec les types de non-objet

class A 
    var cachedPoints = NSCache() 

    func rAt(theta theta: CGFloat) -> CGFloat {   
     if let r = self.cachedPoints.objectForKey(theta) as? CGFloat { 
      return r 
     } 
     // do some very expensive maths here... 
     let r = self.veryExpensiveFunction(theta) 
     self.cachedPoints.setObject(r, forKey: theta) 
     return r 
    } 
} 
+0

Vous mentionnez CGPoint dans la question, mais cela n'apparaît pas dans le code. Voulez-vous dire CGFloat? –

+0

Oups, oui. Éditera. – Grimxn

Répondre

2

De Working with Cocoa Data Types dans le "Utilisation de Swift avec Cocoa et Objective-C" Documentation:

Nombres

Swift ponts automatiquement certains types de numéros natifs, tels que Int et Float, à NSNumber.
...
Il vous permet également de transmettre une valeur de type Int, par exemple, à un argument qui attend un NSNumber.

La documentation mentionne Int, UInt, Float, Double, Bool que les types qui sont automatiquement pontés NSNumber, mais apparemment cela fonctionne pour CGFloat aussi bien (si importé "Fondation"). Ainsi, dans

self.cachedPoints.setObject(r, forKey: theta) 

à la fois r et theta sont enveloppées dans NSNumber cas , puis transmis à la méthode setObject() qui prend deux paramètres de type AnyObject.

Il y a aussi un pont dans le sens inverse, mais c'est moins bien documenté (ou je ne pouvais pas le trouver). Vous pouvez lancer une instance de NSNumber-CGFloat (ou Int, Float, ...)

let num : NSNumber = ... 
let x = num as CGFloat 

et le résultat est le même que si vous avez appelé doubleValue (ou floatValue, en fonction de l'architecture) sur le nombre exemple. Dans

let obj : AnyObject = ... 
let y = obj as? CGFloat // CGFloat? 

l'objet est éventuellement coulé à NSNumber et - si cela était réussie - converti en CGFloat comme dans l'exemple précédent.

Et c'est ce qui se passe dans

if let r = self.cachedPoints.objectForKey(theta) as? CGFloat { ... } 

Si la valeur de retour de objectForKey() est un NSNumber alors il est converti en CGFloat et affecté à r. Sinon, la liaison facultative échoue.

+0

Merci beaucoup!J'avais initialement utilisé NSNumber, mais il semblait si maladroit comparé à l'utilisation de 'Dictionary' que j'ai juste décidé d'essayer. On dirait que j'ai besoin de relire les livres à nouveau! – Grimxn