오늘은 Swift의 inout parameter(파라미터)를 사용하는 함수에 대해 정리하고 마스터해 보겠습니다.
1. inout 파라미터
1-1. inout 파라미터
원래 Swift에서 함수나 메서드에 전달되는 파라미터는,
상수(constants)로 취급되어 함수 내에서 수정할 수 없습니다.
하지만 파라미터를 아래와 같이 inout 키워드와 함께 표시하면,
원래 상수라면 안 되는 다음의 일들이 가능해집니다.
- 함수 내에서 파라미터를 수정 가능
- 함수가 호출될 때 값을 전달받아 함수 내부에서 수정한 후, 수정된 값을 다시 원래 변수에 반영
func makeDouble(number: inout Int) {
number *= 2
}
위 함수는 아래와 같이 사용해 주어야 합니다.
주의할 점은, inout 파라미터를 전달할 때,
'&' 기호를 붙여야 하는데요.
이것은 '이 인자를 inout 파라미터로 전달한다'는 의미를 가집니다.
이 함수를 거쳐 변경될 수 있는 값이라는 의미로 보면 되겠지요.
var testNum = 10
makeDouble(number: &testNum)
2. 일반 함수 vs inout 파라미터 함수
일반함수와 inout 파라미터를 사용하는 함수를 비교하며 익혀 보겠습니다.
2-1. 일반 함수
먼저 inout 없이 일반파라미터를 사용하는 함수를 볼까요.
아래 코드에서, incrementNormal함수 호출 후에도,
myNumber는 상수로 취급하므로 변경 없이 5가 됩니다.
func incrementNormal(number: Int) {
var copy = number
copy += 1
print("함수 내부: \(copy)")
// 원본 변수는 수정되지 않음
}
var myNumber = 5
incrementNormal(number: myNumber)
print("일반 함수 호출 후: \(myNumber)") // 여전히 5
1-2. inout 파라미터 사용한 함수
반면, inout파라미터를 사용하는 함수를 보죠.
아래에서 incrementInout 함수 호출 후,
myNumber는 5가 아니라, 함수에 의해 변경된 6이 됩니다.
// inout 파라미터를 사용한 함수
func incrementInout(number: inout Int) {
number += 1
print("함수 내부: \(number)")
// 원본 변수가 수정됨
}
var myNumber = 5
incrementInout(number: &myNumber)
print("inout 함수 호출 후: \(myNumber)") // 6으로 변경됨
3. 다른 예제 코드
여러 가지 예제 코드를 보면서 어떻게 사용하는지 익혀보겠습니다.
3-1. 두 변수 값 교환
아래는 inout 파라미터를 이용해서,
파라미터에 집어넣는 두 변수의 값을 서로 교환하는 코드입니다.
func swapValues<T>(a: inout T, b: inout T) {
let temporaryA = a
a = b
b = temporaryA
}
var first = 30
var second = 50
print("교환 전: first = \(first), second = \(second)")
swapValues(a: &first, b: &second)
print("교환 후: first = \(first), second = \(second)")
//교환 전: first = 30, second = 50
//교환 후: first = 50, second = 30
3-2. 컬렉션 수정
inout파라미터를 이용해서,
array를 전달한 후,
아래와 같이 추가할 수도 있습니다.
이럴 때는 꼭 inout 파라미터를 사용해야 하지요.
func addItemsToArray(array: inout [String], newItems: [String]) {
for item in newItems {
array.append(item)
}
}
var fruits = ["사과", "바나나"]
let moreFruits = ["딸기", "포도"]
print("추가 전 과일: \(fruits)")
addItemsToArray(array: &fruits, newItems: moreFruits)
print("추가 후 과일: \(fruits)")
// 추가 전 과일: ["사과", "바나나"]
// 추가 후 과일: ["사과", "바나나", "딸기", "포도"]
3-3. Combine에서 구독 객체를 제공된 컬렉션에 저장하기
조금 복잡해 보이지만,
Combine에서 사용하는 사례를 볼까요?
아래 코드에서는,
'.store(in: &subscriptions)'를 마지막에 추가함으로써,
생성된 구독을 subscriptions Set에 저장합니다.
inout 파라미터를 추가하므로,
subscriptions앞에 &를 붙여서 사용한 것이지요.
class SubscriptionExample: ObservableObject {
// 구독을 저장할 Set 컬렉션
private var subscriptions = Set<AnyCancellable>()
init() {
// 타이머 생성 (1초마다 값 발행)
let timer = Timer.publish(every: 1.0, on: .main, in: .common).autoconnect()
// 타이머 구독
timer
.sink { time in
print("현재 시간: \(time)")
}
.store(in: &subscriptions) // 생성된 구독을 저장
// 다른 Publisher도 간단히 구독
Just("안녕하세요")
.sink { message in
print(message)
}
.store(in: &subscriptions) // 이 구독도 저장
}
// 객체가 해제될 때 subscriptions Set도 해제되면서
// 자동으로 모든 구독이 취소됩니다
}
'iOS, Swift > Swift' 카테고리의 다른 글
Swift enum 총정리 (1) | 2025.03.31 |
---|---|
Swift Parameter Label(매개변수 라벨) as 사용방법 정리 (0) | 2025.03.15 |
Swift Closure의 강한 캡처와 [weak self]의 필요성 (2) | 2025.03.14 |
Swift guard let 이용한 Optional unwrapping 방법 (0) | 2025.03.12 |
Swift 불투명 타입 some은 왜 필요할까? (0) | 2025.03.08 |
댓글