클로저
클로저는 다양한 형태로 표현이 가능하다.
- 후행 클로저 : 함수의 마지막 매개변수로 전달되는 클로저는 후행클로저로, 함수 밖에 구현될 수 있다.
- 반환 타입 생략 : 컴파일러가 클로저의 반환 타입을 유추할 수 있는 경우, 반환 타입을 생략할 수 있다.
- 매개변수 이름 생략 : 매개변수의 이름이 필요 없고, 컴파일로가 타입을 유추할 수 있는 경우, 축약된 전달 인자 형태로 사용할 수 있다.
- 암시적 반환 : 반환 값이 있는 경우, 클로저의 맨 마지막 줄에서 return을 생략할 수 있다.
1. 반환 타입 생략
calculate 함수의 method 매개변수는 Int형이 반환된다는 것을 컴파일러도 알고 있기에 클로져에서 반환 타입을 명시해주지 않아도 된다. 하지만 in 키워드는 생략할 수 없다.
let result = calculate(a: 10, b: 20, method: {(left: Int, right:Int) in
return left + right
}
// 후행 클로저
let result = calculate(a: 10, b: 20, {(left: Int, right: Int) in
return left + right
}
2. 매개변수 이름 생략
let result = calculate(a: 10, b: 20, method: {
return $0 + $1
}
// 후행 클로저
let result = calculate(a: 10, b: 20, {
return $0 + $1
}
3. 암시적 반환
클로저가 반환하는 값이 있다면 마지막 줄은 암시적으로 표현 가능
let result = calculate(a: 10, b: 20) {
$0 + $1
}
// 한 줄로 표현 가능
let result = calculate(a: 10, b:20) { $0 + $1 }
프로퍼티
프로퍼티는 구조체, 클래스, 열거형에 소속된 상수나 변수를 말한다. 열거형에는 연산 프로퍼티만 사용 가능하고, 연산 프로퍼티는 읽기 전용(getter)만으로는 구현 가능하지만 쓰기 전용(setter)만으로는 구현할 수 없다. 프로퍼티는 크게 3가지로 나뉜다.
- 저장 프로퍼티
- 연산 프로퍼티
- 타입 프로퍼티
1. 저장 프로퍼티
let, var 키워드를 통해 생성하는 인스턴스 변수나 상수이며, 구조체, 클래스에서만 사용 가능하다.
struct Person {
var name: String
var age: Int
}
+) 구조체에서 저장 프로퍼티를 let으로 선언하면 인스턴스 생성 이후 값을 변경할 수 없다.
struct Person {
let name: String
var age: Int
}
let p1 = Person(name: "kodo", age: 25)
p1.age = 26 // 컴파일 오류!
var p2 = Person(name: "kodo", age: 25)
p2.age = 26 // OK!
이와 다르게 클래스는 값을 변경할 수 있다. 왜냐하면 클래스는 참조 타입, 구조체는 값 타입이기 때문이다.
2. 지연 저장 프로퍼티
지연 저장 프로퍼티는 값이 처음으로 사용되기 전에는 계산되지 않는 프로퍼티이다. 말 그대로 값이 처음으로 사용되기 전에는 값을 가지지 않기에 반드시 var 키워드로 생성해야 한다. 왜냐하면 상수는 초기화가 되기 전에 항상 값을 같는 프로퍼티이기 때문이다. 복잡한 계산 작업을 지연 프로퍼티로 선언하고 사용하면 실제로 사용되기 전, 즉 인스턴스가 사용되기 전에는 실행되지 않아 인스턴스 초기화 시점에 복잡한 계산을 피할 수 있다.
class DataImporter {
// 외부에서 데이터를 가져오는 클래스
var fileName = "data.txt"
}
class DataManager {
lazy var dataImporter = DataImporter()
var data = [String]()
//
let manager = DataManager
manager.data.append("First Data")
// DataImporter 인스턴스는 이 시점에 생성되어 있지 않음
3. 연산 프로퍼티
연산 프로퍼티는 실제 값을 저장하고 있는 것이 아니라 게터와 세터를 통해서 값을 설정하는 프로퍼티이다.
struct Point {
var x: Double = 0.0, y: Double = 0.0
}
struct Size {
var width: Double = 0.0, height: Double = 0.0
struct Rect {
var start = Point()
var size = Size()
var center: Point {
get {
let centerX: Double = start.x + size.width / 2
let centerY: Double = start.y + size.height / 2
}
set(newCenter) {
start.x = newCenter.x - size.width / 2
start.y = newCenter.x - size.height / 2
}
}
}
// 구조체는 자동으로 초기화(생성자)가 생성됨
var square: Rect = Rect(start: start(x: 0.0, y: 0.0), size: Size(width: 10.0, height: 10.0))
let center: Point = square.center // 연산 프로퍼티(게터)를 통해서 값을 계산
square.center = Point(x: 20.0, y: 20.0) // 연산 프로퍼티(세터)를 통해서 새로운 값을 할당
4. 타입 프로퍼티
인스턴스 프로퍼티는 특정 인스턴스에 속한 프로퍼티이다. 따라서 인스턴스가 생성될 때마다 프로퍼티 역시 새롭게 생성된다. 이와 다르게 타입 프로퍼티는 특정 타입에 속한 프로퍼티로 그 타입에 해당하는 단 하나의 프로퍼티만 생성된다. 특정 타입의 모든 인스턴스에 공통적으로 사용되는 값을 정의할 때 유용하다. 또한 타입 프로퍼티는 항상 초기화가 되어 있어야 하며, class는 오버라이딩이 가능한 타입 프로퍼티, static은 불가능한 타입 프로퍼티이다.
5. 프로퍼티 옵저버
새 값이 설정될 때마다 이벤트를 감지할 수 있는 옵저버이다. 프로퍼티 옵저버는 지연 저장 프로퍼티에서는 사용할 수 없고 연산 프로퍼티에서는 게터에서 값의 변화를 감지하기에 따로 옵저버를 정의할 필요가 없다.
- willSet : 값이 저장되기 직전에 호출
- didSet: 새 값이 저장되고 직후에 호출
willSet에서 새 값의 매개변수 이름을 지정하지 않으면 newValue, didSet에서 지정하지 않으면 oldValue를 기본 값으로 사용한다.
class StepCounter {
var totalSteps: Int = 0 {
willSet(newTotalSteps) {
print("[willSet 호출] \\(totalSteps) -> \\(newTotalSteps)")
}
didSet {
if totalSteps > oldValue {
print("[didSet 호출] \\(oldValue) -> \\(totalSteps)")
}
}
}
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200
stepCounter.totalSteps = 360
stepCounter.totalSteps = 896
// 결과
[willSet 호출] 0 -> 200
[didSet 호출] 0 -> 200
[willSet 호출] 200 -> 360
[didSet 호출] 200 -> 360
[willSet 호출] 360 -> 896
[didSet 호출] 360 -> 896
🔗 참고한 것
프로퍼티 (Properties) - The Swift Language Guide (한국어)
프로퍼티는 클래스, 구조체, 열거형과 관련한 값입니다. 프로퍼티의 종류에는 저장 프로퍼티(Stored Properties)와 계산된 프로퍼티(Computed Properties)가 있습니다. 저장 프로퍼티는 말 그대로 값을 저
jusung.gitbook.io
iOS 프로그래밍을 위한 스위프트 기초
부스트코스 무료 강의
www.boostcourse.org
'💻 개발 > iOS' 카테고리의 다른 글
[iOS / SwiftUI] ForEach로 View를 리펙토링 해볼까요? (0) | 2022.10.11 |
---|---|
[iOS / Swift] lim 클로저 -> 0 (클로저, 극한으로 줄여보기) (0) | 2022.10.05 |
[iOS / Swift] 상속 VS 익스텐션 (0) | 2022.09.27 |
[TIL] 22.08.25 (0) | 2022.08.25 |
[TIL] 22.08.24 (0) | 2022.08.24 |