2015-07-31 2 views
-1

Je travaille sur un chemin personnalisé pour UIBezierPath, et je reçois le "Impossible d'attribuer une valeur de type (CGFloat) à une valeur de type CGFloat." Je pense que c'est parce qu'il y a un problème avec le typecasting? Comment puis-je réparer cela? Les avertissements apparaissent pour la ligne "X = (b2 - b1)/(m1 - m2)" et la ligne "Y = m1 * X + b1".Comment faire un "Typecast" dans Swift?

func lineIntersection(m1: CGFloat, b1: CGFloat, m2: CGFloat, b2: CGFloat, inout X: CGFloat, inout Y: CGFloat) -> Bool { 
    if m1 == m2 { 
    return false 
} else if X = (b2 - b1)/(m1 - m2) { 
    return true 
} else if Y = m1 * X + b1 { 
    return true 
    } else { 
    return false 
    } 
} 

Je vais appeler cette fonction dans une autre fonction plus tard

func xxx() { 
     var outX = CGFloat() 
     var outY = CGFloat() 
     lineIntersection(oldSlope, b1: oldIntercept, m2: newSlope, b2: newIntercept, X: &outX, Y: &outY) 
} 
+1

Remplacez '=' par '==' dans vos conditions 'else if', aussi dans ce cas pas besoin d'inouts. (sauf si vous vouliez réellement assigner des valeurs à X et Y au lieu de les comparer, mais votre code ne fonctionnerait pas non plus pour cela). – Moritz

+1

Etes-vous sûr de vouloir '=' sur ces lignes et non '=='? –

+1

Vous devriez vraiment utiliser 'CGPoint' – Sulthan

Répondre

2
  1. Swift n'a pas zéro comme une valeur « false », vous devez comparer explicitement dans != 0 le if s. En outre, déplacez les affectations vers des lignes distinctes au lieu de le faire dans le cadre de la condition.

  2. Les comparaisons d'égalité à virgule flottante ne sont pas fiables, sauf dans quelques cas particuliers, et il est peu probable que ce soit le cas. Je voudrais supprimer les paramètres inout et renvoyer un CGPoint en option, c'est-à-dire -> CGPoint?. Renvoyez nil pour false et l'intersection CGPoint pour true.

fonction résultante (j'ai supprimé les contrôles à l'égalité tout à fait, la division à virgule flottante par zéro n'est pas dangereux, nous pouvons vérifier Inf/NaN plus tard):

func lineIntersection(m1 m1: CGFloat, b1: CGFloat, m2: CGFloat, b2: CGFloat) -> CGPoint? { 
    let x = (b2 - b1)/(m1 - m2) 
    let y = m1 * x + b1 
    return y.isFinite ? CGPoint(x: x, y: y) : nil 
} 

Utilisation à l'appel emplacement serait quelque chose comme:

if let intersection = lineIntersection(m1: m1, b1: b1, m2: m2, b2: b2) { 
    // use intersection.x and intersection.y 
} 

Quant à la question littérale de la façon de typer (bien que ce ne fut pas la question ici), vous pouvez initialiser même « types » avec quelque chose comme CGFloat(value), ce qui entraîne une conversion de type en "créant" un nouveau CGFloat de value. Plusieurs types ont également d'autres manières de spécifier comment exactement la conversion se produit, par exemple, Int32(truncatingBitPattern: largerInteger) prend les 32 bits les plus bas tels qu'ils sont, alors que Int32(largerInteger) se bloque si elle survient trop ou pas. Casting en tant que tel est fait avec as (connu pour réussir au moment de la compilation), as? (essayez de lancer à l'exécution, nil en cas d'échec), as! (essayez de lancer lors de l'exécution, affirmer le succès).

+0

Merci beaucoup pour votre réponse détaillée. C'était extrêmement utile. J'apprécie beaucoup –