Je suis la recherche Swift numerics particulièrement maladroite lorsque, comme cela arrive souvent dans la vie réelle, j'ai pour communiquer avec Cocoa Touch à l'égard de CGRect et CGPoint (par exemple, parce que nous parlons de quelque chose de l' frame
ou bounds
).
CGFloat vs Double
Considérez les points suivants à l'air innocent de code à partir d'un UIViewController sous-classe:
let scale = 2.0
let r = self.view.bounds
var r2 = CGRect()
r2.size.width = r.size.width * scale
Ce code ne peut pas compiler, avec l'habituel mystérieux erreur sur la dernière ligne:
Ne pouvait pas trouver une surcharge pour les '*' qui accepte les arguments fournis
Cette erreur, je suis sûr que vous le savez maintenant, indique une sorte d'adaptation d'impédance entre les types. r.size.width
arrive comme un CGFloat, qui va échanger automatiquement avec une Swift Float, mais ne peut pas interagir avec une Swift variable Double (qui, par défaut, est-ce que scale
).
L'exemple est artificiellement bref, il y a donc un artificiellement la solution la plus simple, qui consiste à jeter scale
d'un Flotteur à partir de l'obtenir-aller. Mais lorsque le nombre de variables tirées de partout sont impliqués dans le calcul d'un projet de CGRect des éléments, il y a beaucoup de casting à faire.
Verbose Initialiseur
Un autre irritation est ce qui arrive quand vient le temps de créer un nouveau CGRect. En dépit de la documentation, il n'y a pas d'initialiseur avec des valeurs mais sans étiquette. Cela ne parvient pas à compiler, car nous avons des Doubles:
let d = 2.0
var r3 = CGRect(d, d, d, d)
Mais même si on jette d
à un Flotteur, nous n'avons pas à compiler:
Argument manquant étiquettes 'x:y:largeur:hauteur:" en appel
Nous avons donc fini par tomber en arrière sur CGRectMake
, ce qui n'est pas d'amélioration sur Objective-C. Et parfois CGRectMake et CGSizeMake sont pas d'amélioration. Considérer ce code réel de l'un de mes apps:
let kSEP : Float = 2.0
let intercellSpacing = CGSizeMake(kSEP, kSEP);
Dans un de mes projets, qui fonctionne. Dans l'autre, il échoue mystérieusement - exactement le même code! - avec cette erreur:
'NSNumber" n'est pas un sous-type de "CGFloat'
C'est comme si, parfois, Swift essaie de "traverser le pont" par coulée d'un Flotteur pour une NSNumber, ce qui bien sûr est la mauvaise chose à faire lorsque ce qui est de l'autre côté du pont, s'attend à un CGFloat. Je n'ai pas encore compris ce qu'est la différence entre les deux projets qui provoque l'erreur à apparaître dans l'un mais pas l'autre (peut-être quelqu'un d'autre).
NOTE: j'ai peut-être trouvé le problème: il semble dépendre de la construction Active Seulement l'Architecture paramètre de construction, qui à son tour suggère que c'est un 64 bits question. Ce qui est logique, puisque le Flotteur ne serait pas un match pour CGFloat sur un périphérique 64 bits. Cela signifie que la différence d'impédance problème est encore pire que je ne le pensais.
Conclusion
Je suis à la recherche pour la pratique des paroles de sagesse sur ce sujet. Je suis en train de penser que quelqu'un peut l'avoir conçu quelques CGRect et CGPoint extension qui va rendre la vie beaucoup plus facile. (Ou peut-être quelqu'un a écrit une cargaison supplémentaire opérateur arithmétique fonction des surcharges, telles que la combinaison de CGFloat de l'Int ou Double "fonctionne" - si c'est possible.)