ios tutorial Numérique rapide et CGFloat(CGPoint, CGRect, etc.)




xcode (3)

CGFloat explicitement scale sur CGFloat , comme vous l’avez découvert, est en effet le moyen de traiter le problème de frappe dans swift. Pour référence pour les autres:

let scale: CGFloat = 2.0
let r = self.view.bounds
var r2 = CGRect()
r2.size.width = r.width * scale

Vous ne savez pas comment répondre à votre deuxième question, vous pouvez l’afficher séparément avec un titre différent.

Mettre à jour:

Chris Lattner, créateur et développeur principal de Swift, a déclaré ce qui suit à ce sujet lors du forum des développeurs Apple du 4 juillet 2014:

Ce qui se passe ici, c'est que CGFloat est une typealias pour Float ou Double, selon que vous construisez pour 32 ou 64 bits. C’est exactement comme cela que fonctionne Objective-C, mais cela pose problème dans Swift car Swift n’autorise pas les conversions implicites.

Nous sommes conscients de ce problème et le considérons comme sérieux: nous évaluons actuellement plusieurs solutions différentes et en présenterons une dans une version bêta ultérieure. Comme vous le remarquerez, vous pouvez faire face à cela aujourd'hui en faisant appel à Double. C'est peu élégant mais efficace :-)

Mise à jour dans Xcode 6 Beta 5:

Un CGFloat peut être construit à partir de n'importe quel type Integer (y compris les types d'entiers dimensionnés) et inversement. (17670817)

Je trouve les calculs Swift particulièrement maladroits lorsque, comme cela se produit souvent dans la vie réelle, je dois communiquer avec Cocoa Touch en ce qui concerne CGRect et CGPoint (par exemple, parce que nous parlons du frame ou des bounds de quelque chose).

CGFloat vs. Double

Considérez le code innocent suivant d'une sous-classe UIViewController:

let scale = 2.0
let r = self.view.bounds
var r2 = CGRect()
r2.size.width = r.size.width * scale

La compilation de ce code échoue, avec l'erreur mystérieuse habituelle sur la dernière ligne:

Impossible de trouver une surcharge pour '*' qui accepte les arguments fournis

Comme vous le savez sans doute maintenant, cette erreur indique une sorte de décalage d’impédance entre les types. r.size.width arrive sous la forme d'une CGFloat, qui s'échange automatiquement avec un Swift Float mais ne peut pas interagir avec une variable Swift Double (qui, par défaut, correspond à quelle scale ).

L'exemple est artificiellement bref. Il existe donc une solution artificiellement simple, qui consiste à lancer l' scale à un flotteur dès le départ. Mais lorsque de nombreuses variables provenant de partout sont impliquées dans le calcul des éléments d'un CGRect proposé, il y a beaucoup d'incantation à faire.

Initialiseur Verbose

Une autre irritation est ce qui se produit lorsque le moment est venu de créer un nouveau CGRect. Malgré la documentation, il n'y a pas d'initialiseur avec des valeurs mais sans étiquettes. 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 nous lançons un Float, nous ne compilons pas:

Étiquettes d'argument manquantes 'x: y: width: height:' dans l'appel

Nous nous retrouvons donc sur CGRectMake , ce qui n’apporte aucune amélioration par rapport à Objective-C. Et parfois, CGRectMake et CGSizeMake n'apportent aucune amélioration. Considérez ce code de l'une de mes applications:

let kSEP : Float = 2.0
let intercellSpacing = CGSizeMake(kSEP, kSEP);

Dans un de mes projets, ça marche. Dans un autre, il échoue mystérieusement - le même code exact! - avec cette erreur:

'NSNumber' n'est pas un sous-type de 'CGFloat'

C'est comme si, parfois, Swift essayait de "traverser le pont" en lançant un Float vers un NSNumber, ce qui est bien sûr la mauvaise chose à faire lorsque ce qui se trouve de l'autre côté du pont attend un CGFloat. Je n'ai pas encore compris quelle est la différence entre les deux projets qui provoquent l'erreur dans l'un mais pas dans l'autre (peut-être quelqu'un d'autre l'a fait).

REMARQUE: j'ai peut-être compris ce problème: il semble dépendre du paramètre de construction Build Active Architecture Only, ce qui suggère à son tour qu'il s'agit d'un problème 64 bits. Ce qui est logique, car Float ne serait pas compatible avec CGFloat sur un périphérique 64 bits. Cela signifie que le problème de déséquilibre impédance est encore pire que je ne le pensais.

Conclusion

Je cherche des mots pratiques de sagesse sur ce sujet. Je pense que quelqu'un a peut-être conçu une extension CGRect et CGPoint qui facilitera grandement la vie. (Ou peut-être quelqu'un a-t-il écrit une surcharge de fonctions d'arithmétiques supplémentaires, telles que la combinaison de CGFloat avec Int ou Double "ne fait que" fonctionner - si cela est possible.)



J'ai créé une extension pour Double et Int qui leur ajoute une propriété calculée CGFloatValue.

extension Double {
    var CGFloatValue: CGFloat {
        get {
            return CGFloat(self)
        }
    }
}
extension Int {
    var CGFloatValue: CGFloat {
        get {
            return CGFloat(self)
        }
    }
}

Vous y let someCGFloat = someDoubleOrInt.CGFloatValue en utilisant let someCGFloat = someDoubleOrInt.CGFloatValue

En outre, comme pour votre initialiseur CGRect, vous obtenez l'erreur d'étiquettes d'argument manquante car vous avez CGRect(x: d, y: d, width: d, height: d) les étiquettes, vous avez besoin de CGRect(x: d, y: d, width: d, height: d) Vous ne pouvez pas laisser les étiquettes. out sauf s'il n'y a qu'un seul argument.





swift