이 Obj-C
코드를 Swift
코드 로 변환하려고하는데이 코드에 해당하는 것이 무엇인지 모르겠습니다.
#define DEGREES_TO_RADIANS(degrees)((M_PI * degrees)/180)
하지만 내 경우에는 Swift에서 변환하는 방법을 이해하지 못합니까?
이 Obj-C
코드를 Swift
코드 로 변환하려고하는데이 코드에 해당하는 것이 무엇인지 모르겠습니다.
#define DEGREES_TO_RADIANS(degrees)((M_PI * degrees)/180)
하지만 내 경우에는 Swift에서 변환하는 방법을 이해하지 못합니까?
답변:
Xcode 11 • Swift 5.1 이상
extension BinaryInteger {
var degreesToRadians: CGFloat { CGFloat(self) * .pi / 180 }
}
extension FloatingPoint {
var degreesToRadians: Self { self * .pi / 180 }
var radiansToDegrees: Self { self * 180 / .pi }
}
운동장
45.degreesToRadians // 0.7853981633974483
Int(45).degreesToRadians // 0.7853981633974483
Int8(45).degreesToRadians // 0.7853981633974483
Int16(45).degreesToRadians // 0.7853981633974483
Int32(45).degreesToRadians // 0.7853981633974483
Int64(45).degreesToRadians // 0.7853981633974483
UInt(45).degreesToRadians // 0.7853981633974483
UInt8(45).degreesToRadians // 0.7853981633974483
UInt16(45).degreesToRadians // 0.7853981633974483
UInt32(45).degreesToRadians // 0.7853981633974483
UInt64(45).degreesToRadians // 0.7853981633974483
Double(45).degreesToRadians // 0.7853981633974483
CGFloat(45).degreesToRadians // 0.7853981633974483
Float(45).degreesToRadians // 0.7853981
Float80(45).degreesToRadians // 0.78539816339744830963
이진 정수가 항상 CGFloat를 반환하는 대신 부동 소수점 유형을 반환하도록하려면 계산 된 속성 대신 일반 메서드를 만들 수 있습니다.
extension BinaryInteger {
func degreesToRadians<F: FloatingPoint>() -> F { F(self) * .pi / 180 }
}
let radiansDouble: Double = 45.degreesToRadians() // 0.7853981633974483
let radiansCGFloat: CGFloat = 45.degreesToRadians() // 0.7853981633974483
let radiansFloat: Float = 45.degreesToRadians() // 0.7853981
let radiansFloat80: Float80 = 45.degreesToRadians() // 0.78539816339744830963
CGFloat
않습니까?
이것은 당신이 요청한 것과 동일하지는 않지만 Swift 3 / iOS 10에서는 공식을 몰라도 측정 유형을 사용하고 변환을 수행 할 수 있습니다!
let result = Measurement(value: 45, unit: UnitAngle.degrees)
.converted(to: .radians).value
let angle = 45° // angle will be in radians, 45 is in degrees
Swift 3에서 컴파일합니다 . 여전히 모든 값을 유지하고 CGFloats를 사용하여 라디안 단위로 모든 계산을 수행하지만, 각도 상수를 사용하여 코드를 더 읽기 쉽게 만듭니다. 예 : 90 ° ° 기호는 마법처럼 각도를 라디안으로 변환합니다.
설정 방법 :
° 기호에 접미사 연산자를 정의하고 사용합니다 . 이 연산자는 각도를 라디안으로 변환합니다. 이 예제는 Ints 용이며, 필요한 경우 Float 유형에 대해서도 확장합니다.
postfix operator °
protocol IntegerInitializable: ExpressibleByIntegerLiteral {
init (_: Int)
}
extension Int: IntegerInitializable {
postfix public static func °(lhs: Int) -> CGFloat {
return CGFloat(lhs) * .pi / 180
}
}
사용의 몇 가지 예 :
let angle = 45°
contentView.transform = CGAffineTransform(rotationAngle: 45°)
let angle = 45
contentView.transform = CGAffineTransform(rotationAngle: angle°)
경고!
이 변환을 두 번 사용하는 것은 너무 쉽습니다 (실수로 이미 라디안으로 표시된 값에서) 결과로 매우 작은 숫자를 얻게되고 결과 각도는 항상 0이됩니다. 동일한 값에 °를 사용하지 마십시오. 값을 두 번 (두 번 변환하지 마십시오) !! :
// OBVIOUSLY WRONG!
let angle = 45°° // ° used twice here
// WRONG! BUT EASY TO MISS
let angle = 45° // ° used here
contentView.transform = CGAffineTransform(rotationAngle: angle°) // ° also used here
IntegerInitializable
프로토콜은 무의미합니다. Int는 이미 준수ExpressibleByIntegerLiteral
public extension FixedWidthInteger { postfix static func °<T: FloatingPoint>(lhs: Self) -> T { T(lhs) * .pi / 180 } }
let angle: CGFloat = 45°
. 그러나 그것이 기대 어디에 필요하지 않습니다 CGFloat
또는 FloatingPoint
유형CGAffineTransform(rotationAngle: 45°)
변수 이름을 만들 때 더 이상 ASCII 문자로 제한되지 않으므로 π (alt-p)를 사용하면 어떨까요?
typealias RadianAngle = CGFloat
let π = RadianAngle(M_PI)
let π_x_2 = RadianAngle(M_PI * 2)
let π_2 = RadianAngle(M_PI_2)
let π_4 = RadianAngle(M_PI_4)
extension RadianAngle {
var degrees: CGFloat {
return self * 180 / π
}
init(degrees: Int) {
self = CGFloat(degrees) * π / 180
}
}
사용 예 :
let quarterCircle = RadianAngle(degrees: 90)
print("quarter circle = \(quarterCircle) radians")
// quarter circle = 1.5707963267949 radians
let halfCircle = π
print("half circle = \(halfCircle.degrees) degrees")
// half circle = 180.0 degrees
스위프트 4.2
전역 일반 함수를 작성할 수 있습니다.
public func radians<T: FloatingPoint>(degrees: T) -> T {
return .pi * degrees / 180
}
public func degrees<T: FloatingPoint>(radians: T) -> T {
return radians * 180 / .pi
}
예:
let cgFloat: CGFloat = 23.0
let double: Double = 23.0
let float: Float = 23.0
let int: Int = 23
let cgf = radians(degrees: cgFloat) // 0.4014 CGFloat
let d = radians(degrees: double) // 0.4014 Double
let f = radians(degrees: float) // 0.4014 Float
let i = radians(degrees: int) // compile error
이와 같이 모든 플로팅 유형을 확장하고 싶지 않은 경우
extension FloatingPoint { ... }
return .pi * degrees / 180
않습니까?
T
는 FloatingPoint
유형이고 180은 Int
유형 이기 때문 입니다 . 신속하게 다른 유형에 대한 계산을 수행 할 수 없습니다.
위에서 언급 한 동일한 원칙 @ t1ser를 사용하지만 CGFloat
, 정도에 대해 소수를 더 쉽게 사용할 수 있도록 확장을 만듭니다 (예를 들어 23.4도를 가질 수 있음).
extension CGFloat {
func degrees() -> CGFloat {
return self * .pi / 180
}
init(degrees: CGFloat) {
self = degrees.degrees()
}
}
그것을 사용하는 것도 꽤 쉬울 것입니다 (주로 나는 개인적으로 ° 😜을 입력하는 방법을 몰랐기 때문에-당신도 그렇지 않은 경우 option+shift+8
btw입니다) :
let degreesToConvert: CGFloat = 45.7
.
.
.
let convertedDegrees = degreesToConvert.degrees()
또는 이니셜 라이저를 사용하려면 :
let convertedDegrees = CGFloat(degrees: 45.3)
신속한 2.3
func kilometersBetween(Place1:CLLocationCoordinate2D , Place2:CLLocationCoordinate2D) -> Double{
var start = MKMapPointForCoordinate(Place1)
var finish = MKMapPointForCoordinate(Place2)
print(MKMetersBetweenMapPoints(start, finish) / 1000)
return MKMetersBetweenMapPoints(start, finish) / 1000
}