iOS/๐Ÿค– App

Review of Implement a Custom Control (2) - Food Tracker

woozzang 2021. 1. 22. 19:05

Add Support for Interface Builder

@IBDesignable

Interface Builder๋Š” view์™€ ์—ฐ๊ฒฐ๋œ ์ปค์Šคํ…€ ์ฝ”๋“œ์— ๋Œ€ํ•ด์„œ ์ „ํ˜€ ๋ชจ๋ฆ…๋‹ˆ๋‹ค.

 

๊ทธ๋ž˜์„œ ์ปค์Šคํ…€ ์ฝ”๋“œ๋ฅผ ๋ฐ˜์˜ํ•˜์ง€ ์•Š์€ ์ฑ„ ์ธ์Šคํ„ด์Šคํ™”ํ•˜์—ฌ canvas์— ๊ทธ๋ฆฝ๋‹ˆ๋‹ค.

 

์ปค์Šคํ…€ ์ฝ”๋“œ๋ฅผ ๋ฐ˜์˜ํ•˜๊ฒŒ ํ•˜๋Š” ๋ฐฉ๋ฒ•์€ custom control code ์•ž์— @IBDesignable attribute ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

 

์ด Attribute ์„ ํ†ตํ•ด Interface Builder ๊ฐ€ canvas์— view๋ฅผ ๊ทธ๋ฆด๋•Œ, ์ปค์Šคํ…€ ์ฝ”๋“œ๋ฅผ ์˜ฌ๋ฐ”๋ฅด๊ฒŒ ๋ฐ˜์˜ํ•˜์—ฌ ๊ทธ๋ฆด ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.

" This lets Interface Builder instantiate and draw a copy of your control directly in the canvas."

 

์ถ”๊ฐ€์ ์œผ๋กœ, Interface Builder ๊ฐ€ custom control์˜ ์ƒ์ƒํ•œ ์นดํ”ผ๋ณธ์„ ๊ฐ€์ง€๊ณ  ์žˆ์œผ๋‹ˆ, ๊ทธ๊ฒƒ์˜ layout engine ์ด control์˜ ์œ„์น˜์™€ ์‚ฌ์ด์ฆˆ๋ฅผ ์ ์ ˆํ•˜๊ฒŒ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

์š”์•ฝ: @IBDesignable์„ ์ถ”๊ฐ€ํ•˜๋ฉด canvas์—์„œ ์ปค์Šคํ…€ ์ฝ”๋“œ์˜ ์ ์šฉ์‚ฌํ•ญ์„ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ( ์ถ”๊ฐ€ํ•˜์ง€ ์•Š์œผ๋ฉด ๋Ÿฐํƒ€์ž„์—์„œ๋งŒ ๊ฐ€๋Šฅ )


 

@IBInspectable

@IBInspectable  attribute๋ฅผ control์˜ ์†์„ฑ ์•ž์— ์ถ”๊ฐ€ํ•˜๋ฉด, Attribute Inspector์— ์ถ”๊ฐ€ํ•œ ์†์„ฑ์ด ๋‚˜ํƒ€๋‚˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

์•„๋ž˜๋Š” ๊ด€๋ จ ์ฝ”๋“œ ์ž…๋‹ˆ๋‹ค

  // StackView Custom Code `RatingControl.swift` ์ค‘
  
  @IBInspectable
  var starSize: CGSize = CGSize(width: 44.0, height: 44.0) {
    didSet {
      setupButtons()
    }
  }
  
  @IBInspectable
  var starCount: Int = 5 {
    didSet {
      setupButtons()
    }
  }

 

ํ•˜์ง€๋งŒ Attribute Inspector์—์„œ ๋ณ€๊ฒฝํ•œ ์†์„ฑ์€ ์ ์šฉ๋˜์ง€ ์•Š์„ ๊ฒƒ์ž…๋‹ˆ๋‹ค.

์•ฑ ๋””์ž์ธ ์‹œ์ ์˜ canvas ์—์„œ๋‚˜ ๋Ÿฐํƒ€์ž„ ๋ชจ๋‘ ์ ์šฉ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๋ณ€๊ฒฝํ•œ ์†์„ฑ ๊ฐ’์„ control์— ์ ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋ณ€๊ฒฝ ์‹œ๋งˆ๋‹ค control์„ ๋ฆฌ์…‹ํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

์†์„ฑ ๊ฐ’์„ ๋ณ€๊ฒฝ์‹œ๋งˆ๋‹ค ํ˜ธ์ถœ๋˜๋Š” Property observer๋ฅผ ์ถ”๊ฐ€ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค. ( ๊ทธ์ค‘ `didSet` )

 

" This code iterates over all of the rating control’s buttons.

First, it removes the button from the list of views managed by the stack view.

