Путаница из-за Swift, лишенная неявной конверсии CGFloat
Попытка выполнить арифметику в функции, которая возвращает `CGFloat, я получаю сообщение об ошибке:
Не удалось найти перегрузку для '/', которая принимает предоставленные аргументы
func kDCControlDegreesToRadians(x : CGFloat) -> CGFloat
{
return (M_PI * (x) / 180.0) // error is here.
}
Кто-нибудь еще видел этот тип проблемы?
Ответы
Ответ 1
Это проблема преобразования double
в float
.
На 64-битной машине CGFloat
определяется как double
, и вы скомпилируете его без проблем, потому что M_PI
и x
оба являются удвоенными.
На 32-битной машине CGFloat
является float
, но M_PI
по-прежнему является двойным. К сожалению, в Swift нет неявных отбросов, поэтому вы должны явно указывать:
return (CGFloat(M_PI) * (x) / 180.0)
Выводится тип литерала 180.0
.
В Swift 3
M_PI
устарел, используйте CGFloat.pi
вместо:
return (x * .pi / 180.0)
Ответ 2
В этом конкретном случае у меня есть симпатичный трюк, чтобы рекомендовать
let π = CGFloat(M_PI)
Unicode везде, а π легко получить с помощью Opt + P
Ответ 3
Лучше всего абстрагироваться от сложности. Сначала создайте расширение
extension Double {
/** Converts the specified value in degrees into radians. */
func degrees() -> CGFloat {
return CGFloat(self) * CGFloat(M_PI / 180.0)
}
}
затем используйте его в своем коде, например, в следующем примере
let angle = 30.0.degrees()
let transform = CGAffineTransformRotate(self.sliderControl.transform, angle);
Сначала я не хотел продлевать Double, потому что мне не нравится создавать пользовательское использование языка (от ужасов от кодирования, найденных на С++). Однако практический опыт показал, что это способ абстрагирования, естественный для языка.
Ответ 4
Это должно исправить ошибку:
func kDCControlDegreesToRadians(x : CGFloat) -> CGFloat
{
return (CGFloat(M_PI) * (x) / 180.0)
}
Причина возникновения ошибки заключается в том, что x
явно объявлен как CGFloat
, а M_PI
имеет тип CDouble
, как видно из объявления:
var M_PI: CDouble { get } /* pi */
Из-за этого вам нужно указать M_PI
для ввода CGFloat
, чтобы он соответствовал типу x
(как я уже делал в приведенном выше коде). Таким образом, нет конфликтов при работе на разных типах.
Обратите внимание, что вопреки тому, что указано в других ответах (и, как прокомментировал @Cezar), вам не нужно явно использовать 180.0
для типа CGFloat
, потому что это буквально, и не имеет явного типа, поэтому автоматически будет преобразован в CGFloat
без необходимости ручной трансляции.