Subscripts는 Swift에서 배열이나 딕셔너리와 유사하게 키나 인덱스를 통해 타입의 값에 접근할 수 있도록 해 주지만, 사용자 정의 타입에도 사용할 수 있습니다. 구문은 함수와 유사하지만 다음과 같이 괄호 안에서 접근합니다: object[key].
특성:
get만 포함하거나 get과 set을 모두 포함).적용:
예: 2차원 배열(행렬)과 두 개의 매개변수를 가진 subscript:
struct Matrix { let rows: Int, columns: Int private var grid: [Double] init(rows: Int, columns: Int) { self.rows = rows self.columns = columns grid = Array(repeating: 0.0, count: rows * columns) } subscript(row: Int, column: Int) -> Double { get { precondition(isValid(row: row, column: column), "Index out of range") return grid[(row * columns) + column] } set { precondition(isValid(row: row, column: column), "Index out of range") grid[(row * columns) + column] = newValue } } private func isValid(row: Int, column: Int) -> Bool { return row >= 0 && row < rows && column >= 0 && column < columns } } var matrix = Matrix(rows: 2, columns: 2) matrix[0,1] = 5.0 print(matrix[0,1]) // 5.0
subscript가 inout 유형의 매개변수를 가질 수 있거나 구조체에서 mutating일 수 있습니까?
답변:
inout일 수 없습니다.mutating set으로 선언할 수 있으며, 이를 통해 set 내에서 self를 변경할 수 있습니다:struct Counter { var value: Int = 0 subscript(increment: Bool) -> Int { mutating get { value += increment ? 1 : -1 return value } } }
이야기
사용자 정의 컬렉션에서 구조체에서 subscript의 set을 mutating으로 만들지 않아, subscript를 통해 요소를 변경하려는 모든 시도가 컴파일 오류를 일으켰습니다. 이 오류는 오랜 디버깅 후 컬렉션 통합 단계에서 나타났습니다.
이야기
사용자 정의 subscript에서 인덱스의 범위를 벗어나는 경우를 올바르게 처리하지 않아 범위를 벗어나는 호출 시 크래시가 발생했습니다. 그 결과 데이터 처리와 관련된 비즈니스 크리티컬한 기능이 중단되었습니다.
이야기
캐싱을 위해 enum에서 두 개의 매개변수를 가진 subscript를 구현했지만, subscript가 타입에 대해 static이 아니라 인스턴스에서만 가능하다는 것을 간과했습니다. 아키텍처 결정이 잘못된 것으로 판명되어 컬렉션 상호 작용 API를 다시 작성해야 했습니다.