This tells the stack view that it should no longer calculate the button’s size and position—but the button is still a subview of the stack view. "

 

์œ„ ๋ฌธ์žฅ์—์„œ ArrangedSubView์— ์ถ”๊ฐ€๋˜๋Š” ๊ฒƒ๊ณผ SubView์˜ ์ถ”๊ฐ€๋˜๋Š” ๊ฒƒ์€ ๋ณ„๊ฐœ๋ผ๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

ArrangedSubView ๋Š” Subview์˜ ๋ถ€๋ถ„์ง‘ํ•ฉ์œผ๋กœ์„œ, SubView์— ์ถ”๊ฐ€๋˜๋Š” ๊ฒƒ์ด ArrangedSubView ์ถ”๊ฐ€๋˜๋Š” ๊ฒƒ์ด๋ผ๊ณ  ๋ณผ ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

 

๋” ์ž์„ธํžˆ ์‚ดํŽด๋ณด๋ฉด, ArrangedSubView์— ์ถ”๊ฐ€๋˜๋ฉด Stack View๋Š” ์ด ์•„์ดํ…œ์˜ size์™€ position์„ ๊ณ„์‚ฐํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

 

๊ด€๋ จ ๊ธ€ 1: arranged subview vs subview- stackoverflow
๊ด€๋ จ ๊ธ€ 2: arranged subview - apple developer documentation

N O T E

 

setUpButton( ) ์˜ ๋กœ์ง์ด ํผํฌ๋จผ์Šค ๊ด€์ ์—์„œ ์ตœ๊ณ ์˜ ์•„์ด๋””์–ด๋Š” ์•„๋‹ˆ์ง€๋งŒ, ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋Š” Interface Builder์— ์˜ํ•ด ์•ฑ design time์— ํ˜ธ์ถœ๋  ๋ฟ์ด๊ณ , ์•ฑ ์‹คํ–‰ ์‹œ์—๋Š” ๋‹จ ํ•œ๋ฒˆ ํ˜ธ์ถœ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฌธ์ œ๊ฐ€ ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.



 

Add Star Images to the Buttons

 

Assets.xcassets ํŒŒ์ผ์— ์ƒˆ๋กœ์šด ํด๋”๋ฅผ ๋งŒ๋“ค๊ณ  3๊ฐ€์ง€ ์ƒํƒœ์˜ ๋ณ„ ์ด๋ฏธ์ง€๋ฅผ ์ถ”๊ฐ€ํ•ฉ๋‹ˆ๋‹ค.

Assets.xcassets ๋Š” asset catalog๋ฅผ ๋‹ด๊ณ  ์žˆ๋Š” ํŒŒ์ผ์ž…๋‹ˆ๋‹ค. Asset catalog๋Š” ์ด๋ฏธ์ง€๋“ค์„ ์ €์žฅํ•˜๊ณ  ๊ด€๋ฆฌํ•˜๋Š” ์žฅ์†Œ์ž…๋‹ˆ๋‹ค.

 

Assets.xcassets ํ™”๋ฉด ๊ตฌ์„ฑ

 

To set star images for the buttons

 

Assets catalog ๊ฐ€ ์•ฑ์˜ main bundle์— ์œ„์น˜ํ•ด์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์ƒ๊ธฐํ•˜์„ธ์š”

์ด๊ฒƒ์€ ์ด๋ฏธ์ง€๋ฅผ UIImage(named:) ๋ฉ”์„œ๋“œ๋กœ ๋ถˆ๋Ÿฌ์˜ฌ ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ control ์ด @IBDesignable ์ด๊ธฐ ๋•Œ๋ฌธ์—, ๊ตฌ์„ฑ ์ฝ”๋“œ๋Š” ์ธํ„ฐํŽ˜์ด์Šค ๋นŒ๋”์—์„œ๋„ ์‹คํ–‰๋  ํ•„์š”๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฏธ์ง€๋ฅผ  ์ธํ„ฐํŽ˜์ด์Šค ๋นŒ๋”์—์„œ ์ ์ ˆํ•˜๊ฒŒ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ์œ„ํ•ด์„œ๋Š”, ๋ฐ˜๋“œ์‹œ catalog์˜ bundle์„ ํŠน์ •ํ•˜์—ฌ ๋ช…์‹œํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

์ด๊ฒƒ์ด ์‹œ์Šคํ…œ์ด ์ด๋ฏธ์ง€๋ฅผ ์ฐพ๊ณ  ๋ถˆ๋Ÿฌ์˜ค๋Š” ๊ฒƒ์„ ๋ณด์žฅํ•ด์ค๋‹ˆ๋‹ค.

 

๊ด€๋ จ ๊ธ€: Bundle

 

