프로그래밍iOS 개발자

Swift에서 컬렉션을 위한 서브스크립트 메커니즘이 어떻게 작동하며 이를 사용자 정의 타입에 어떻게 적용할 수 있는지 설명하십시오. 사용 예를 제시하십시오.

Hintsage AI 어시스턴트로 면접 통과

답변.

Swift의 서브스크립트 메커니즘은 2014년에 언어와 함께 등장했으며, 컬렉션 데이터에 보다 편리한 구문으로 접근하기 위해 설계되었습니다. 서브스크립트를 통해 배열, 딕셔너리 및 기타 컬렉션의 요소에 대괄호를 통해 접근할 수 있습니다. 현대의 Swift는 사용자 정의 타입을 위한 사용자 정의 서브스크립트를 만들 수 있도록 하여 표준 데이터 구조처럼 API를 직관적으로 만듭니다.

문제: 이전에는 접근 방법이 더 번거롭게 보였으며 (예: .getElement(at:)), 서브스크립트는 타입과의 상호작용을 간결하게 만들어줍니다. 그러나 잘못된 구현은 비효율적인 코드나 컬렉션 범위를 초과하는 접근 오류를 일으킬 수 있습니다.

해결책: 서브스크립트를 구현하려면 서브스크립트라는 키워드를 사용하고, 그 다음에 매개변수와 반환 값을 지정합니다. 서브스크립트는 읽기 전용일 수도 있고, 읽기 및 쓰기가 가능할 수도 있습니다. 또한, 서브스크립트는 다른 매개변수에 대해 오버로딩 될 수 있습니다.

코드 예:

struct Matrix { let rows: Int let columns: Int var grid: [Double] init(rows: Int, columns: Int) { self.rows = rows self.columns = columns self.grid = Array(repeating: 0.0, count: rows * columns) } subscript(row: Int, column: Int) -> Double { get { assert(row >= 0 && row < rows && column >= 0 && column < columns, "Index out of range") return grid[(row * columns) + column] } set { assert(row >= 0 && row < rows && column >= 0 && column < columns, "Index out of range") grid[(row * columns) + column] = newValue } } } var matrix = Matrix(rows: 2, columns: 2) matrix[0, 1] = 3.14 print(matrix[0, 1]) // 3.14

주요 특징:

  • 서브스크립트는 [index]라는 친숙한 구문을 통해 요소의 읽기 및 쓰기를 지원합니다.
  • 여러 매개변수를 받을 수 있으며 오버로딩이 가능합니다.
  • 서브스크립트를 통해 타입을 컬렉션으로 만들 수 있습니다.

껴안는 질문들.

서브스크립트를 읽기 전용으로만 지정할 수 있나요? 아니면 서브스크립트는 항상 get과 set을 가져야 합니까?

서브스크립트는 구현에 set이 없는 경우 읽기 전용(오직 get만)일 수 있습니다. 두 가지 접근자를 모두 구현할 필요는 없으며, 이는 속성과 유사합니다.

코드 예:

subscript(index: Int) -> Int { get { return index * 2 } }

서브스크립트에 inout을 통해 변경 가능한 매개변수를 전달할 수 있나요?

아니요, 서브스크립트는 시그니처에서 inout 매개변수를 지원하지 않습니다. 모든 서브스크립트 매개변수는 accessor 본문 내에서 let 상수로 처리됩니다.

서브스크립트가 선택적 타입을 반환할 수 있나요?

네, 서브스크립트는 선택적 값을 반환할 수 있으며, 이는 배열의 범위를 초과할 위험 없이 컬렉션 요소에 안전하게 접근하는 데 유용합니다.

코드 예:

extension Array { subscript(safe index: Int) -> Element? { return indices.contains(index) ? self[index] : nil } }

일반적인 오류 및 안티 패턴

  • 서브스크립트 구현 시 범위 초과 검사를 건너뛰기.
  • accessor에서 과도한 로직을 포함하여 단일 책임 원칙을 위반하기.
  • 서브스크립트와 명시적 get/set 메소드 간의 의미 차이가 명확하지 않아 사용 시 혼란을 초래하기.

실제 사례

부정적 사례

입력 인덱스 오류로 인해 앱이 충돌하도록 하는 복합 타입 행렬에 대한 서브스크립트 구현은 범위 초과에 대한 유효성 검사가 없습니다.

장점:

  • 간단하고 빠르게 구현할 수 있으며, 간결한 코드입니다.

단점:

  • assert나 guard의 부재로 인해 런타임 오류 가능성.
  • 테스트하기 힘들고 확장성이 낮은 코드.

긍정적 사례

안전한 인덱싱 및 오류 처리를 위한 선택적 서브스크립트를 추가하여 API를 명확하고 안전하게 만듭니다.

장점:

  • 보다 안전한 접근 방식으로, 잠재적인 문제를 미리 경고합니다.
  • 예측 가능한 동작으로, 런타임 충돌이 줄어듭니다.

단점:

  • 클라이언트 수준에서 선택적 값을 처리해야 합니다.