ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Review of Implement a Custom Control (1) - FoodTracker
    iOS/๐Ÿค– App 2021. 1. 21. 22:59

    ์ด ์žฅ์—์„œ ํ•ด๋ณธ ๊ฒƒ๋“ค

    1. Custom source code ๋ฅผ ์ž‘์„ฑํ•˜๊ณ  ๊ทธ๊ฒƒ์„ stroyboard ๋‚ด์˜ ์š”์†Œ๊ณผ ์—ฐ๊ฒฐํ•˜๊ธฐ

    2. Container view๋กœ์„œ UIStackView ์‚ฌ์šฉํ•˜๊ธฐ

    3. ์ฝ”๋“œ๋กœ view ๋“ค์„ ์ƒ์„ฑํ•˜๊ธฐ

    4. ์ ‘๊ทผ์„ฑ ์ •๋ณด๋ฅผ custom control ์— ์ถ”๊ฐ€ํ•˜๊ธฐ

    5. @IBInspectable, @IBDesignable ์‚ฌ์šฉํ•˜์—ฌ Interface Builder์—์„œ custom view ๋ฅผ ๋„์šฐ๊ณ , ์กฐ์ž‘ํ•˜๊ธฐ


     

    Create a Custom View

    Container View ์ธ UIStackView ์•ˆ์— 5๊ฐœ์˜ UIButton ์„ ๋„ฃ์–ด์„œ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

     

    UIButton ์€ ์„œ๋ธŒํด๋ž˜์‹ฑํ•˜์—ฌ Custom control ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

     

    ๋งŒ๋“ค์–ด๋ณผ Custom Control ์˜ ๊ตฌ์„ฑ

    ์ด contol ์„ ํ†ตํ•ด ์‚ฌ์šฉ์ž๋Š” meal ( ์Œ์‹ ) ์„ ํ‰๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

     

    ์‚ฌ์šฉ์ž๊ฐ€ ํŠน์ • ๋ณ„์„ tap ํ•˜๋ฉด, ํŠน์ • ๋ณ„์„ ํฌํ•จํ•œ ์ด์ „์˜ ๋ณ„๊นŒ์ง€ ๋ชจ๋‘ ๊ฒ€์€์ƒ‰์œผ๋กœ ์ฑ„์›Œ์ง‘๋‹ˆ๋‹ค.

     

    ์˜ˆ๋ฅผ ๋“ค์–ด ์‚ฌ์šฉ์ž๊ฐ€ ๊ฐ€์žฅ ์˜ค๋ฅธ์ชฝ์˜ ๋ณ„์„ tap ํ•œ๋‹ค๋ฉด, ๋ชจ๋“  ๋ณ„์ด ๊ฒ€์€์ƒ‰์œผ๋กœ ์ฑ„์›Œ์งˆ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

     

    ๊ทธ๋ฆฌ๊ณ  ์ฑ„์›Œ์ง„ ๋ณ„ ์ค‘ ๊ฐ€์žฅ ์˜ค๋ฅธ์ชฝ์˜ ๋ณ„์„ ๋‹ค์‹œ tap ํ•˜๋ฉด ๋ชจ๋“  ๋ณ„์ด ๋น„์›Œ์ง‘๋‹ˆ๋‹ค.

     

    ์šฐ์„  UIStackView๋ฅผ ์„œ๋ธŒํด๋ž˜์‹ฑํ•œ ์ปค์Šคํ…€ ์ฝ”๋“œ๋ฅผ ๋งŒ๋“ญ๋‹ˆ๋‹ค.

     


    View ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์€ ํฌ๊ฒŒ ๋‘ ๊ฐ€์ง€๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

     

    1. View๋ฅผ ์ฝ”๋“œ๋กœ ์ดˆ๊ธฐํ™”ํ•˜๊ธฐ

    2. Stroyboard ์—์„œ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ

     

    `1 `์—์„œ๋Š” init(frame:)  ๋ฉ”์„œ๋“œ๋กœ view๋ฅผ ์ดˆ๊ธฐํ™” ํ•ฉ๋‹ˆ๋‹ค.

    `2 `์—์„œ๋Š” init?(coder:)  ๋ฉ”์„œ๋“œ๋กœ storyboard์—์„œ view๋ฅผ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค.

     

    Initializer ๋Š” ์‚ฌ์šฉํ•  ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ค€๋น„ํ•ด์ฃผ๋Š” ๋ฉ”์„œ๋“œ๋ผ๋Š” ๊ฒƒ์„ ์ƒ๊ธฐํ•˜์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

    ์—ฌ๊ธฐ์„œ ์ค€๋น„ํ•ด์ค€๋‹ค๋Š” ๊ฒƒ์€ ์ธ์Šคํ„ด์Šค์˜ ๊ฐ ์†์„ฑ์„ ์ดˆ๊ธฐํ™”ํ•ด์ฃผ๊ณ  ๋‹ค๋ฅธ setup ๋“ค์„ ์ˆ˜ํ–‰ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

     

    ์•ฑ์„ ์„ค๊ณ„ํ•  ๋•Œ, Interface Builder ๋Š”  view ๋ฅผ canvas ์— ์ถ”๊ฐ€ํ•  ๋•Œ ์ฝ”๋“œ๋ฅผ ์ด์šฉํ•ด view๋ฅผ ์ธ์Šคํ„ด์Šคํ™” ํ•ฉ๋‹ˆ๋‹ค.

    ์•„๋ž˜ ๋‹จ๊ณ„๋ฅผ ์ง„ํ–‰ํ•˜๋‹ค๋ณด๋ฉด, view์™€ ์—ฐ๊ฒฐ๋œ ๊ด€๋ จ ์ฝ”๋“œ๊ฐ€ ๋”ฐ๋กœ ์—†์œผ๋ฉด Inspector configuration ์—๋”ฐ๋ผ ์ ์šฉํ•จ์„ ์•Œ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     

    ์•ฑ์„ ์‹คํ–‰ํ•  ๋•Œ, ์•ฑ์€ stroyboard ์—์„œ view๋ฅผ ๋ถˆ๋Ÿฌ์˜ต๋‹ˆ๋‹ค.

     

    ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— ์œ„ ๋‘ Initialization ๋ชจ๋‘ ๊ตฌํ˜„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

    class RatingControl: UIStackView {
      
      //MARK: Initialization
      override init(frame: CGRect) {
        super.init(frame: frame)
      }
      
      required init(coder: NSCoder) {
        super.init(coder: coder)
      }
    }

    NOTE

    Swift๋Š” ํด๋ž˜์Šค์— ์–ด๋– ํ•œ Initializer๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์„ ๋•Œ, ์ž๋™์œผ๋กœ super class ์˜ ๋ชจ๋“  designated initializer ๋ฅผ ์ƒ์†ํ•ฉ๋‹ˆ๋‹ค.

     

    ๋งŒ์•ฝ ํ•œ ๊ฐœ ์ด์ƒ์˜ initializer ๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•œ๋‹ค๋ฉด, ๋” ์ด์ƒ super class ์˜ ๋ชจ๋“  designated initializer ๋“ค์€ ์ž๋™์œผ๋กœ ์ œ๊ณต๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

     

    ๋”ฐ๋ผ์„œ ์ด ๊ฒฝ์šฐ super class์— `required` initializer๊ฐ€ ์žˆ๋‹ค๋ฉด ๋ฐ˜๋“œ์‹œ ๊ตฌํ˜„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

     

    ์ถ”๊ฐ€์ ์œผ๋กœ sub class ๋Š” ๊ตฌํ˜„ํ•œ super class ์˜ `required` initializer ์•ž์— `required` ํ‚ค์›Œ๋“œ๋ฅผ ๋ฐ˜๋“œ์‹œ ๋ถ™์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.



     

    Display the Custom View

    Story board ์—์„œ Object Library ๋กœ Horizontal Stack View ๋ฅผ  ์”ฌ์— ์ถ”๊ฐ€ ํ•œ ํ›„,

    Identity Inspector๋ฅผ ํ†ตํ•ด ์œ„์—์„œ ์ž‘์„ฑํ•œ `RatingControl` Class ์™€ ์—ฐ๊ฒฐํ•˜์˜€์Šต๋‹ˆ๋‹ค.


     

    Add Buttons to the View

     

    ์ฝ”๋“œ๋กœ ์Šคํƒ ๋ทฐ์— ๋ฒ„ํŠผ์ถ”๊ฐ€ํ•˜๊ธฐ

     

    ์œ„ ๋‹จ๊ณ„์—์„œ, ์ €๋Š” `RatignControl` ์ด๋ผ๋Š” UIStackView ๋ฅผ ์„œ๋ธŒํด๋ž˜์‹ฑํ•œ Custom class ๋ฅผ ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

     

    ์ด์ œ ์ด View ์— ๋ฒ„ํŠผ(UIButton) ์„ ์ถ”๊ฐ€ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

     

    ์œ„์˜ ๋‘ ๊ฐœ์˜ Initializer ์ค‘ ์–ด๋–ค ๋ฉ”์†Œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜๋”๋ผ๋„ ๋ฒ„ํŠผ์ด ์ถ”๊ฐ€๋˜์–ด์•ผ ํ•  ๊ฒƒ ์ž…๋‹ˆ๋‹ค.

     

    ๋”ฐ๋ผ์„œ private method๋กœ ๋ฒ„ํŠผ์„ ์ƒ์„ฑํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑ ํ›„ ๋‘ ๊ฐœ์˜ Initializer์— ๋ชจ๋‘ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

    Here, you are using one of the UIButton class’s convenience initializers. `UIButton()`

    This initializer calls init(frame:) and passes in a zero-sized rectangle.

      //MARK: Private Methods
      private func setupButtons() {
        
        // Create the button
        let button = UIButton()
        button.backgroundColor = .red
        
        // Add constraints
        /* 1 */
        button.translatesAutoresizingMaskIntoConstraints = false
        
        /* 2 */
        button.heightAnchor.constraint(equalToConstant: 44.0).isActive = true
        
        /* 3 */
        button.widthAnchor.constraint(equalToConstant: 44.0).isActive = true
    
        // Add the button to the stack
        /* 4 */
        addArrangedSubview(button)
      }

    /* 1 */ ์€ ๋ฒ„ํŠผ์˜ constraints ๊ฐ€ ์ž๋™์œผ๋กœ ์ƒ์„ฑ๋˜๋Š” ๊ฒƒ์„ ๋ง‰์Šต๋‹ˆ๋‹ค.

     

    view ๋ฅผ ์ฝ”๋“œ์—์„œ ์ธ์Šคํ„ด์Šคํ™” (Instantiate) ํ•  ๋•Œ, translatesAutoresizingMaskIntoConstraints ์˜ ๊ธฐ๋ณธ ๊ฐ’์€ true ์ž…๋‹ˆ๋‹ค.

     

    ์ด๊ฒƒ์€ layout engine ์ด view ์˜ ์†์„ฑ์ธ frame ๊ณผ autoresizingMask ์— ๊ธฐ๋ฐ˜ํ•ด ์ž๋™์œผ๋กœ view์˜ ํฌ๊ธฐ์™€ ์œ„์น˜๋ฅผ ์„ค์ •ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

     

    ๋ณดํ†ต AutoLayout ์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด, ์ด autogenerated constraints ๋“ค ๋Œ€์‹  ์ง์ ‘ ์„ค์ •ํ•œ ๊ฐ’์„ ์“ฐ๊ณ  ์‹ถ์–ดํ•ฉ๋‹ˆ๋‹ค.

    ๋”ฐ๋ผ์„œ false ๋กœ ์„ค์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

    Layout engine์ด ์ž๋™์œผ๋กœ ์ƒ์„ฑํ•œ constraints = autogenerated constraints

     

    /* 2 */ ์™€  /* 3 */ ์—์„œ heightAnchor ์™€ widthAnchor ๋Š” view์˜ ๋†’์ด์™€ ๋„“์ด๋ฅผ ์„ค์ •ํ•˜๋Š” constraints ๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค.

     

    1. Button์˜ heightAnchor ์™€ widthAnchor ์†์„ฑ์€ layout anchor ๋กœ์˜ ์ ‘๊ทผ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. ์ด layout anchor๋ฅผ ํ†ตํ•˜์—ฌ constraints๋ฅผ ์ƒ์„ฑํ•ฉ๋‹ˆ๋‹ค. - ์œ„ ์ฝ”๋“œ์˜ ๊ฒฝ์šฐ view ์˜ height ์™€ width๋ฅผ ๊ฐ๊ฐ ์ •์˜ํ•˜๋Š” constraints ๋ฅผ ์ƒ์„ฑํ•˜์˜€์Šต๋‹ˆ๋‹ค.

     

    2. Anchor์˜ constraint(equalToConstant:) ๋ฉ”์„œ๋“œ๋Š” immutable ํ•œ height ํ˜น์€ width ํฌ๊ธฐ๋ฅผ ๋ถ€์—ฌํ•˜๋Š” constraint๋ฅผ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

     

    3. Constraints ์˜ isActive ์†์„ฑ์„ ํ†ตํ•ด ํ™œ์„ฑ/๋น„ํ™œ์„ฑ์„ ๊ฒฐ์ •ํ•ฉ๋‹ˆ๋‹ค. ๊ฐ’์ด true๋ผ๋ฉด, ์‹œ์Šคํ…œ์€ ๋งž๋Š” view ์— constraints ๋ฅผ ์ถ”๊ฐ€ํ•˜๊ณ  ํ™œ์„ฑํ™” ํ•ฉ๋‹ˆ๋‹ค.

     

    ๊ฒฐ๊ณผ์ ์œผ๋กœ /* 1 */ /* 2 */ /* 3 */ ์„ ํ†ตํ•ด Button ์„ ๊ณ ์ •๋œ ํฌ๊ธฐ์˜ object๋กœ ์ •์˜ํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. ( 44 points x 44 points )

     

    /* 4 */ ์—์„œ addArrangedSubview( )  ๋ฉ”์„œ๋“œ๋Š” RatingControl ์Šคํƒ๋ทฐ๊ฐ€ ๊ด€๋ฆฌํ•˜๋Š” view์˜ ๋ฆฌ์ŠคํŠธ์— button ์„ ๋„ฃ๋Š” ์ฝ”๋“œ์ž…๋‹ˆ๋‹ค.

    ์ด ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด button์€ RatingControl์˜ subview๊ฐ€ ๋˜๊ณ , RatingControl ์—๊ฒŒ RatingControl ๋‚ด๋ถ€์—์„œ button ์˜ ์œ„์น˜๋ฅผ ๊ด€๋ฆฌํ•  contstraints๋ฅผ ์ƒ์„ฑํ•˜๋„๋ก ์•Œ๋ ค์ค๋‹ˆ๋‹ค.


     

    ์ฝ”๋“œ๋กœ ๋ฒ„ํŠผ์— ์•ก์…˜ ์ถ”๊ฐ€ํ•˜๊ธฐ

    private func setUpButton() {
      ...
    
      button.addTarget(self, action: #selector(self.ratingButtonTapped(button:)), for: .touchUpInside)
      
      addArrangedSubView(button)
    }
    
    @objc func ratingButtonTapped(button: UIButton) {
      //code
    }

     

    ์œ„ ์ฝ”๋“œ๋Š” target-action pattern ์„ ์ฝ”๋“œ๋กœ ๊ตฌํ˜„ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

     

    addTarget(_, action:, for) ๋ฉ”์„œ๋“œ๋ฅผ ์ด์šฉํ•ฉ๋‹ˆ๋‹ค. button ์—์„œ ์ด ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด button์— touchUPInside ์ด๋ฒคํŠธ๊ฐ€ ๋ฐœ์ƒํ• ๋•Œ๋งˆ๋‹ค ratingButtonTapped(button:) ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.

     

    addTarget(_, action:, for) ๋ฉ”์„œ๋“œ๋ฅผ ์ž์„ธํ•˜๊ฒŒ ๋ถ„์„ ํ•ด๋ณด๋ฉด:

     

    ์ฒซ๋ฒˆ์งธ parameter ์—๋Š” target ์ด ๋“ค์–ด๊ฐ€๋Š”๋ฐ, action์„ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค์— ์ „๋‹ฌํ•ด์•ผํ•˜๋ฏ€๋กœ `self ๊ฐ€ ๋˜๊ฒ ์Šต๋‹ˆ๋‹ค.

     

    ๋‘๋ฒˆ์งธ parameter ์—์„œ #selector ๋Š” ์ฃผ์–ด์ง„ ๋ฉ”์„œ๋“œ์˜ Selector ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

     

    Selector๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์‹๋ณ„ํ•˜๋Š” ๋ถˆํˆฌ๋ช…ํ•œ ๊ฐ’ ์ž…๋‹ˆ๋‹ค.

     

    ์˜ค๋ž˜๋œ API๋“ค์€ ๋ฉ”์„œ๋“œ๋“ค์„ ๋™์ ์œผ๋กœ ๋ถ€๋ฅผ๋•Œ selector๋ฅผ ์‚ฌ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.

     

    performSelector(_:) and addTarget(_:action:forControlEvents:) ๊ฐ€ ๊ทธ ์˜ˆ๊ฐ€ ๋˜๊ณ  ์•„์ง ์‚ฌ์šฉํ•˜๋Š” API์ž…๋‹ˆ๋‹ค.

     

    #selector(RatingControl.ratingButtonTapped(_:)) ๊ฐ€ ratingButtonTapped(_:) action method ์˜ selector ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•ด ์ค๋‹ˆ๋‹ค.

     

    ์„ธ๋ฒˆ์งธ parameter ์—๋Š” UIControlEvents ํƒ€์ž…์ด ๋“ค์–ด๊ฐ‘๋‹ˆ๋‹ค. ์ด ํƒ€์ž…์€ control ์ด ๋ฐ˜์‘ํ•  ์ˆ˜ ์žˆ๋Š” ์ด๋ฒคํŠธ์˜ ์ข…๋ฅ˜๋ฅผ ์ •์˜ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.

     

    ์œ„ ์ฝ”๋“œ์—์„œ๋Š” .touchUpInside ์ด๋ฒคํŠธ๋ฅผ parameter๋กœ ์ „๋‹ฌํ•˜์˜€์Šต๋‹ˆ๋‹ค.

     

    ๋งˆ์ง€๋ง‰์œผ๋กœ, Interface Builder ๋กœ ์•ก์…˜์„ ์—ฐ๊ฒฐํ•˜๊ณ  ์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์—, IBAction attribute ๋ฅผ action ๋ฉ”์„œ๋“œ ์•ž์— ์ •์˜ํ•  ํ•„์š”๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋ฉ”์„œ๋“œ์˜ parameter ์˜ต์…˜์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

    func doSomething()
    
    /* ๋ฉ”์„œ๋“œ๋ฅผ ํ˜ธ์ถœํ•œ control ์ธ์Šคํ„ด์Šค ์ „๋‹ฌ */
    func doSomething(sender: UIButton)
    
    /* control ์ธ์Šคํ„ด์Šค plus ๋ฐœ์ƒํ•œ ์ด๋ฒคํŠธ ์ข…๋ฅ˜ ์ „๋‹ฌ */
    func doSomething(sender: UIButton, forEvent event: UIEvent)

    N O T E

     

    ๊ด€๋ จ ๊ธ€: woozzang.tistory.com/50

     

    ์ถ”๊ฐ€์ ์œผ๋กœ `Touch Up Inside` ๋Š” ์ด๋ฒคํŠธ์˜ ์ข…๋ฅ˜๋กœ์„œ, ์ผ๋ฐ˜์ ์œผ๋กœ ์ƒ๊ฐํ•˜๋Š” ํƒญ ๋™์ž‘์— ๋ฐœ์ƒํ•˜๋Š” ์ด๋ฒคํŠธ์ž…๋‹ˆ๋‹ค.

     

    ์—„๋ฐ€ํžˆ ์ด์•ผ๊ธฐํ•˜๊ธฐ ์œ„ํ•ด `Touch Up Outside` ์ด๋ฒคํŠธ์™€ ๋น„๊ตํ•ด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

     

    ์‚ฌ์šฉ์ž์˜ ๋™์ž‘์„ ์ผ๋‹จ Touch์™€ Up์œผ๋กœ ๋ถ„๋ฆฌํ•ด์„œ ์ƒ๊ฐํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

     

    ๋ง ๊ทธ๋Œ€๋กœ 1. (์†๊ฐ€๋ฝ์œผ๋กœ) ํ„ฐ์น˜ํ•˜๋Š” ๋™์ž‘๊ณผ 2. (์†๊ฐ€๋ฝ์„) ๋–ผ๋Š” ๋™์ž‘์œผ๋กœ ๊ตฌ๋ถ„ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

     

    Touch Up Inside ๋Š” ๋ทฐ๋ฅผ ํ„ฐ์น˜ํ•˜๊ณ  ์žˆ๋Š” ์ƒํƒœ์—์„œ ํ•ด๋‹น ๋ทฐ์˜ ๋ฐ”์šด๋”๋ฆฌ ๋‚ด(Inside)์—์„œ ์†๊ฐ€๋ฝ์„ ๋–ผ๋ฉด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

     

    ์ผ๋ฐ˜์ ์ธ ํƒญ ๋™์ž‘์ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

     

    Touch Up Outside ๋Š” ๋ทฐ๋ฅผ ํ„ฐ์น˜ํ•˜๊ณ  ์žˆ๋Š” ์ƒํƒœ์—์„œ ๋“œ๋ž˜๊ทธํ•œ ์ฑ„๋กœ ์ด๋™ํ•˜์—ฌ ๋ทฐ์˜ ๋ฐ”์šด๋”๋ฆฌ ๋ฐ”๊นฅ(Outside)์—์„œ ์†๊ฐ€๋ฝ์„ ๋–ผ๋ฉด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.


     

     

     

    ๋!


     

    ๋Œ“๊ธ€

์–ด์ œ๋ณด๋‹ค ๋ฐœ์ „ํ•œ ๋‚˜