Swift랑 친해지기/Swift 책보면서 정리해보기

배열 아이템 동적 할당 방법 - 스위프트

데브킹덕 2022. 1. 24. 15:43

배열에 동적으로 아이템을 추가하고 싶을때에는 메소드를 사용한다.

대표적으로 아래 세가지를 사용함

* append(_:) 

* insert(_:at:)

* append(constentsOf:)

 

append(_:) 메소드

배열에서 존재하지 않는 인덱스에 접근하면 오류가 발생함

아이템 추가 전에 먼저 배열의 크기를  +1만큼 확장하여 인덱스 공간을 확보한 후,

인자값을 마지막 인덱스 위치에 추가함 

 

insert(_:at:)

메소드는 아이템을 원하는 위치에 직접 추가할때 사용

at:뒤에 입력되는 정수값은 아이템이 추가될 인덱스 위치를 뜻함

값이 추가가 되면 인덱스들은 하나씩 밀려나감

 

append(contentsOf:)

append(_:)처럼 배열의 맨 마지막에 아이템을 추가하지만

개별아이템이 아니라 여러개의 아이템을 한꺼번에 추가할때 사용

메소드의 인자값은 항상 배열이어야 함

메소드를 사용하여 배열에 동적으로 아이템 추가하는 코드

4행 - 배열의 크기 +1 추가하여 0인덱스공간 확보 후 인자값을 마지막 인덱스0에  Seoul 추가

5행 - 배열 의 크기 +1 추가하여 1인덱스공간 확보 후 인자값을 마지막 인덱스1에 NewYork 추가

6행 - 2인덱스의 공간을 확보한 후 1인덱스에 Tokyo 를 삽입하고 NewYork이 2인덱스밀려감 

7행 - 마지막 인덱스에 차례로 Dubai,Sydney 추가 

 

 

만약에 인덱스에 할당된 값을 변경하고 싶으면??

원하는 인덱스를 교체하는 방식으로 변경하면됨

 

그렇다면 cities[2]= "Madrid" 처럼 배열을 직접 대입하면 되지 않을까??

 

배열에 인덱스를 이용하여 직접 아이템에 접근하는 코드 

 

결론:잘못된 인덱스 참조로 인한 에러남

배열의 인덱스를 이용하여 직접 아이텝에 접근하는 방식은 

기존에 있는 값을 수정할 수 있지만, 값을 추가할 수는 없음

 

어떤 경우든 배열의 인덱스를 직접 이용하여 아이템의 값을 할당하거나 수정하고, 읽어오는 것은

해당 배열에 그인덱스가 이미 만들어져 있거나 인덱스가 확보되었을때만 가능함 

 

insert(_:at:) 메소드는 현재 배열에서 마지막 인덱스에 이어지는 다음 인덱스를 참조하는 것이 허용됨

내부적으로 배열의 크기를 +1 확장하여 새로운 인덱스를 만들어주기 때문

insert 메소드는 내부적으로 배열의 크기를 +1 확장한다를 보여주는 코드

 

배열의 인덱스에 직접 접근하려면 접근할 인덱스 공간이 미리 만들어져 있어야 함

배열의 길이가 늘어나면 그만큼 인덱스도 자동으로 늘어나는 것이 스위프트에서 배열의 특징임

이렇게 되면 배열의 크기는 항상 현재 입력된 값의 개수만큼 생성 됨

새로운 아이템을 직접 할당하기 위해 참조해야 할 인덱스는 아직 생성되어 있지 않은 상태라는 말임

때문에 오류가 발생함

즉, 배열의 크기를 동적으로 변경하는 방식으로 생성한 배열은 새로운 아이템을 추가할 목적으로 인덱스에 직접 접근 할 수 없음 

 

코코아 터치 프레임워크에는 초기화할 때 배열의 크기를 지정할 수 있는 구문이 정의되어 있음  Array(repeating:count:)

extension Array : RangeRelaceableCollection {
	public init(repeating repeatedValue: Element, count:Int)
}

*init*

 - 객체를 생성할때 사용하는 구문

*repeatedValue*

- 배열의 크기만큼 생성된 인덱스 각각에 기본값으로 넣어줌

*count*

- 배열의 길이를 정해줌 

 

Array(repeating: count:) 구문을 이용한 코드

이렇게 Array(repeating:count:) 구문을 사용하게 되면 배열의 인덱스가 개수만큼 미리 정의되고,

기본값이 각각 추가된 상태로 배열이 만들어짐

주의할 점은 인덱스 범위를 넉넉하게 확보해 놓아도 생성된 배열의 크기를 벗어나면 

마찬가지로 인덱스에 접근하고자 할때 잘못된 인덱스 참조 오류가 발생함

때문에, 배열의 길이 내에서 움직이는 것이 매우 중요함 

 

범위 연산자를 이용하여 인덱스 참조

주로 일정 범위의 배열 아이템을 한꺼번에 읽어 들일 때 사용함

범위연산자를 이용하여 인덱스를 참조한 코드

범위 연산자를 이용하여 배열의 인덱스를 참조하면 범위에 해당하는 모든 인덱스의 아이템을 읽어 오게 됨

이때 결과 값은 배열로 전달 됨

 

범위 연산자로 읽어 들인 배열의 크기보다 더 큰 아이템을 할당 할 수 있음 

범위 연산자를 이용한 아이템 수정 코드

범위 연산자로 읽어 들인 배열에 새로운 값을 할당하면 할당할 배열 아이템과 범위 연산자로 읽어 들인 배열의 크기가 일치하지 않을 때도 

값을 변경할 수 있음.

과정)

1. 범위 연산자로 얻은 인덱스는 1,2이고 해당하는 아이템은 ["b", "c"]이다

2. ["1", "2", "3"]을 할당하면  ["b", "c"] 삭제 되고 그 자리에 ["1", "2", "3"]이 대신하게 됨

3. 때문에 ["a", "1", "2", "3", "d" , "e"]가 됨

결론) 

2개의 아이템이 제거되었고 새로 3개의 아이템이 추가 되어 전체 배열 길이가 1만큼 커짐요

 

그렇다면

 

범위 연산자로 가져온 배열보다 할당될 배열의 크기가 작은 경우

범위 연산자로 가져온 배열보다 할당될 배열의 크기가 작은 경우

과정)

1. alphabet[2...4]를 이용하여 가져오는 아이템은 3개로 ["2", "3", "d"]

2. 아이템에 연결되어 있던 범위 인덱스에 ["A"]를 할당

즉, 기존 아이템 3개 모두 제거, 대신["A"] 추가 

3. 전체 배열은 ["a", "1", "A", "e"]로 수정 되며 배열의 크기는 4로 줄어듦

 

TMI)

NSArray, NSMutableArray

파운데이션 프레임워크에서 제공하는 객체들임

objective-c에서 배열 형식의 데이터를 다룰때 사용했음

NSArray는 수정이 필요 없는 배열

NSMutableArray는 수정이 필요한 배열에 사용

 

스위프트 배열 파운데이션 프레임워크 배열
구조체로 정의 클래스로 정의
생성할때 정의된 한가지 타입의 자료형만 배열에 저장 가능  데이터의 타입에 상관없이 저장 가능 

👨‍💻 타입이 명확하게 정해지지 않은 불특정형 집합 데이터나 여러 종류의 값이 섞여 있는 집합 데이터를 처리할때에는 

NSArray나 NSMutableArray를 사용해야 함