๐Ÿ‘€Property์™€ Property Observer?

sangheeยท2021๋…„ 9์›” 21์ผ
0

๐Ÿ‘iOS ์Šคํ„ฐ๋””

๋ชฉ๋ก ๋ณด๊ธฐ
4/10
post-thumbnail

ํ”„๋กœํผํ‹ฐ๋ž€?

ํ”„๋กœํผํ‹ฐ๋Š” ํด๋ž˜์Šค, ๊ตฌ์กฐ์ฒด, ์—ด๊ฑฐํ˜•๊ณผ ๊ด€๋ จ๋œ ๊ฐ’์ด๋‹ค. ํ”„๋กœํผํ‹ฐ์˜ ์ข…๋ฅ˜๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

  • ์ €์žฅ ํ”„๋กœํผํ‹ฐ: ๊ฐ’์„ ์ €์žฅํ•˜๊ณ  ์žˆ๋‹ค. ํด๋ž˜์Šค์™€ ๊ตฌ์กฐ์ฒด์—์„œ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ: ๊ฐ’์„ ์ €์žฅํ•˜์ง€ ์•Š๊ณ  ๊ณ„์‚ฐํ•œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•œ๋‹ค. ํด๋ž˜์Šค, ๊ตฌ์กฐ์ฒด ์—ด๊ฑฐํ˜• ๋ชจ๋‘ ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•˜๋‹ค.

์ €์žฅ ํ”„๋กœํผํ‹ฐ(Stored Properties)

let ํ˜น์€ var๋กœ ์„ ์–ธํ•œ๋‹ค.

struct FixedLengthRange {
    var firstValue: Int
    let length: Int
}

var rangeOfThree = FixedLengthRange(firstValue: 0, length: 3)
rangeOfThree.firstValue = 6
rangeOfThree.length = 4 // error

์œ„์˜ ์˜ˆ์ œ์—์„œ rangeOfThree๋Š” var๋กœ ์„ ์–ธ๋˜์—ˆ๊ธฐ ๋•Œ๋ฌธ์— ํ”„๋กœํผํ‹ฐ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค. ๋ฐ˜๋ฉด ๊ตฌ์กฐ์ฒด๊ฐ€ ์•„๋‹ˆ๋ผ ํด๋ž˜์Šค๋Š” let์œผ๋กœ ์„ ์–ธํ•˜๋”๋ผ๋„ ์ฐธ์กฐ ํƒ€์ž…์ด๊ธฐ์— ํ”„๋กœํผํ‹ฐ๋ฅผ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋‹ค.

class FixedLengthRange {
    var firstValue = 0
    var length = 3
}

let rangeOfFour = FixedLengthRange()
rangeOfFour.length = 4

print(rangeOfFour.length) // 4

์ง€์—ฐ ์ €์žฅ ํ”„๋กœํผํ‹ฐ(Lazy Stored Properties)

๊ฐ’์ด ์ฒ˜์Œ ์‚ฌ์šฉ๋  ๋•Œ ๊ณ„์‚ฐ๋˜๋Š” ํ”„๋กœํผํ‹ฐ์ด๋‹ค. ๋ฐ˜๋“œ์‹œ var๋กœ ์„ ์–ธํ•ด์•ผ ํ•œ๋‹ค. ํŠน์ • ์š”์†Œ์— ์˜์กด์ ์ด๊ฑฐ๋‚˜ ๊ณ„์‚ฐ์ด ๋ณต์žกํ•œ ๊ฒฝ์šฐ lazy๋กœ ์„ ์–ธํ•œ๋‹ค.

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("More data")

์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ(Computed Properties)

์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ๋Š” getter์™€ setter๋ฅผ ์ด์šฉํ•ด ๊ฐ’์„ ํƒ์ƒ‰ํ•˜๊ณ  ๊ฐ„์ ‘์ ์œผ๋กœ ๋‹ค๋ฅธ ํ”„๋กœํผํ‹ฐ์˜ ๊ฐ’์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค.

์•„๋ž˜์˜ ์˜ˆ์ œ๋ฅผ ๋ณด๋ฉด center๊ฐ€ ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ์— ํ•ด๋‹นํ•œ๋‹ค. center๋Š” origin๊ณผ size์˜ ๊ฐ’์„ ์—ฐ์‚ฐํ•œ ํ›„ ๋‚˜์˜จ ๊ฒฐ๊ณผ๊ฐ’์ด๋‹ค. setter๋ฅผ ์ด์šฉํ•ด center๊ฐ’์ด ๋ณ€๊ฒฝ๋˜๋ฉด origin๊ฐ’์„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋‹ค. newCenter๋ผ๊ณ  ์ธ์ž ์ด๋ฆ„์„ ์ง€์ •ํ•˜์ง€ ์•Š์•„๋„ newValue๋กœ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.

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)
 
square.origin = Point(x: 0.0, y: 0.0)
print("square.center is now at (\(square.center.x), \(square.center.y))")
// square.center is now at (5.0, 5.0)

์ฝ๊ธฐ์ „์šฉ ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ (Read-Only Computed Properties)

getter๋งŒ ์žˆ๊ณ  setter๋ฅผ ์ œ๊ณตํ•˜์ง€ ์•Š๋Š” ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ๋ฅผ ์˜๋ฏธํ•œ๋‹ค. ์ฝ๊ธฐ์ „์šฉ ๋ฟ ์•„๋‹ˆ๋ผ ๋ชจ๋“  ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ๋Š” var๋กœ ์„ ์–ธํ•œ๋‹ค.

ํ”„๋กœํผํ‹ฐ ์˜ต์ €๋ฒ„ (Property Observers)

ํ”„๋กœํผํ‹ฐ ์˜ต์ €๋ฒ„๋Š” ๋ง ๊ทธ๋Œ€๋กœ ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ด€์ฐฐํ•œ๋‹ค. ์ƒˆ ๊ฐ’์ด ์„ค์ •(set)๋˜๋Š” ์ด๋ฒคํŠธ๋ฅผ ๊ฐ์ง€ํ•œ๋‹ค. ์ด ์˜ต์ €๋ฒ„๋Š” ์ง€์—ฐ ์ €์žฅ ํ”„๋กœํผํ‹ฐ์—์„œ๋Š” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

  • willSet: ๊ฐ’์ด ์ €์žฅ๋˜๊ธฐ ๋ฐ”๋กœ ์ง์ „์— ํ˜ธ์ถœ๋œ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ newValue๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
  • didSet: ๊ฐ’์ด ์ €์žฅ๋œ ๋ฐ”๋กœ ์งํ›„์— ํ˜ธ์ถœ๋œ๋‹ค. ๊ธฐ๋ณธ๊ฐ’์œผ๋กœ oldValue๋ฅผ ์‚ฌ์šฉํ•œ๋‹ค.
class StepCounter {
    var totalSteps: Int = 0 {
        willSet {
            print("\(totalSteps) -> \(newValue)")
        }
        didSet {
            print("\(oldValue) -> \(totalSteps)")
        }
    }
}

let stepCounter = StepCounter()
stepCounter.totalSteps = 100
// 0 -> 100
// 0 -> 100
stepCounter.totalSteps = 300
// 100 -> 300
// 100 -> 300

์ฐธ๊ณ  ์‚ฌ์ดํŠธ

https://jusung.gitbook.io/the-swift-language-guide/language-guide/10-properties

profile
๐Ÿ‘ฉโ€๐Ÿ’ป

0๊ฐœ์˜ ๋Œ“๊ธ€