2014-06-09 27 views
10

próbuje zrobić arytmetyki w funkcję, która zwraca `CGFloat, otrzymuję błąd:Zamieszanie spowodowane Swift brakuje niejawna konwersja CGFloat

Couldn't find overload for '/' that accepts supplied arguments

func kDCControlDegreesToRadians(x : CGFloat) -> CGFloat 
{ 
    return (M_PI * (x)/180.0) // error is here. 
} 

Czy ktoś widział tego typu problemu?

+4

To nie jest duplikat. Chociaż zgłaszany błąd jest taki sam, przyczyna jest tutaj o wiele bardziej zniuansowana niż nieporozumienie dotyczące bezpieczeństwa typu i typu wnioskowania. – Cezar

+0

@Mani, proponuję spróbować wymyślić inny tytuł dla twojego pytania. W rzeczywistości powoduje to zamieszanie z domniemanym duplikatem i może spowodować, że pytanie zostanie zamknięte przez osoby, które głosują tylko na podstawie tytułu. – Cezar

+0

@Cezar Zmieniłem swój tytuł, jeśli uważasz, że ten tytuł wprowadza zamieszanie, możesz edytować mój tytuł. – Mani

Odpowiedz

15

To jest problem z konwersją z double na float.

Na komputerze 64-bitowym, CGFloat jest zdefiniowany jako double i skompilować go bez problemów, ponieważ M_PI i x są zarówno podwaja.

Na komputerze 32-bitowym CGFloat to float, ale M_PI jest nadal podwójnym. Niestety, nie istnieją żadne ukryte odlewy w Swift, więc trzeba rzucić wyraźnie:

return (CGFloat(M_PI) * (x)/180.0) 

typ dla 180.0 dosłownym jest wywnioskować.

w Swift 3

M_PI jest przestarzała, użyj CGFloat.pi zamiast:

return (x * .pi/180.0) 
+0

Wyjaśnia, dlaczego nie mam problemu z tym kodem. – Cezar

+0

Wciąż mój umysł płynący z C i Objective-C, to problem. Mam cię. Dobrze pracować. Dzięki @Sulthan .. – Mani

0

To powinno rozwiązać błąd:

func kDCControlDegreesToRadians(x : CGFloat) -> CGFloat 
{ 
    return (CGFloat(M_PI) * (x)/180.0) 
} 

Powodem jest błąd występujący dlatego x jest wyraźnie uznany za CGFloat, natomiast M_PI ma typ CDouble, jak widać w oświadczeniu:

var M_PI: CDouble { get } /* pi    */ 

Z tego powodu należy odrzucić M_PI, aby wpisać CGFloat, więc pasuje do typu x (tak jak zrobiłem to w t on kod powyżej). W ten sposób nie ma konfliktu w działaniu na różnych typach.

Należy zauważyć, że wbrew temu, co zostało stwierdzone w innych odpowiedzi (oraz @Cezar skomentował), nie trzeba jawnie rzucić 180.0 do CGFloat typu, ponieważ jest to dosłowne, i nie ma wyraźny typ, zostanie automatycznie przekonwertowany na CGFloat bez konieczności ręcznego przesyłania.

+0

Powinieneś mieć przynajmniej flagę kompilatora, która sprawi, że ten typ nazistów zostanie sprawdzony. To naprawdę zabija produktywność – pkuhar

+0

Jest, nazywa się '-x target-c' – Greg

+0

@ PartialyFinite, który ma inny rodzaj produktywności ki]]. – pkuhar

11

W tym konkretnym przypadku mam ładny lewę polecić

let π = CGFloat(M_PI)

Unicode wszędzie , a π jest łatwe do uzyskania dzięki Opt + P

+0

+1 za użycie nazw symboli Unicode, które nie przerażają mnie tak bardzo jak większość: D (Zastanawiam się, czy mógłbyś dodać to jako rozszerzenie, ponieważ 'CGFloat.π' uczyniłoby to widocznym jaka to jest wartość ...) –

1

Najlepiej odjąć złożoność.Najpierw utworzyć rozszerzenie

extension Double { 
    /** Converts the specified value in degrees into radians. */ 
    func degrees() -> CGFloat { 
     return CGFloat(self) * CGFloat(M_PI/180.0) 
    } 
} 

następnie używać go w kodzie, takich jak w poniższym przykładzie

let angle = 30.0.degrees() 
let transform = CGAffineTransformRotate(self.sliderControl.transform, angle); 

Na początku byłem niechętnie przedłużyć dwukrotnie, ponieważ nie lubię tworzyć niestandardowe dostosowane używania język (od kodowania horrorów znalezionych w C++). Jednak praktyczne doświadczenie pokazało, że jest to sposób abstrakcji naturalny dla tego języka.