UIButton์˜ ํŠน์ง•

  • 5๊ฐ€์ง€ ์ƒํƒœ๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ( normal, highlighted, focused, selected, disabled )

  • ๊ธฐ๋ณธ์ ์œผ๋กœ ์ƒํƒœ์— ์˜ํ•ด ๋ชจ์Šต์ด ๋ฐ”๋€๋‹ˆ๋‹ค.

  • ๋ฒ„ํŠผ์€ ๋™์‹œ์— ์—ฌ๋Ÿฌ ๊ฐ€์ง€ ์ƒํƒœ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.  ์˜ˆ๋ฅผ ๋“ค๋ฉด disabled ์ด๋ฉด์„œ highlighted ์ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  • ์‚ฌ์šฉ์ž๊ฐ€ ๋ฒ„ํŠผ์„ ํ„ฐ์น˜ํ•˜๋ฉด ๋ฒ„ํŠผ์€ ์ƒํƒœ์— ์ƒ๊ด€์—†์ด ํ•ญ์ƒ `highligted ` ์ƒํƒœ๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

  • focused  ์ƒํƒœ๋Š” focus ๊ธฐ๋ฐ˜ ์ธํ„ฐํŽ˜์ด์Šค์—์„œ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.  ( Apple TV์™€ ๊ฐ™์€ )


 

Implement the Button Action

 

์„ ํƒ๋œ Button์˜ ๋ฐฐ์—ด ๋‚ด ์ธ๋ฑ์Šค๋ฅผ ์ฐพ๋Š” ๊ตฌํ˜„์—์„œ index(of:) ๋ฉ”์„œ๋“œ๋Š” deprecated ๋˜์—ˆ์œผ๋ฏ€๋กœ, firsrtIndex(of:) ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.

 

์ด์™ธ๋Š” ๊ธฐ์กด์— ๋ฐฐ์šด ๋‚ด์šฉ์˜ ๋ณต์Šต ์ด๋ฏ€๋กœ ์ƒ๋žตํ•˜์˜€์Šต๋‹ˆ๋‹ค.


 

Add Accessibility Information

 

๊ธฐ๊ธฐ ์‚ฌ์šฉ์— ๋„์›€์ด ํ•„์š”ํ•œ ์‚ฌ๋žŒ๋“ค์—๊ฒŒ ํ›Œ๋ฅญํ•œ ๋ชจ๋ฐ”์ผ ๊ฒฝํ—˜์„ ์ œ๊ณตํ•ด ์ค„ ์ˆ˜ ์žˆ๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.

 

VoiceOver, Switch Control, Guided Access ๋“ฑ์„ ํฌํ•จํ•ฉ๋‹ˆ๋‹ค.

 

ํŠนํžˆ VoiceOver๋Š” ์ €์‹œ๋ ฅ์ž ๋ฐ ์‹œ๊ฐ์žฅ์• ์ธ์—๊ฒŒ ํ›Œ๋ฅญํ•œ ์Šคํฌ๋ฆฐ๋ฆฌ๋”๊ฐ€ ๋ฉ๋‹ˆ๋‹ค.

 

VoicdeOver๋Š” ์‚ฌ์šฉ์ž์—๊ฒŒ ๋‹น์‹ ์˜ UI๋ฅผ ์ฝ์–ด ์ค๋‹ˆ๋‹ค.

 

๊ธฐ์กด์˜ control ๋“ค ์—๊ฒŒ๋Š” ํ›Œ๋ฅญํ•œ ๊ธฐ๋ณธ ์„ค๋ช…์ด ๋˜์–ด ์žˆ์ง€๋งŒ, custom view์™€ control๋“ค์— ๋Œ€ํ•ด์„œ๋Š” ์ตœ์ ํ™”๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

 

์ดํ•˜ Accessibility์— ๋Œ€ํ•œ ๋‚ด์šฉ์€ ๋”ฐ๋กœ ๊ธ€๋กœ ์ž‘์„ฑํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.


 

Connect the Rating Control to the View Controller

๊ธฐ์กด์— ๋ฐฐ์šด ๋‚ด์šฉ์„ ์ด์šฉํ•ด ์‹ค์Šตํ•˜๋Š” ๋‚ด์šฉ์ด๋ฏ€๋กœ ์ƒ๋žตํ•˜์˜€์Šต๋‹ˆ๋‹ค.


 

Clean Up the Project

 

ํด๋ฆฐ ๋นŒ๋“œ ํ•˜๋Š” ๋ฒ• : Command-Shift-K ์ดํ›„ ์žฌ๋นŒ๋“œ

 

Command-Shift-K ์‹คํ–‰ ์‹œ `Clean Finished`๋ฉ”์‹œ์ง€๊ฐ€ ๋œน๋‹ˆ๋‹ค. ์ดํ›„ ์žฌ๋นŒ๋“œํ•ฉ๋‹ˆ๋‹ค.

 

 

 

๋!