ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Swift] Property Observer (속성 κ°μ‹œμž) λž€?
    iOS/🟠 Swift 2020. 11. 27. 23:18

    1μ°¨ μˆ˜μ •: 2021/06/02

     

    "μ†μ„±κ°’μ˜ 변경을 κ°μ‹œν•œλ‹€"

     

    μ•ˆλ…•ν•˜μ„Έμš”. μ΄λ²ˆμ‹œκ°„μ€ 속성 κ°μ‹œμžμ— λŒ€ν•΄μ„œ μ•Œμ•„λ³΄κ² μŠ΅λ‹ˆλ‹€πŸΆ

     

    μ²˜μŒμ—λŠ” 문법 μ •λ„λ§Œ 적은 κΈ€μ΄μ—ˆλŠ”λ°, λ°°μš°λ‹€ λ³΄λ‹ˆ 적고싢은 λ‚΄μš©μ΄ λ§Žμ•„μ Έμ„œ μΆ”κ°€ν•˜κ²Œ λ˜λŠ” 것 κ°™μ•„μš”.

     

    그럼 μ‹œμž‘ν•΄λ³Όκ²Œμš”!!


     

    속성 κ°μ‹œμž(Property Observer) λŠ” 속성(Property) 이 μƒˆλ‘œμš΄ κ°’μœΌλ‘œ λ³€κ²½ 될 λ•Œ 호좜 λ˜λŠ” μ½”λ“œ λΈ”λŸ­μž…λ‹ˆλ‹€.

     

    λΈ”λ‘λ§Œ μΆ”κ°€ν•΄ λ†“μœΌλ©΄ 속성이 변경될 λ•Œλ§ˆλ‹€ ν˜ΈμΆœλ˜μ–΄μ„œ μ†μ„±κ°μ‹œμžλ₯Ό μ‚¬μš©ν•˜λ©΄ μ΄λ²€νŠΈμ— λŒ€μ‘ν•˜κΈ° μ‰½μŠ΅λ‹ˆλ‹€.

    var observingValue: String = "Hello" {
      didSet {
        self.textLabel.text = observingValue
      }
    }

    μœ„μ˜ μ½”λ“œλ₯Ό 예둜 λ“€μžλ©΄, observingValue λΌλŠ” String ν˜•μ‹μ˜ 속성 값이 λ³€κ²½ λ˜μ—ˆμ„ λ•Œ, μ†μ„±κ°μ‹œμžλ‘œ κ΅¬ν˜„ν•œ didSet μ΄λΌλŠ” 블둝은 μžλ™μœΌλ‘œ ν˜ΈμΆœλ©λ‹ˆλ‹€.

     

    그리고 블둝 λ‚΄λΆ€μ—μ„œλŠ” μ–΄λ–€ UITextLabel 의 text λ‚΄μš©μ„ λ³€κ²½λœ obersingValue κ°’μœΌλ‘œ μ μš©μ‹œν‚€κ³  μžˆμŠ΅λ‹ˆλ‹€.


     

    그런데 속성 값이 λ³€κ²½λœλ‹€λŠ” 것이 μ •ν™•νžˆ μ–΄λ–€ 것을 μ˜λ―Έν•˜λŠ”μ§€ μ•„μ‹œλ‚˜μš”?

     

    μ†μ„±κ°μ‹œμžλŠ” μ†μ„±μ˜ ν˜•μ‹μ΄ κ°’ ν˜•μ‹μΌ λ•Œμ™€ μ°Έμ‘° ν˜•μ‹ 일 λ•Œλ₯Ό κ΅¬λΆ„μ§€μ–΄μ„œ μƒκ°ν•˜μ§€ μ•ŠμœΌλ©΄, μ˜ˆμƒν•˜μ§€ λͺ»ν•œ 논리적 였λ₯˜λ₯Ό κ²ͺ을 수 μžˆμŠ΅λ‹ˆλ‹€.

     

    κ°„λž΅νžˆ 이유λ₯Ό λ§μ”€λ“œλ¦¬μžλ©΄,

    κ°’ ν˜•μ‹μ€ 말 κ·ΈλŒ€λ‘œ 값을 λ‹΄κ³  μžˆμ§€λ§Œ, μ°Έμ‘° ν˜•μ‹μ˜ 값은 `ν•΄λ‹Ή 값이 μœ„μΉ˜ν•˜κ³  μžˆλŠ” λ©”λͺ¨λ¦¬μ˜ μ£Όμ†Œ` λ₯Ό λ‚˜νƒ€λ‚΄κΈ° λ•Œλ¬Έμž…λ‹ˆλ‹€.

     

    κ°’ ν˜•μ‹κ³Ό μ°Έμ‘° ν˜•μ‹ 비ꡐ에 κ΄€ν•œ μžμ„Έν•œ λ‚΄μš©μ€ μ œκ°€ 이전에 적은 글을 μ°Έκ³ ν•΄μ£Όμ„Έμš”!

    μ°Έκ³  κΈ€ : Value Type vs Reference Type


     

    Syntax

    μš°μ„  μž‘μ„± 문법뢀터 μ‚΄νŽ΄λ³΄κ² μŠ΅λ‹ˆλ‹€.

    var name: String = "test" {
        willSet {
            print(newValue)
        }
        
        didSet {
            print(oldValue)
        }
    }
    
    name = "abc"
    // prints "abc"   - willSet 블둝이 호좜된 것
    // prints "name"  - didSet 블둝이 호좜된 것
    

    속성 κ°μ‹œμžλŠ” μ„ μ–Έν•œ κ°’ 뒀에 { } 블둝을 μΆ”κ°€ν•˜μ—¬ κ΅¬ν˜„ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

     

    그리고 블둝 μ•ˆμ—λŠ” 두 가지 μ’…λ₯˜μ˜ 블둝 쀑 ν•˜λ‚˜ 이상을 μΆ”κ°€ν•΄μ•Όν•©λ‹ˆλ‹€.

     

    ' willSet ' 블둝은 값이 λ³€κ²½λ˜κΈ° 직전에 ν˜ΈμΆœλ©λ‹ˆλ‹€.

     

    이 블둝 μ•ˆμ—μ„œλŠ” newValue λΌλŠ” μ΄λ¦„μ˜ 속성을 μ‚¬μš© ν•  수 μžˆμŠ΅λ‹ˆλ‹€. 변경될 값을 λ‹΄κ³  μžˆμŠ΅λ‹ˆλ‹€.

     

    λ§Œμ•½ Parameter name 을 μ§€μ •ν•΄μ„œ λ°›λŠ”λ‹€λ©΄ 더이상 newValue λŠ” μ‚¬μš©ν•  수 μ—†κ³ , μ§€μ •ν•œ 이름을 μ‚¬μš©ν•˜κ²Œ λ©λ‹ˆλ‹€.

     

     

    ' didSet ' 블둝은  κ°’이 λ³€κ²½λœ 직후에 호좜 λ©λ‹ˆλ‹€.

     

    이 블둝 μ•ˆμ—μ„œλŠ” oldValue λΌλŠ” μ΄λ¦„μ˜ 속성을 μ‚¬μš© ν•  수 μžˆμŠ΅λ‹ˆλ‹€. λ³€κ²½ μ΄μ „μ˜ 값을 λ‹΄κ³  μžˆμŠ΅λ‹ˆλ‹€.

     

    λ§Œμ•½ Parameter name 을 μ§€μ •ν•΄μ„œ λ°›λŠ”λ‹€λ©΄ 더이상 oldValue λŠ” μ‚¬μš©ν•  수 μ—†κ³ , μ§€μ •ν•œ 이름을 μ‚¬μš©ν•˜κ²Œ λ©λ‹ˆλ‹€.

    :: 보톡 νŒŒλΌλ―Έν„°λ₯Ό μƒλž΅ν•˜κ³  oldValueλ₯Ό κ·ΈλŒ€λ‘œ μ‚¬μš©ν•˜λ”λΌκ΅¬μš” 저도 그게 νŽΈν•œλ“―πŸ€”


     

    νŠΉμ§•

    속성 κ°μ‹œμžλŠ” 일반 μ €μž₯ 속성에 μΆ”κ°€ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

    단, μƒμˆ˜λŠ” ν•œ 번 μ΄ˆκΈ°ν™” 되면 값이 변경될 수 μ—†μœΌλ―€λ‘œ μΆ”κ°€ν• μˆ˜ μ—†μŠ΅λ‹ˆλ‹€.

     

    μΆ”κ°€μ μœΌλ‘œ 상속받은 μ €μž₯ 속성과 계산 속성(Computed Property) μ—λ§Œ 속성 κ°μ‹œμžλ₯Ό μΆ”κ°€ν•  수 μžˆμŠ΅λ‹ˆλ‹€.

     

    μ΄λ•Œ 계산 속성에 기쑴에 μžˆλŠ” getter 와 setter λŠ” κ·ΈλŒ€λ‘œ μž‘λ™ν•©λ‹ˆλ‹€.


     

    κ°’ νƒ€μž… κ³Ό μ°Έμ‘° νƒ€μž…μ—μ„œμ˜ λ™μž‘ 차이🍯

     

    κ°’ νƒ€μž…μ—μ„œλŠ” μ˜ˆμƒ ν•˜μ‹ κ²ƒμ²˜λŸΌ κ°’이 변경될 λ•Œ λ§ˆλ‹€ 호좜이 잘 λ©λ‹ˆλ‹€

     

    μ°Έμ‘° νƒ€μž…μ—μ„œλ„ 값이 변경될 λ•Œ 호좜이 잘 λ˜μ§€λ§Œ,

    단 ν•œκ°€μ§€β—οΈβ—οΈβ—οΈβ—οΈ    κ°’을 λ³€κ²½ν•œ 것같은데 μ‹€μ œλ‘œλŠ” λ³€κ²½λ˜μ§€ μ•ŠλŠ” 경우만 μœ μ˜ν•΄μ£Όλ©΄ λ©λ‹ˆλ‹€.

    import UIKit
    
    class ViewController: UIViewController {
      
      var myImage: UIImageView? {
        didSet {
          print("myImage DidSet")
        }
      }
    
      override func viewDidLoad() {
        super.viewDidLoad()
        
        // 1
        myImage = UIImageView() /// prints "myImage DidSet"
        
        // 2
        myImage!.frame = .zero	/// didSet 호좜이 μΌμ–΄λ‚˜μ§€ μ•ŠλŠ”λ‹€.
      }
    }

     

    μœ„ μ½”λ“œλŠ” λ°‘μ˜ λ¬Έμž₯을 ν•œ 쀄씩 μ½μ–΄λ³΄μ‹œλ©΄ μ–΄λ–€ κ²½μš°μΈμ§€ λ°”λ‘œ μ•Œκ²Œ λ˜μ‹€κ±°μ—μš”!!

     

    * UIImageVIew ν΄λž˜μŠ€λŠ” μ°Έμ‘° νƒ€μž…μž…λ‹ˆλ‹€.

     

    * μ°Έμ‘° νƒ€μž…μ˜ 값은 [값이 μ €μž₯된 μ£Όμ†Œ κ°’] μž…λ‹ˆλ‹€.

     

    * μ°Έμ‘° μΈμŠ€ν„΄μŠ€μ˜ 속성을 변경해도 μ£Όμ†Œ 값은 λ°”λ€Œμ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

     

    <1번 μ½”λ“œμ—μ„œ>

    μ΅œμ΄ˆμ— nil 둜 μ΄ˆκΈ°ν™” λ˜μ—ˆλ˜ myImageλŠ” 1번 μ½”λ“œμ—μ„œ μƒˆλ‘œμš΄ μΈμŠ€ν„΄μŠ€λ₯Ό μ–»κ²Œ λ˜μ—ˆμŠ΅λ‹ˆλ‹€!!

    더 μ •ν™•νžˆ λ§ν•˜λ©΄ μ°Έμ‘° 값을 μ–»κ²Œ λ˜μ—ˆμ£ .

    κ·Έλž˜μ„œ κ°’μ˜ 변경이 μΌμ–΄λ‚¬μŠ΅λ‹ˆλ‹€. [ nil -> (μ£Όμ†Œ κ°’) ]

    didSet이 ν˜ΈμΆœλ©λ‹ˆλ‹€.

     

    <2번 μ½”λ“œμ—μ„œ>

     myImage μΈμŠ€ν„΄μŠ€μ˜ 속성을 λ³€κ²½ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

    μ°Έμ‘° νƒ€μž…μ—μ„œ 속성 λ³€κ²½λ§ŒμœΌλ‘œλŠ” μ£Όμ†Œκ°€ λ³€κ²½λ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.

    κ°’μ˜ 변경이 μ—†μœΌλ‹ˆ didSet은 ν˜ΈμΆœλ˜μ§€ μ•ŠμŠ΅λ‹ˆλ‹€.


     

    μΆ”κ°€ 정보

    NOTE 1

    The willSet and didSet observers of superclass properties are called when a property is set in a subclass initializer, after the superclass initializer has been called. They aren’t called while a class is setting its own properties, before the superclass initializer has been called.

    For more information about initializer delegation, see Initializer Delegation for Value Types and Initializer Delegation for Class Types.

     

    ν•œ 쀄 μš”μ•½

    수퍼클래슀의 속성 κ°μ‹œμžλŠ” μ„œλΈŒν΄λž˜μŠ€μ˜ μ΄ˆκΈ°ν™” κ³Όμ •μ—μ„œ 수퍼클래슀의 μ΄ˆκΈ°ν™”κ°€ μ™„λ£Œλœ 이후에 λ™μž‘ν•œλ‹€.

    Initializer Delegation 에 μ˜ν•œ μ„œλΈŒν΄λž˜μŠ€μ˜ μ΄ˆκΈ°ν™” 과정에 λŒ€ν•΄ μ•Œκ³  κ³„μ‹ κ°€μš”? β†—οΈβ†˜οΈ

     

     

    NOTE 2

    If you pass a property that has observers to a function as an in-out parameter, the willSet and didSet observers are always called. This is because of the copy-in copy-out memory model for in-out parameters: The value is always written back to the property at the end of the function. For a detailed discussion of the behavior of in-out parameters, see In-Out Parameters.

     

    ν•œ 쀄 μš”μ•½

    속성 κ°μ‹œμžκ°€ 달린 속성을 λ©”μ„œλ“œμ— in-out νŒŒλΌλ―Έν„°λ‘œ μ „λ‹¬ν•˜λ©΄, λ©”μ„œλ“œμ˜ 호좜 μ‹œμ κ³Ό λ°˜ν™˜ μ‹œμ  총 2회 ν˜ΈμΆœλœλ‹€.

    In-Out νŒŒλΌλ―Έν„°μ˜ μ •ν™•ν•œ λ™μž‘μ€ λͺ°λžλŠ”데, μ°Έκ³ ν•˜λ©΄ 쒋을 것 κ°™μŠ΅λ‹ˆλ‹€!

     

     

    끝!


    πŸ€–πŸŸ’[우짱의 iOS λΈ”λ‘œκ·Έ]πŸ”΅πŸ’»

    iOSλ₯Ό κ³΅λΆ€ν•˜λ©΄μ„œ 배운 λ‚΄μš©μ„ κΈ°λ‘ν•˜κ³  μžˆμŠ΅λ‹ˆλ‹€.

     

    참고 자료: https://docs.swift.org/swift-book/LanguageGuide/Properties.html

    'iOS > 🟠 Swift' μΉ΄ν…Œκ³ λ¦¬μ˜ λ‹€λ₯Έ κΈ€

    Mutability of Collections - Collections  (0) 2020.12.01
    Self Type - General  (0) 2020.11.27
    Side Effect - General  (0) 2020.11.24
    Nested Functions - Functions  (0) 2020.11.08
    Function Types - Functions  (0) 2020.11.08

    λŒ“κΈ€

μ–΄μ œλ³΄λ‹€ λ°œμ „ν•œ λ‚˜