-
[Swift] 프로퍼티(Property)- 프로퍼티의 정의, 종류iOS 2022. 8. 9. 22:05
증말 기본적인 개념인데도 그냥 대애충 두루뭉술하게만 알고 넘어갔었더라고요 🥲
막상 구체적으로 문제가 나오니까 확실히 아는게 없는 것 같아서
이번 기회에 한 번 정리해봅니다 ><
목차
프로퍼티란 어떤 대상(클래스,구조체,열거형etc.)에 값을 할당해주는 존재입니다.
프로퍼티는 크게 저장 프로퍼티, 연산 프로퍼티로 나눌 수 있습니다!
저장 프로퍼티 (Stored Properties)
Stored Properties
► 이름에서 알 수 있듯 가장 단순하고 기본적인 개념의 프로퍼티로, 클래스 또는 구조체의 인스턴스와 연관된 값을 저장하는 프로퍼티
► 클래스 / 구조체에서만 사용 가능!! (열거형x)
- 변수 저장 프로퍼티 (variable stored properties) - var 키워드 사용
- 상수 저장 프로퍼티 (constant stored properties) - let 키워드 사용
struct Point { var x: Int // 변수 저장 프로퍼티 let y: Int // 상수 저장 프로퍼티 }
정의에서 봤듯이 어떤 대상 - 이경우에는 Point 라는 구조체에 x,y라는 값을 할당해주는 애들이 프로퍼티 입니다.
Lazy Stored Properties
► lazy라는 키워드를 사용하는 지연 저장 프로퍼티는 호출이 있어야 값을 초기화 합니다.
그 말은, 값이 처음으로 사용 되기 전에는 계산되지 않는다는 말이죠!
► 지연 저장 프로퍼티는 반드시! var로 선언해야 합니다. let 선언은 초기화가 되기 전에 항상 값을 갖는 프로퍼티이기 때문!!!
► 어떨 때 유용할까? 프로퍼티가 특정 요소에 의존적이어서, 그 요소가 끝나기 전에 값을 알 수 없는 경우.
혹은 복잡한 계산, 부하가 많이 걸리는 작업을 lazy로 선언하면 인스턴스 초기화 시점에 복잡한 계산을 피할 수 있읍니당.
► 지연 프로퍼티가 여러 스레드에서 사용되면? 한번만 실행된다는 보장이 x. Thread safe 하지 않음!!
► 단일 스레드에서 사용될 경우 초기화는 한 번!
class DataImporter { /* 겁 나 오 래 걸 리 는 초기화 작업 */ var filename = "data.txt" } class DataManager { lazy var importer = DataImporter() var data = [String]() /* 데이터를 관리하는 기능 */ } let manager = DataManager() manager.data.append("Some data") manager.data.append("Some more data") // DataImporter 인스턴스는 이 시점에 생성돼 있지 x //이렇게 직접 importer 인스턴스에 접근할때야 생성됨 print(manager.importer.filename)
연산 프로퍼티 (Computed Properties)
► 클래스, 구조체, 열거형은 저장 프로퍼티 뿐만 아니라 연산 프로퍼티도 선언할 수 있습니다.
► 저장 프로퍼티와 다르게 실제 값을 저장하고 있는 것이 아니라, 다른 프로퍼티와 간접적으로 값을 검색하고 세팅합니다
그게 바로 getter 와 setter(optional)라는 연산 프로퍼티!
► 계산값에 따라 값이 변할 수 있는 프로퍼티이기 때문에 항상 var 으로 선언!!!
►set(newValue) { ... } 와 같은 구조에서 (newValue)라고 인자이름을 지정하지 않아도 기본 이름인 newValue를 사용할 수 있습니다!
like this
set { origin.x = newValue.x - (size.width / 2) origin.y = newValue.y - (size.height / 2) }
► 예제 1
class P { var x: Int { get { return x } set(newValue) { x = newValue * 2 } } } var p = Point() p.x = 12 // error!
이렇게 하면 에러가 납니다!!!!!
x값이 자기 자신을 리턴하고 자기 자신을 두배로 만들고 있기 때문에 이렇게 사용하면 오류가 납니다.
그래서 getter setter에는 필수적으로 변수가 더 있어야하는데, 이처럼 내부에서 사용하는 변수용으로 사용하는 stored Property는 언더바를 붙인 형태로 구분합니다.
class Test { private var _myProperty: Int var myProperty: Int { get { return _myProperty } set { return _myProperty = newValue } } }
► 예제2
struct Point { var x = 0.0, y = 0.0 } struct Size { var width = 0.0, height = 0.0 } struct Rect { var origin = Point() var size = Size() var center: Point { get { let centerX = origin.x + (size.width / 2) let centerY = origin.y + (size.height / 2) return Point(x: centerX, y: centerY) } set { origin.x = newValue.x - (size.width / 2) origin.y = newValue.y - (size.height / 2) } } }
center라는 Point형 변수에 접근할 때는 origin, size라는 다른 프로퍼티를 이용하여 계산하고, center를 직접 설정할 때는 size를 이용해서 origin을 변경하고 있습니다.
var square = Rect(origin: Point(x: 0.0, y: 0.0), size: Size(width: 10.0, height: 10.0)) let initialSquareCenter = square.center //getter로 square의 center값 가져옴 square.center = Point(x: 15.0, y: 15.0) //setter로 center값 변경 print("square.origin is now at (\(square.origin.x), \(square.origin.y))") // "square.origin is now at (10.0, 10.0)" 출력
프로퍼티 옵저버 (Property Observers)
► 프로퍼티에 새 값이 설정(set)될 때마다 이벤트를 감지할 수 있습니다.
► 지연 저장 프로퍼티(lazy stored properties)에서는 사용할 수 없음!
► 연산 프로퍼티는 setter에서 값의 변화를 감지하므로 따로 옵저버를 정의할 필요가 없음!
► willSet : 값이 저장되기 바로 직전에 호출 (연산프로퍼티의 set에서와 마찬가지로 기본 값으로 newValue라는 파라미터명 사용)
didSet : 값이 저장되고 난 직후에 호출 (oldValue라는 파라미터 사용)► 예제
class StepCounter { var totalSteps: Int = 0 { willSet(newTotalSteps) { print("About to set totalSteps to \(newTotalSteps)") } didSet { if totalSteps > oldValue { print("Added \(totalSteps - oldValue) steps") } } } } let stepCounter = StepCounter() stepCounter.totalSteps = 200 // About to set totalSteps to 200 // Added 200 steps stepCounter.totalSteps = 360 // About to set totalSteps to 360 // Added 160 steps stepCounter.totalSteps = 896 // About to set totalSteps to 896 // Added 536 steps
'iOS' 카테고리의 다른 글
Cocoa touch framework 정리 (0) 2023.01.15 iOS 소셜로그인 구현 - 구글 로그인 연동 (0) 2022.05.16 iOS 소셜 로그인 구현 - 카카오톡 로그인 연동 (0) 2022.05.10 [iOS/Swift] 신입 면접 질문 정리 (22.05.04 업데이트) (0) 2022.05.04 [rxSwift] Swift UItextView 에서 Placeholder설정, DidBeginEditing, DidEndEditing (0) 2021.06.03