2장 스위프트 기본 데이터 구조의 활용 - Array

sun02·2021년 10월 5일
0

- 애플이 구조체를 사용하는 이유?

: 오브젝티브 C, C++, 파이썬 등 여러 객체지향형 언어를 이용할 때, 원하는 타입을 만들기 위해 클래스를 사용했을 것이다.

그러나, 스위프트에서는 위와같은 용도로 클래스를 사용하지 않고, 스위프트에서 정의된 타입은 대부분 구조체(structure)이다.

그렇다면 스위프트는 왜 값타입인 구조체를 사용하여 참조 타입인 클래스를 지원하도록 하는 것일까?

=> 다양한 기능을 제공하는 클래스에 비해 제한된 기능을 제공하는 구조체가 더 적합하기 때문이다.

구조체는

  • 벨류 타입이기 때문에 하나의 소유 객체만을 가지고
  • 새로운 변수에 할당하거나 함수에 전달할 대 항상 복사해서 사용한다

=> 이러한 단순성이 코드를 안정화시킨다.

그렇다면 클래스는 언제 써야 할까?

  • 기본적으로 구조체를 사용한다.
  • Object-C 상호운용성이 필요할 때 클래스를 사용한다.
  • 모델링하는 데이터의 identity를 제어할 필요가 있는 경우 클래스를 사용한다.
  • 프로토콜로 구현(implementations)을 공유하고 채택해야하는 경우 구조체를 사용한다.

자세히 보기: Apple documents_choosing_between_structures_and_classes

- 배열

: 동일 타입의 값을 저장하는 데이터 타입.

Objective-C의 NSArray에는 다양한 타입을 저장할 수 있지만
동일 타입의 값으로 배열을 구성하면서 반환될 값의 타입을 명확히 예측할 수 있고 더 효율 적인 코드, 실수가 줄어든 코드를 작성할 수 있다.

그러나 만약 같은 배열 내에서 다른 타입의 값을 사용해야하는 경우 AnyObject 타입으로 정의할 수 있다.
(스위프트의 배열은 구조체로 정의된다.)

스위프트의 배열 유형

  • Array
  • ContiguousArray
  • ArraySlice

1. Array

: 배열에 포함된 배열 요소를 저장하기 위한 메모리 공간을 유지한다.

배열의 메모리 영역은

  • 배열 요소의 타입이 클래스나 @objc 프로토콜인 경우
    : NSArray 인스턴스 또는 NSArray의 서브클래스의 인스턴스로 저장
  • 배열 요소의 타입이 클래스나 @objc 프로토콜이 아닌 경우
    : 인접 블록에 저장

2. ContiguousArray

: 연속적으로 저장된 배열

  • Array 구현에 사용되는 다양한 프로토콜을 공유할 수 있으며, 거의 비슷한 프로퍼티 활용 가능하다.
  • Objective-C와의 브릿징을 지원하지 않는다는 점에서 Array와 다르다.

=> ContiguousArray는 항상 배열 요소를 인접한 메모리 영역에 저장하기 때문에 배열 요소의 타입이 클래스, @objc이고 브릿징이나 Objective-C API에 배열을 전달할 필요가 없는 경우 Array보다 ContiguousArray를 사용하는 것이 효율적이다.

3. ArraySlice

: Array, ContiguousArray 또는 ArraySlice 인스턴스의 조각이다.

  • ContiguousArray와 마찬가지로 배열 저장 시 인접 메모리 공간을 사용한다.
  • Objective-C와의 브릿징 지원하지 않는다.

=> 이미 존재하는 다른 배열의 일부를 대표하기 때문에 원본 배열의 생애주기가 끝나면 ArraySlice애 저장된 배열 요소 또한 접근 불가능하다.
따라서 Apple은 ArraySlice 인스턴스의 장기 사용을 권장하지 않는다.

+ 브릿징이란?

: Swift와 Objective-C로 작성된 데이터를 서로 교환해서 사용하는 것

NSArray, NSSet, NSDictionary에 대해서 native Swift로 변환할 수 있는 브릿징을 제공한다.


let nsFibonazzy : NSArray = [0,1,1,2,3,5,8,13]
let swiftFibonazzy : Array = nsFibonazzy as! [Int]

let nsFibonazzy : NSArray = [0,1,1,2,3,5,8,13]
if let swiftFibonazzy : Array = nsFibonazzy as? [Int] {
	// do sth
}
  • NSArray 를 Array로 브릿징

배열의 저장공간

Array, ContiguousArray, ArraySlice 인스턴스를 생성할 때 해당 배열 요소를 저장하기 위한 추가 저장 공간(Array's capacity)가 할당된다.
-> 배열에 메모리 공간을 재할당하지 않고 배열 관련 작업을 진행할 수 있는 잠재적인 저장 공간이다.

스위프트는 배열에 요소를 추가할 때마다 소진된 배열 용량을 자동으로 증가시키기 때문에 배열 요소 추가 작업이 대량으로 반복될 것을 미리 아는 경우, 배열 용량을 미리 할당해 두어야 시간을 줄일 수 있다.

  • reserveCapacity(500) 메서드를 통해 500개의 용량을 예약하였지만 실제 할당된 공간은 그 보다 큰 508이다.
    • 스위프트가 성능을 고려하여 실제 요청 이상으로 할당한다.

0개의 댓글