ji_iin
iOSLog
ji_iin
전체 방문자
오늘
어제
  • 분류 전체보기 (56)
    • Swift (8)
    • iOS (6)
    • 알고리즘 (34)
    • CS (3)
    • 회고 (3)
    • 제품리뷰 (2)

블로그 메뉴

  • 홈
  • 태그
  • 방명록

공지사항

인기 글

태그

  • 브루트포스 알고리즘
  • 다이나믹 프로그래밍
  • 그래프이론
  • ios
  • 자바
  • 수학
  • 깊이우선탐색
  • 깊은복사와 얕은복사
  • 대기업코테
  • 구조체와 클래스
  • swiftUI
  • 회고
  • SWiFT
  • 개발회고
  • 공식문서
  • 알고리즘
  • opional
  • 그래프탐색
  • 알고리즘개념
  • Bye2023
  • 너비우선탐색
  • 백트래킹
  • 정렬
  • django
  • 재귀
  • 백준
  • 2022년 회고
  • Python
  • 프로그래머스
  • 파이썬

최근 댓글

최근 글

티스토리

hELLO · Designed By 정상우.
ji_iin
Swift

[Swift] 프로퍼티 (Properties)

Swift

[Swift] 프로퍼티 (Properties)

2022. 9. 14. 14:12

프로퍼티

  • 클래스, 구조체, 열거형과 관련한 값
  • 프로퍼티 옵저버를 정의하여 값이 변할때마다 모니터링 가능
  • 저장 프로퍼티 : 값을 저장하고 있음
    • 사용 : 클래스, 구조체
  • 계산된 프로퍼티 : 값을 저장하지 않고, 특정하게 계산한 값을 반환
    • 사용 : 클래스, 구조체, 열거형

저장 프로퍼티 (Stored Properties)

  • 단순히 값을 저장하고 있는 프로퍼티
  • let, var 키워드 이용해서 변수 선언해 사용
struct FixedLengthRange {
    var firstValue: Int
    let length: Int
}
// ---> 변수 구조체 
var rangeOfThreeItems = FixedLengthRange(firstValue: 0, length: 3)
// 범위 값은 0, 1, 2 입니다.
rangeOfThreeItems.firstValue = 6
// 범위 값은 6, 7, 8 입니다.

// ---> 상수 구조체 
let rangeOfFourItems = FixedLengthRange(firstValue: 0, length: 4)
// 범위 값은 0, 1, 2, 3 입니다.
rangeOfFourItems.firstValue = 6
// 에러 발생! 인스턴스의 프로퍼티 값 변경 안됨

지연 저장 프로퍼티 (Lazy Stored Properties)

  • 값이 처음 사용되기 전에는 계산되지 않음
  • lazy property는 반드시 var 로 선언되야 함 !
    • 왜냐하면 상수는 초기화 되기전 항상 값을 갖는 프로퍼티인데, lazy 프로퍼티는 처음 사용되기 전엔 값을 가지지 않으므로
    • (없다 생겨서 변하므로 상수로 선언해야 된다는 뜻인듯)
  • 특정 요소에 의존적이여서 그 요소가 끝나기 전에 적절한 값을 알지 못하는 경우에 유용
  • 복잡한 계산 / 부하가 많이 걸리는 작업 에서 선언해 사용하면 실제 사용 전에 실행되지 않아 인스턴스 초기화 시점에 복잡한 계산 피할 수 있음

예시

  • DataManager는 데이터를 가져오는 DataImporter를 가지고 있음
  • DataImporter 는 실제 디스크 파일에서 데이터를 갖고와서 초기화 때 많은 시간 필요 → 🟢 그래서 importer를 lazy로 선언
  • 🔵DataManager 인스턴스를 생성하고 거기에 data 넣어도 그 시점에 DataImporter 인스턴스는 생성되지 않음.
  • 🟣 importer에 접근하는 순간 그제서야 인스턴스가 생성된다
