본문 바로가기

iOS/Swift

Swift - Strideable Protocol

https://developer.apple.com/documentation/swift/strideable

 

Strideable | Apple Developer Documentation

A type representing continuous, one-dimensional values that can be offset and measured.

developer.apple.com

 

 

 

Definition

 

Strideable연속적인 1차원 값을 나타내며, offset(차이)을 계산하고 측정(거리 계산)할 수 있는 타입을 정의한다.

즉, 어떤 값이 Strideable 프로토콜을 채택하면, 그 값 사이의 거리를 측정하거나, 일정 간격으로 값을 증분시킬 수 있다는 의미이다.

 

protocol Strideable<Stride> : Comparable

 

  • 대표적인 Strideable 타입에는 Int, Double, Date, CGFloat 등이 있다.
  • 두 값의 거리(distance)를 나타내는 Stride 타입을 Associcated Type으로 갖는다.
associatedtype Stride : Comparable, SignedNumeric

 

Overview

 

Strideable을 채태한 타입은 stride(from:to:by:)stride(from:through:by:)에서 사용할 수 있다.

  • 값 간의 간격을 설정하여 반복 작업
  • 특히 부동 소수점, 정수, 날짜와 같은 타입에 대해 간격을 두고 반복하거나 계산할 때 유용

stride(from:to:by:)

  • 시작 값에서 목표 값까지 지정한 간격으로 반복하되, 목표 값은 포함하지 않음

 

stride(from:through:by:)

  • 목표 값을 포함하여 반복

 

[부동 소수점을 사용한 반복]

// 0부터 2π까지, π/2 간격으로 반복하면서, 각 라디안(radian) 값을 도(degree)로 변환하여 출력
for radians in stride(from: 0.0, to: .pi * 2, by: .pi / 2) {
    let degrees = Int(radians * 180 / .pi)
    print("Degrees: \(degrees), radians: \(radians)")
}

 

[정수를 사용한 반복 - for in loop]

/// When a closed range uses integers as its lower and upper bounds, or any
/// other type that conforms to the Strideable protocol with an integer
/// stride, you can use that range in a for-in loop or with any sequence or
/// collection method. The elements of the range are the consecutive values
/// from its lower bound up to, and including, its upper bound. 
  • Stride 타입이 Int인 경우 ClosedRange를 사용하여 for-in 루프를 돌 수 있다.
  • Float이나 Double의 경우 Stride 타입이 각각 자기 자신이기 때문에 위의 stride 함수 들을 사용해야 함
var sum = 0
for x in 1...100 {
    sum += x
}
// sum == 5050


let digits = (0..<10).map(String.init)
// ["0", "1", "2", "3", "4", "5", "6", "7", "8", "9"]

 

Conforming to the Strideable Protocol

Strideable 프로토콜을 채택하기 위해서 다음 두 가지주요 메서드를 구현해야 한다.

 

  • advanced(by:): 현재 날짜에서 n일만큼 앞서거나 뒤로 이동한 날짜를 반환합니다.
  • distance(to:): 다른 날짜와의 일 수 차이를 반환합니다.

 

다음은 2000년 1월 1일 이후의 날짜를 나타내는 커스텀 구조체에 Strideable 프로토콜을 채택하는 예시이다.

 

1. Date 타입 정의

struct Date: Equatable, CustomStringConvertible {
    var daysAfterY2K: Int

    var description: String {
        return "Days after Y2K: \(daysAfterY2K)"
    }
}

 

 

2. Strideable 프로토콜 구현

  • typealias Stride = Int가 자동으로 추론됨 
extension Date: Strideable {
    func advanced(by n: Int) -> Date {
        var result = self
        result.daysAfterY2K += n
        return result
    }

    func distance(to other: Date) -> Int {
        return other.daysAfterY2K - self.daysAfterY2K
    }
}

 

3. stride(from:to:by:) 함수 사용

let startDate = Date(daysAfterY2K: 0)   // 2000년 1월 1일
let endDate = Date(daysAfterY2K: 15)    // 2000년 1월 16일

for date in stride(from: startDate, to: endDate, by: 7) {
    print(date)
}

// Days after Y2K: 0
// Days after Y2K: 7
// Days after Y2K: 14

 

[중요]

  • Strideable 프로토콜을 구현할 때, ==(동등 비교)와 <(작다 비교) 연산자에 대한 기본 구현이 제공됨
  • 이 연산자들은 Strideable이 사용하는 Stride 타입에 의존해 동작
  • 하지만, Strideable 타입 자체가 그 타입의 Stride 타입인 경우, 즉 자기 자신이 Stride 타입인 경우에는 무한 재귀가 발생할 수 있기 때문에, 구체적인 구현을 제공해야 함
    • 타입 자체가 Stride 타입이라면, 이 연산자는 자기 자신을 참조하는 방식으로 구현될 수 있어, 무한 재귀가 발생한다

 

 

 

 

'iOS > Swift' 카테고리의 다른 글