학습 기록/swift

NSArray, NSMutableArray

romi__ 2024. 11. 19. 15:38

/Swift

 

 

Hello World + Variables

/C 국룰 Hello, World를 Xcode를 통해 출력해 보았다. Variables를 선언하는 방법에는 크게 두 가지가 있다. var를 사용하기, let을 사용하기. let은 재할당이 불가한 반면 var는 가능하다. 위의 예시에서는

romiwaves.tistory.com

 

 

어제 진행했던 실습에서 NSArray, NSMutableArray가 포함된 코드를 작성하였다.

let someNames = NSMutableArray(
    array: [
        "Foo",
        "Bar"
    ]
)
func changeTheArray(_ array: NSArray) {
    let copy = array as! NSMutableArray
    copy.add("Baz")
}
changeTheArray(someNames)
someNames //internally mutated

 

NSMutableArray와 NSArray가 뭐길래 let으로 선언한 변수도 수정할 수 있는 것일까?

 

📌 NSArray

예를 들면, NSArray는 한번 채워지면 더 이상 바꿀 수 없는 장난감 상자와도 같다. 

let toyBox: NSArray = ["자동차", "인형", "공"]

// 상자 안에 무엇이 있는지 확인 가능
print(toyBox[0]) // "자동차"

// 하지만 추가, 제거, 순서 변경은 불가

 

toyBox를 한 번 NSArray로 선언하고 나면, 해당 배열 안에 어떤 장난감이 있는지 확인하고 순서에 맞게 불러올 순 있지만 장난감을 제거 및 추가하거나, 장난감의 순서를 바꾸는 것은 불가능하다.

 

📌 NSMutableArray

반면 NSMutableArray는 조금 다르다. 같은 장난감 상자를 선언하더라도, NSMutableArray에서는 그 내용에 변화를 줄 수 있다.

let mutableToyBox: NSMutableArray = ["자동차", "인형", "공"]

// 새 장난감 추가
mutableToyBox.add("레고")
print(mutableToyBox) // ["자동차", "인형", "공", "레고"]

// 특정 장난감 제거
mutableToyBox.remove("인형")
print(mutableToyBox) // ["자동차", "공", "레고"]

// 순서 바꾸기
mutableToyBox[0] = "비행기"
print(mutableToyBox) // ["비행기", "공", "레고"]

 

 

차이점을 요약하자면,

특징 NSArray NSMutableArray
변경 가능성 수정할 수 없음 수정 가능
추가/삭제 가능 추가하거나 삭제할 수 없음 추가하거나 삭제할 수 있음
속도 더 빠르고 메모리를 더 적게 사용 더 느리고 메모리를 더 많이 사용

 

이 정도가 되겠다.

 

📌 그렇다면 이 코드에서는...?

어제 살펴보았던 코드를 다시 한 번 보자.

let someNames = NSMutableArray(
    array: [
        "Foo",
        "Bar"
    ]
)
func changeTheArray(_ array: NSArray) {
    let copy = array as! NSMutableArray
    copy.add("Baz")
}
changeTheArray(someNames)
someNames //internally mutated

 

엥? NSArray를 매개변수로 갖는 changeTheArray 함수에 someNames를 적용하면 someNames가 internally mutated 된 것을 확인할 수 있었다. 방금 막 NSArray는 변화할 수 없다고 배운 참인데... 이게 어떻게 된 일인지?

 

사실 여기에는 이유가 있다. 그 이유는 바로 객체의 참조와 변환이다.

 

NSArray는 수정 불가능한 것이 맞다. 하지만 그 객체가 실제로는 NSMutableArray일 경우에는 참조를 통해 내부 데이터를 바꿀 수 있다. 코드를 분석해보자.

 

let someNames = NSMutableArray(
    array: [
        "Foo",
        "Bar"
    ]
)

 

여기서 선언한 someNames는 NSMutableArray 객체이다. 즉, 수정 가능한 배열로 생성된 상태이다.

 

func changeTheArray(_ array: NSArray) {
    let copy = array as! NSMutableArray
    copy.add("Baz")
}

 

changeTheArray함수를 호출할 때, NSArray를 매개변수로 받는다. 다만 내부에서 as! NSMutableArray를 이용하여 강제로 NSMutableArray로 캐스팅하였다. (이러한 코드는 매우 bad code... 실제로 사용하면 안 된다) 따라서 copy.add를 하게 되면 실제로는 불러온 매개변수가 변경되는 것이다.

 

NSArray는 수정 불가능한 인터페이스를 제공하지만, 이 경우는 객체의 외부에서 수정하지 못하도록 제한하는 것이다. 하지만 원래의 객체가 NSMutableArray라면, 내부 참조를 통해 수정이 허용된다.

 

 

📌 만약 정말로 수정이 불가능하게 할 것이었다면

NSArray를 복사본으로 넘기는 방법이 있다.

func changeTheArray(_ array: NSArray) {
    let copy = array.mutableCopy() as! NSMutableArray
    copy.add("Baz")
}

 

이렇게 코드를 작성하면 새로운 배열이 수정되고, someNames는 수정되지 않은 상태로 유지된다.

'학습 기록 > swift' 카테고리의 다른 글

if and else  (0) 2024.11.21
Operators  (0) 2024.11.20
Hello World + Variables  (0) 2024.11.18
Xcode 설치하기  (0) 2024.11.17
앞으로는  (2) 2024.11.16