class DataImporter {
    /*
        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")

🟣 print(manager.importer.filename) 

만약, lazy property가 여러 스레드에서 사용되면 한번만 실행되는 걸 보장하지 않습니다. 단일 스레드에서 사용되면 초기화는 한번만 한다.

계산된 프로퍼티 (Computed Properties)

  • 실제 값을 저장하고 있는게 아니라 getter 와 옵셔널한 setter 를 제
  • 값을 탐색하고 간접적으로 다른 프로퍼티 값을 설정할 수 있는 방법 제공
  • 반드시 var 로 선언되야 함

예시

  • 좌표와 크기를 갖는 사각형을 표현하는 구조체
  • center라는 계산된 프로퍼티를 제공, origin과 size를 이용해서 값을 직접 갖고있는 것이 아닌 적절히 연산해서 구함
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(newCenter) {
            origin.x = newCenter.x - (size.width / 2)
            origin.y = newCenter.y - (size.height / 2)
        }
    }
}
var square = Rect(origin: Point(x: 0.0, y: 0.0),
                  size: Size(width: 10.0, height: 10.0))
let initialSquareCenter = square.center
square.center = Point(x: 15.0, y: 15.0)
print("square.origin is now at (\\(square.origin.x), \\(square.origin.y))")
// "square.origin is now at (10.0, 10.0)" 출력
  • setter에서 인자이름을 명시하지 않으면 기본 인자이름인 newValue 사용
set {
        origin.x = newValue.x - (size.width / 2)
        origin.y = newValue.y - (size.height / 2)
    }

읽기전용 계산된 프로퍼티 (Read-Only Computed Properties)

  • getter만 있고, setter 없음
  • 반환 값을 제공하고, 다른 값을 지정할 수는 없는 프로퍼티
  • 반드시 var 로 선언되야 함.
  • 보통 read-only는 한번 정해지면 변하지 않아 let 으로 선언하는 것이 맞으나, 계산된 프로퍼티는 read-only라도 계산 값에 따라 변경되기 때문에 var로 선언되야한다.

예시

  • volume 이라는 읽기전용 계산된 프로퍼티 사용
struct Cuboid {
    var width = 0.0, height = 0.0, depth = 0.0
    var volume: Double {
        return width * height * depth
    }
}
let fourByFiveByTwo = Cuboid(width: 4.0, height: 5.0, depth: 2.0)
print("the volume of fourByFiveByTwo is \\(fourByFiveByTwo.volume)")
// "the volume of fourByFiveByTwo is 40.0" 출력

프로퍼티 옵져버 (Property Observers)

  • 프로퍼티에 새 값이 set 될 때마다 이벤트를 감지할 수 있는 옵져버 제공
  • 새 값이 이전과 같아도 항상 호출됨
  • 지연 저장 프로퍼티(lazy) 에서는 사용할 수 없음
  • 서브 클래스의 프로퍼티에 옵저버 정의하는 것 가능
  • computed property는 setter에서 이미 값의 변화를 감지하기 때문에 옵져버 정의할 필요 없음

종류

  • willSet : 값이 저장되기 바로 직전에 호출, 파라미터명 지정하지 않으면 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

만약, in-out 파라미터로 선언된 함수의 인자에 프로퍼티 넘기면 willSet , didSet 항상 실행된다. in-out 파라미터는 프로퍼티가 항상 copy 되기 때문에, 원래 값에 새 값을 다시 덮어쓰게 된다.

전역변수와 지역변수

  • computed property, 옵저버 기능 모두 전역변수와 지역변수에 사용 가능
  • 전역 상수와 변수는 지연 저장 프로퍼티와 같이 지연 계산(lazy computed)된다. 하지만 lazy 키워드 붙일 필요 없음 (전역으로 사용되는 상수, 변수는 값이 사용될 때 변경되어서 인가..?)
  • 반면 지역상수와 변수는 지연 계산될 수 없음

타입 프로퍼티(Type Properties)

  • 특정 인스턴스에 속한 프로퍼티
  • 새로운 인스턴스가 생성될 때마다 새로운 프로퍼티도 같이 생성
  • 특정 타입에 속한 프로퍼티로 그 타입에 해당하는 하나의 프로퍼티만 생성
  • 특정 타입의 모든 인스턴스에 공통으로 사용되는 값을 정의할 때 유용
  • 인스턴스 프로퍼티와 다르게, 항상 초기값을 지정해서 사용해야함 ! 왜냐 타입 자체에는 초기자가 없어 초기화 할 곳이 없기 때문..

타입 프로퍼티 구문 (Type Property Syntax)

  • 타입 프로퍼티 선언 : static 키워드로 선언
  • 클래스에서 선언 : static , class(overriding 가능)로 타입 프로퍼티 선언
struct SomeStructure {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 1
    }
}
enum SomeEnumeration {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 6
    }
}
class SomeClass {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 27
    }
		//enable to overriding
    class var overrideableComputedTypeProperty: Int {
        return 107
    }
}
저작자표시 (새창열림)

'Swift' 카테고리의 다른 글

Swift Concurrency 1 : async/await 시작하기 (동기/비동기 그리고 동시성 개념)  (0) 2024.08.11
[Swift] 접근제어자 (Access Control)  (0) 2022.05.16
[Swift] inout parameter  (0) 2022.01.05
[Swift] 타입 캐스팅(Type Casting) - in / as 키워드  (0) 2021.11.27
[Swift] Optinoal이란? Wrapping/Unwrapping  (0) 2021.10.02
  • 프로퍼티
  • 저장 프로퍼티 (Stored Properties)
  • 지연 저장 프로퍼티 (Lazy Stored Properties)
  • 예시
  • 계산된 프로퍼티 (Computed Properties)
  • 예시
  • 읽기전용 계산된 프로퍼티 (Read-Only Computed Properties)
  • 예시
  • 프로퍼티 옵져버 (Property Observers)
  • 종류
  • 전역변수와 지역변수
  • 타입 프로퍼티(Type Properties)
  • 타입 프로퍼티 구문 (Type Property Syntax)
'Swift' 카테고리의 다른 글
  • Swift Concurrency 1 : async/await 시작하기 (동기/비동기 그리고 동시성 개념)
  • [Swift] 접근제어자 (Access Control)
  • [Swift] inout parameter
  • [Swift] 타입 캐스팅(Type Casting) - in / as 키워드
ji_iin
ji_iin
개발성장일지🐥

티스토리툴바

단축키

내 블로그

내 블로그 - 관리자 홈 전환
Q
Q
새 글 쓰기
W
W

블로그 게시글

글 수정 (권한 있는 경우)
E
E
댓글 영역으로 이동
C
C

모든 영역

이 페이지의 URL 복사
S
S
맨 위로 이동
T
T
티스토리 홈 이동
H
H
단축키 안내
Shift + /
⇧ + /

* 단축키는 한글/영문 대소문자로 이용 가능하며, 티스토리 기본 도메인에서만 동작합니다.