๊ณต๋ถ€ ์—ฐ์Šต์žฅ :-)

TIL_20180601 ~ 20180608

|

2018.06.01

  • Codable: Codableํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•˜์—ฌ JSONSerialization์—†์ด ๋ฐ”๋กœ Dataํƒ€์ž…์„ ๊ฐ์ฒด๋กœ ๋ณ€ํ™˜ํ•  ์ˆ˜ ์žˆ์—ˆ์Œ
  • ๋ณ€ํ™˜์„ ์›ํ•˜๋Š” ๊ฐ์ฒด๋Š” Codableํƒ€์ž…์ด์–ด์•ผ ํ•จ

2018.06.05

  • ํ”„๋กœํผํ‹ฐ ์˜ต์ €๋ฒ„ didSet
  • ํ…Œ์ด๋ธ”๋ทฐ์˜ ์…€ ๋†’์ด ์ž๋™์ง€์ •
    • tableView.rowHeight = UITableViewAutomaticDimension

2018.06.07

  • Contact ํ”„๋ ˆ์ž„์›Œํฌ
  • youtube์—์„œ ์‰ฌ์šด ํŠœํ† ๋ฆฌ์–ผ์„ ์ฐพ์•˜๋‹ค. ๊ทธ๋ƒฅ ์ง„์ž‘์— ์ด๊ฑฐ๋ถ€ํ„ฐ ๋”ฐ๋ผํ• ๊ฑธใ… ใ… ใ… ..
  • privacy-sensitive data์— ๋Œ€ํ•ด์„œ access๊ถŒํ•œ ์š”์ฒญํ•˜๊ธฐ
    • ์ฃผ์†Œ๋ก๊ฐ™์€ privateํ•œ ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ• ๋•Œ๋Š” ๋ฐ˜๋“œ์‹œ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ ‘๊ทผ๊ถŒํ•œ์„ ์š”์ฒญํ•ด์•ผํ•จ. ์ด๊ฑด Info.plist์—์„œ ์„ค์ •ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ ์•ˆ๊ทธ๋Ÿฌ๋ฉด ์•ฑ์ด ์•„๋ž˜์˜ ์—๋Ÿฌ๋ฅผ ๋ฑ‰๊ณ  ์ฃฝ์–ด๋ฒ„๋ฆผ. ์—๋Ÿฌ์—์„œ ์นœ์ ˆํ•˜๊ฒŒ๋„ ํ•ด๊ฒฐ๋ฐฉ๋ฒ•์„ ์•Œ๋ ค์ค˜์„œ ๊ธฐ๋ก!
    • This app has crashed because it attempted to access privacy-sensitive data without a usage description. The app's Info.plist must contain an NSContactsUsageDescription key with a string value explaining to the user how the app uses this data.
    • ํ•ด๊ฒฐ๋ฐฉ๋ฒ•: Info.plistํŒŒ์ผ๋กœ ๊ฐ€์„œ Information Property List ์—์„œ +๋ฒ„ํŠผ ๋ˆ„๋ฅด๊ณ  Privacy - Contacts ์ถ”๊ฐ€ํ•˜์—ฌ description์“ฐ๊ธฐ!

TIL_20180423 ~ 20180430

|

2018.04.30

  • 4์›” ํšŒ๊ณ 
  • ์นด๋“œ๊ฒŒ์ž„ CardDeckDelegate ์‹ฑ๊ธ€ํ†ค๊ตฌํ˜„
    class CardGameDelegate: CardGameManageable {
    
      static let defaultStackRange: CountableClosedRange = 1...7
      static let defaultStackNumber: Int = 7
    
      private static var sharedCardDeck = CardGameDelegate()
    
      private init() {
          cardDeck.shuffle()
          var stacks = [CardStack]()
          for numberOfCard in CardGameDelegate.defaultStackRange {
              let oneStack = cardDeck.makeStack(numberOf: numberOfCard)
              oneStack.sortDefaultStack()
              stacks.append(oneStack)
          }
          self.cardStacks = stacks
      }
    
      class func shared() -> CardGameDelegate {
          return sharedCardDeck
      }
      // ์•ฑ ๋‚ด ์–ด๋–ค ํด๋ž˜์Šค์—์„œ ์ด ๋ฉ”์†Œ๋“œ๋ฅผ ํ˜ธ์ถœํ•˜๋”๋ผ๋„ ์ด๋ฏธ ์ดˆ๊ธฐํ™”๋œ sharedCardDeck๋งŒ ๋ฆฌํ„ด๋จ
      // ์ด๋•Œ ์ดˆ๊ธฐํ™”๋‚˜ ๊ฐ์ฒด์ƒ์„ฑ์€ ์ž๊ธฐ ์ž์‹  (CardGameDelegate)๋งŒ ์Šค์Šค๋กœ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ณดํ˜ธ๋˜์–ด์žˆ์Œ
    

4์›” ํšŒ๊ณ 

Good

  • ์žํŒ๊ธฐ์™„์„ฑ!
  • ์นด๋“œ๊ฒŒ์ž„๋ถ€ํ„ฐ ๊นƒํ—™ ์ด์Šˆ๊ด€๋ฆฌ๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ ์‹œ์ž‘ํ–ˆ๋Š”๋ฐ ์ ์‘๋๋‹ค. ํฐ ์š”๊ตฌ์‚ฌํ•ญ๋„ ๋‹จ๊ณ„๋ณ„๋กœ ์ชผ๊ฐœ๊ณ  ํ•˜๋‚˜์˜ ์ด์Šˆ๋กœ ๊ด€๋ฆฌํ•˜๋‹ˆ๊นŒ ์ˆ˜์ •์‚ฌํ•ญ ๊ด€๋ฆฌ์™€ ํ”ผ๋“œ๋ฐฑ๊ด€๋ฆฌ๊ฐ€ ํŽธํ•ด์ง.
  • ์ปค๋ฐ‹๋ฉ”์‹œ์ง€์“ฐ๋Š” ๋ฐฉ๋ฒ•์„ ํ†ต์ผ์‹œํ‚ค๊ณ  ์ด์Šˆ๋ฒˆํ˜ธ์™€ ํ•จ๊ป˜ ๊ด€๋ฆฌ
    • ์ปค๋ฐ‹๋ฉ”์‹œ์ง€๋Š” ํ•ญ์ƒ ํƒ€์ดํ‹€: ๊ฐ„๋žต ๋‚ด์šฉ ํ˜•์‹์œผ๋กœ ์“ฐ๊ณ  ๋งŒ์•ฝ ๋‚ด์šฉ์ด ๊ธธ์–ด์ง€๋ฉด ์•„๋ž˜ ์ค„๋กœ ๋‚ด๋ ค์„œ ๋‚ด์šฉ์„ ์“ด๋‹ค
  • ๋ทฐ - ๋ทฐ๋ชจ๋ธ์˜ ๊ด€๊ณ„์™€ ๋งŒ๋“œ๋Š” ๋ฐฉ๋ฒ• ์ดํ•ดํ•จ
    • ์ฑ…์ž„๊ณผ ์—ญํ• ์ด ๋ถ„๋ช…ํ•ด์ง„๋‹ค: ๊ทธ๋ƒฅ ๋‹จ์ˆœ MVC๋ณด๋‹ค V-VM ๊ด€๊ณ„๋ฅผ ๋งŒ๋“œ๋‹ˆ ๋” ์ฑ…์ž„๊ณผ ๊ด€๊ณ„์˜ ๊ฒฝ๊ณ„๊ฐ€ ๋ช…ํ™•ํ•ด์ง€๋Š”๊ฒƒ๊ฐ™์•˜๋‹ค. ๋ทฐ๋ชจ๋ธ์— ์žˆ๋Š” ๋กœ์ง๋Œ€๋กœ ๋ฐ”๋€ ๋‚ด์šฉ์„ ๋ทฐ๋Š” ๊ทธ๋ฆฌ๊ธฐ๋งŒ ํ•˜๋ฉด ๋œ๋‹ค.
    • ํ…Œ์ŠคํŠธ๊ฐ€ ๊ฐ€๋Šฅํ•ด์ง„๋‹ค: ์ด๋ ‡๊ฒŒ ๋˜๋ฉด ๋ทฐ๋ชจ๋ธ์„ ํ…Œ์ŠคํŠธํ•จ์œผ๋กœ์จ ๋ทฐ๋ฅผ ๋งค๋ฒˆ ๊ทธ๋ ค๊ฐ€๋ฉด์„œ ๊ฒฐ๊ณผํ™”๋ฉด์„ ๋ณด๊ฑฐ๋‚˜, ํ”„๋ฆฐํŠธ๋กœ ๊ทธ๋ ค์ง€๋Š” ๊ฐ’์„ ์ฐ์–ด๋ณด๋Š” 1์ฐจ์›์ ์ธ ๋ฐฉ๋ฒ•์œผ๋กœ ๋””๋ฒ„๊น…์„ ํ•˜์ง€ ์•Š์•„๋„๋œ๋‹ค.
    • ๋˜ํ•œ ๋ทฐ๋ชจ๋ธ์„ ๋งŒ๋“ค๋ฉด์„œ ํ”„๋กœํ† ์ฝœ์— ์˜์กดํ•˜๋Š” ๋ฐฉ๋ฒ• (SOLID๋ฒ•์น™์—์„œ L - ๋‹คํ˜•์„ฑ)์„ ์ดํ•ดํ•˜๊ฒŒ๋๋‹ค.
    • ๋ชจ๋ธ์„ ํ™•์žฅ ๊ฐ€๋Šฅํ•˜๊ฒŒ ๋งŒ๋“ ๋‹ค: ๋ทฐ์™€ ๋ทฐ๋ชจ๋ธ๊ด€๊ณ„์—์„œ๋Š” ๋ทฐ๊ฐ€ ๋ทฐ๋ชจ๋ธ์„ ๊ตฌํ˜„ํ•œ ํด๋ž˜์Šค๋ฅผ ์†์„ฑ์œผ๋กœ ๊ฐ–๊ฒŒ๋˜๋Š”๋ฐ, ์ด๋•Œ ๋ทฐ๊ฐ€ ๋ชจ๋ธ์„ ์ง์ ‘ ๊ฐ€์ง€๋Š”๊ฒŒ ์•„๋‹ˆ๋ผ ํ•ด๋‹น ๋ชจ๋ธํด๋ž˜์Šค๊ฐ€ ์ƒ์†(๊ตฌํ˜„)ํ•˜๊ณ ์žˆ๋Š” ํ”„๋กœํ† ์ฝœ ํƒ€์ž…์„ ๊ฐ€์ ธ์•ผ ํ•œ๋‹ค.
    • ์ด๋ ‡๊ฒŒ ๋ชจ๋ธํด๋ž˜์Šค๋ฅผ ์ถ”์ƒํ™”ํ•œ ํ”„๋กœํ† ์ฝœ์ด ๋”ฐ๋กœ ์žˆ๊ณ , ์–ด๋–ค ํด๋ž˜์Šค๊ฐ€ ๋ชจ๋ธ๋กœ ์˜ค๋”๋ผ๋„ ํ™•์žฅ์— ์—ด๋ ค์žˆ๋Š” ๊ตฌ์กฐ๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์ข‹๋‹ค. ์ด๋ ‡๊ฒŒ ๋˜๋ฉด ๋ทฐ๊ฐ€ ์ง์ ‘ ๋ชจ๋ธ์„ ๊ฐ€์ง€๋Š”๊ฒƒ์ด ์•„๋‹ˆ๋ผ ํ”„๋กœํ† ์ฝœ์— ์˜์กดํ•˜๋Š” ์•ฝํ•œ ์˜์กด์„ฑ์„ ๊ฐ–๊ฒŒ๋œ๋‹ค.

Bad

  • ์ฃผ๋ง์ด๋‚˜ ์ˆ˜์š”์ผ๊ฐ™์€ ์—ฌ์œ ์‹œ๊ฐ„์— ๊ณต๋ถ€๋ฅผ ๋งŽ์ด ๋ชปํ–ˆ๋‹ค. ์‰ด๋• ์‰ฐ๋‹ค๋Š” ํ•‘๊ณ„๋กœ..
  • ๊ทผ๋ฐ ๋‚œ ํ•˜๋‚˜์˜ ๋ฐฐ๊ฒฝ์ง€์‹์ด๋ผ๋„ ์ค‘์š”ํ•œ ๋น„์ „๊ณต์ž๋‹ˆ๊ป˜โ€ฆ
  • ์ผ๋‹จ์€ ๋„์›€์ด ์•ˆ๋˜๋„ ๋“ค์–ด๋†“๊ณ  ๋ด๋†“์œผ๋ฉด ์–ธ์  ๊ฐ„ ์ •๋ง ๋„์›€์ด ๋˜๋Š”๊ฒƒ ๊ฐ™๋‹ค.
  • ์ฒ˜์Œ ๋“ฃ๊ฑฐ๋‚˜ ๋ณผ๋•Œ๋Š” ์•„์˜ˆ ๋ชจ๋ฅด๊ฒ ๋Š” ๋ง์ด ๋งŽ์€๋ฐ, ํ•œ๋ฒˆ ์ฒ˜์Œ ๋ณผ ๋•Œ ๋ฌด์Šจ ๋ง์ธ์ง€ ๋ชจ๋ฅด๋”๋ผ๋„ ์ผ๋‹จ ๋ด๋‘๋ฉด ๋‚˜์ค‘์— ์ ์–ด๋„ ์ƒ์†Œํ•˜์ง€๋Š” ์•Š์œผ๋‹ˆ, ์ฒ˜์Œ๋ณด๋‹ค๋Š” ํŽธํ•œ ๋ถ€๋ถ„์ด ์žˆ์—ˆ๋‹ค.
  • ํ•ญ์ƒ ๊ท€๋ฅผ ์—ด๊ณ  ๋ˆˆ์„ ์—ด์ž!

AppDelegate methods by App lifecycle

|

์•ฑ ๋ผ์ดํ”„์‚ฌ์ดํด์— ๋”ฐ๋ฅธ AppDelegate methods ์ •๋ฆฌ Strategies for Handling App State Transitions ์ฐธ๊ณ , ๊ฐ„๋‹จ๋ฒˆ์—ญ๊ณผ ์ •๋ฆฌ

  • ๋Œ€๋ถ€๋ถ„์˜ ์ƒํƒœ๋ณ€ํ™”๋Š” AppDelegate๊ฐ์ฒด์˜ ๋ฉ”์†Œ๋“œ ํ˜ธ์ถœ์„ ๊ฑฐ์นœ๋‹ค.
  • AppDelegate.swift ํŒŒ์ผ์—๋Š” ์•ฑ์˜ ์ƒํƒœ์— ๋”ฐ๋ผ ์‹คํ–‰๋˜๋Š” ํ•จ์ˆ˜๋“ค์ด ์ •์˜๋˜์–ด ์žˆ๋‹ค.
  • ์•ฑ์˜ ์ƒํƒœ์— ๋”ฐ๋ผ ์‹คํ–‰๋˜๋Š” delegate ํ•จ์ˆ˜๋“ค์ด ์ •์˜๋˜์–ด ์žˆ๊ธฐ๋•Œ๋ฌธ์— ํ•จ์ˆ˜์•ˆ์— ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑ ํ•จ์œผ๋กœ์จ ์•ฑ์˜ ํŠน์ • ์ƒํƒœ์—์„œ ๋™์ž‘ํ•˜๋Š” ๋กœ์ง์„ ๊ตฌํ˜„ ํ•  ์ˆ˜ ์žˆ๋‹ค.
application(_:didFinishLaunching:) - ์•ฑ์ด ์ฒ˜์Œ ์‹œ์ž‘๋  ๋•Œ ์‹คํ–‰
applicationWillResignActive: - ์•ฑ์ด active ์—์„œ inactive๋กœ ์ด๋™๋  ๋•Œ ์‹คํ–‰(foreground)
applicationDidEnterBackground: - ์•ฑ์ด background ์ƒํƒœ์ผ ๋•Œ ์‹คํ–‰
applicationWillEnterForeground: - ์•ฑ์ด background์—์„œ foreground๋กœ ์ด๋™ ๋ ๋•Œ ์‹คํ–‰ (์•„์ง foreground์—์„œ ์‹คํ–‰์ค‘์ด์ง„ ์•Š์Œ)
applicationDidBecomeActive: - ์•ฑ์ด active์ƒํƒœ๊ฐ€ ๋˜์–ด ์‹คํ–‰ ์ค‘(foreground)
applicationWillTerminate: - ์•ฑ์ด ์ข…๋ฃŒ๋  ๋•Œ ์‹คํ–‰
  • application:willFinishLaunchingWithOptions:
    • ์•ฑ์„ ์‹คํ–‰ํ•  ๋•Œ ์ตœ์ดˆ๋กœ ์‹คํ–‰ํ•  ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋ฉด ์ข‹์Œ.
    • ์•ฑ์„ ์‹คํ–‰ํ•  ๋•Œ ํ•„์š”ํ•œ, ์•ฑ ๋ฒˆ๋“ค์ด๋‚˜ iCloud ์ปจํ…Œ์ด๋„ˆ์— ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ ๋ถˆ๋Ÿฌ์™€์„œ ์„ค์ •ํ• ๋•Œ ์‚ฌ์šฉ
  • application:didFinishLaunchingWithOptions:
  • ์•ฑ์˜ ํ™”๋ฉด์ด ์‚ฌ์šฉ์ž์—๊ฒŒ ๋ณด์—ฌ์ง€๊ธฐ ์ง์ „์— ์ตœ์ข… ์ดˆ๊ธฐํ™” ์ž‘์—…์„ ์ง„ํ–‰
  • applicationDidBecomeActive: ์•ฑ์ด ์ด์ œ Foreground๋กœ ๊ฐˆ ๊ฒƒ. ์ตœ์ข… ์ค€๋น„์ž‘์—….
  • applicationWillResignActive:
    • ์•ฑ์ด Foreground์—์„œ ๋‹ค๋ฅธ ์ƒํƒœ๋กœ ์ „ํ™˜์ด ๋ ๊ฒƒ์ž„์„ ์•Œ๋ ค์ค๋‹ˆ๋‹ค. ์•ฑ์ด ์ž ์ž ํ•œ(quiescent) ์ƒํƒœ๋กœ ๋ณ€ํ™˜๋˜๋Š” ์ž‘์—…์„ ์—ฌ๊ธฐ์„œ ์ง„ํ–‰ํ•˜์„ธ์š”.
    • Alert-based interruptions์œผ๋กœ ์ธํ•ด ์•ฑ์˜ ์ปจํŠธ๋กค์ด ์ผ์‹œ์ ์œผ๋กœ ์ค‘๋‹จ๋  ์ˆ˜ ์žˆ๋‹ค. ์•ฑ์€ foreground์ƒํƒœ์—์„œ ๊ณ„์† ๋™์ž‘ํ•˜์ง€๋งŒ, touch event๋ฅผ ๋ฐ›์„ ์ˆ˜ ์—†๋Š” ์ƒํƒœ์ด๋‹ค. (It does continue to receive notifications and other types of events, such as accelerometer events, though.)
    • ์ด๋Ÿฌํ•œ ์ƒํƒœ์— ๋Œ€์ฒ˜ํ•˜๊ธฐ์œ„ํ•ด applicationWillResignActive๋ฅผ ๊ตฌํ˜„ํ•ด์•ผํ•จ
      • Save data and any relevant state information.
      • Stop timers and other periodic tasks.
      • Stop any running metadata queries.
      • Do not initiate any new tasks.
      • Pause movie playback (except when playing back over AirPlay).
      • Enter into a pause state if your app is a game.
      • Throttle back OpenGL ES frame rates.
      • Suspend any dispatch queues or operation queues executing non-critical code. - (You can continue processing network requests and other time-sensitive background tasks while inactive.)
  • applicationWillEnterForeground:
    • ์•ฑ์ด Background์—์„œ ๋‹ค์‹œ Foreground๋กœ ๋Œ์•„์˜ค๊ฒŒ ๋  ๊ฒƒ์ž„์„ ์•Œ๋ ค์คŒ. ์•„์ง ์•ฑ์ด Active์ƒํƒœ๋Š” ์•„๋‹˜.
    • ์ด ํ•จ์ˆ˜๋Š” applicationWillResignActive:๋Š” ๋ฐ˜๋Œ€์˜ ์ƒํƒœ์ผ๋•Œ ํ˜ธ์ถœ๋˜๋Š”๋ฐ, ์ด๋•Œ๋Š” reactivation์— ํ•„์š”ํ•œ ๋™์ž‘์„ ๊ตฌํ˜„ํ•ด์•ผํ•œ๋‹ค.
      • restart timers, resume dispatch queues, and throttle up OpenGL ES frame rates again. However, games should not resume automatically; they should remain paused until the user chooses to resume them.
  • applicationDidEnterBackground: ์•ฑ์ด Background๋กœ ๋Œ์•„๊ฐ. ๊ทธ๋ฆฌ๊ณ  ์–ธ์ œ๋“ ์ง€ Suspended์ƒํƒœ๋กœ ๋ณ€ํ™˜์ด ๋  ์ˆ˜ ์žˆ๋‹ค.
  • applicationWillTerminate: ์•ฑ์ด ์ข…๋ฃŒ๋  ๊ฒƒ์ž„์„ ์•Œ๋ ค์คŒ. ๋งŒ์•ฝ ์•ฑ์ด Suspended์ƒํƒœ๋ผ๋ฉด ์ด ๋ฉ”์†Œ๋“œ๋Š” ํ˜ธ์ถœ๋˜์ง€ ์•Š๋Š”๋‹ค.

Responding to Temporary Interruptions

  • Notifications that display a banner do not deactivate your app in the way that alert-based notifications do. Instead, the banner is laid along the top edge of your app window and your app continues receive touch events as before. However, if the user pulls down the banner to reveal the notification center, your app moves to the inactive state just as if an alert-based interruption had occurred. Your app remains in the inactive state until the user dismisses the notification center or launches another app. At this point, your app moves to the appropriate active or background state. The user can use the Settings app to configure which notifications display a banner and which display an alert.

  • Pressing the Sleep/Wake button is another type of interruption that causes your app to be deactivated temporarily. When the user presses this button, the system disables touch events, moves the app to the background, sets the value of the appโ€™s applicationState property to UIApplicationStateBackground, and locks the screen. A locked screen has additional consequences for apps that use data protection to encrypt files.

What to Do When Your App Enters the Foreground

Note: The UIApplicationWillEnterForegroundNotification notification is also available for tracking when your app reenters the foreground. Objects in your app can use the default notification center to register for this notification.

TIL_20180416 ~ 20180422

|

2018.04.16

  • awakeFromNib()์—๋Œ€ํ•œ ์งˆ๋ฌธ
  • ์นด๋“œ๊ฒŒ์ž„ ํ”ผ๋“œ๋ฐฑ ์ฒ˜๋ฆฌํ•˜๊ณ  step3์‹œ์ž‘ํ•˜๊ธฐ
    • ์นด๋“œ๊ฐ์ฒด์™€ ์นด๋“œ์ด๋ฏธ์ง€๋ทฐ 1:1๋กœ ๋งคํ•‘๋˜๋Š” ๊ด€๊ณ„๋งŒ๋“ค๊ธฐ
  • CardDeck (UIImageview)์˜ ์ œ์Šค์ณ ์ด๋ฒคํŠธ
  • CardDeck์ด ํ„ฐ์น˜๋ ๋•Œ๋งˆ๋‹ค ํƒญ์ œ์Šค์ณ๊ฐ€ ์ž‘๋™ํ•˜์ง€ ์•Š๋Š” ๋ฌธ์ œํ•ด๊ฒฐ
    • ์Šคํƒ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ์—์„œ ์ฐพ์•„๋ณธ ๋ฐ”๋กœ๋Š” isUserInteractionEnabled์˜ ๊ธฐ๋ณธ๊ฐ’์€ true๋ผ๊ณ ํ–ˆ๋Š”๋ฐ,โ€ฆ ๊ทธ๊ฒŒ ์•„๋‹ˆ์—ˆ๋‹ค.
    • UIView์˜ isUserInteractionEnabled / UIImageview์˜ isUserInteractionEnabled
      • (UIView์—์„œ ์„ค๋ช…์— Note: โ€˜Some UIKit subclasses override this property and return a different default value.โ€™๋ฅผ ์ž˜ ์ฝ์–ด๋ดค์–ด์•ผํ–ˆ๋‹ค..)
    • ์‹ฌ์ง€์–ด ํด๋ž˜์Šค ์ฐธ์กฐ ๋ฌธ์ œ๋„ ์žˆ์—ˆ์Œ.

2018.04.17

  • ์นด๋“œ๊ฒŒ์ž„ step3 ์ง„ํ–‰
    • ์นด๋“œ๋ฑ ํ„ฐ์น˜๋ถ€๋ถ„ ๋ฆฌํŒฉํ† ๋ง: isUserInteractionEnabled - CardImageView์— ์ ์šฉ
    • ์•„๋ž˜ ์นด๋“œ์Šคํƒ๋ถ€๋ถ„ ์ถœ๋ ฅ ์ฒ˜๋ฆฌ
      • ์Šคํƒ์˜ ๋งˆ์ง€๋ง‰ ์นด๋“œ๊ฐ€ ์•ž๋ฉด์ธ์ง€ ๊ฒ€์‚ฌํ•ด์„œ ์•ž๋ฉด์ด ์•„๋‹ˆ๋ฉด ๋งˆ์ง€๋ง‰ ํ•œ์žฅ์„ ์•ž์œผ๋กœ ๋’ค์ง‘๋Š”(open) ๋ฉ”์†Œ๋“œ ์ถ”๊ฐ€ํ•˜๊ธฐ

2018.04.20

  • CardStackDelegate๋งŒ๋“ค๊ธฐ
  • class ํƒ€์ž…์—์„œ struct๋กœ ๋ณ€๊ฒฝ. CardStackDelegate๊ฐ€ ๊ฐ€์ง„ stacks ์ƒํƒœ๊ฐ€ ๋ณ€๊ฒฝ๋˜๋ฉด ์นด๋“œ๊ฒŒ์ž„ ์•ฑ ๋‚ด ๋ชจ๋“  ๊ฐ์ฒด๊ฐ€ ๋˜‘๊ฐ™์€ ์ƒํƒœ์˜ ์นด๋“œ์Šคํƒ ์ƒํƒœ๋ฅผ ์•Œ์•„์•ผํ•˜๋ฏ€๋กœ ์‹ฑ๊ธ€ํ†ค ์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•˜๋Š” ๋Š๋‚Œ์œผ๋กœ?
  • ์ฐจ๋ผ๋ฆฌ ์‹ฑ๊ธ€ํ†ค์œผ๋กœ ๋งŒ๋“œ๋Š”๊ฒŒ ๋‚˜์€๊ฐ€? ๊ณ ๋ฏผ

2018.04.22

  • ์• ๋‹ˆ๋ฉ”์ด์…˜ ๊ฐ•์˜ ์ •๋ฆฌ
  • ๋ฆฌ์Šคํฐ๋”์ฒด์ธ ๋ณต์Šต
  • subclass CardImageView์˜ ์‚ฌ์ด์ฆˆ๋Š” ์†์„ฑ์œผ๋กœ ๊ณ ์ •ํ•˜๊ณ  VC์—์„œ origin๋งŒ ๋ถ€์—ฌํ•˜์—ฌ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ• ์ด์Šˆ ์ •๋ฆฌ
    • < ๊ฐ„๋‹จํ•œ ์งˆ๋ฌธ, ๋‹ต๋ณ€๋‚ด์šฉ ์š”์•ฝ >
    • Q: subview๋กœ ์ถ”๊ฐ€ํ•  ์šฉ๋„์˜ ์ปค์Šคํ…€ UIView๋ฅผ ๋งŒ๋“ค๋•Œ size๊ฐ’๋งŒ ๊ณ ์ •ํ•˜๊ณ  origin๋งŒ superView์—์„œ ์ฃผ๋Š” ๋ฐฉ์‹์œผ๋กœ ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ํšจ์œจ์ ์ธ๊ฐ€?
    • A: ์–ด์ฐจํ”ผ frame(ํŠนํžˆ origin)๊ฐ’์„ subview์Šค์Šค๋กœ ๊ณ„์‚ฐํ•  ์ˆ˜ ์—†๋‹ค. superView๊ธฐ์ค€์œผ๋กœ ๋œ ๊ฐ’์ด๊ธฐ๋•Œ๋ฌธ์— superView์—์„œ subview๋ฅผ ๋งŒ๋“ค๋•Œ frame๊ฐ’์„ ๋„ฃ์–ด์ฃผ๋Š”๊ฒŒ ๋” ์ž์—ฐ์Šค๋Ÿฌ์šฐ๋ฉฐ, superView์˜ ์ฝ”๋“œ๋ฅผ ์งง๊ฒŒํ•˜๊ณ ์ž subview์˜ ์‚ฌ์ด์ฆˆ๋ฅผ ๋‚ด๋ถ€์— ๊ณ ์ •ํ•ด๋‘๋Š” ๊ฒƒ ์ž์ฒด๋กœ๋Š” ํฐ ํšจ์œจ์ด ์—†๋‹ค.
  • animate ๊ณต๋ถ€

์ปค์Šคํ…€ ๋ทฐ ํด๋ž˜์Šค์— ์†์„ฑ ์ง€์ •ํ•˜๊ธฐ, UIView์˜ ์ƒ์„ฑ์ž - init(), awakeFromNib()

|

์ปค์Šคํ…€ ๋ทฐ ๋งŒ๋“ค๊ธฐ์˜ ์žฅ์ 

๋งŒ์•ฝ ํ•˜๋‚˜์˜ ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ์— ์—ฌ๋Ÿฌ UIImageview(ํ˜น์€ UIView) ํƒ€์ž…์˜ ์„œ๋ธŒ๋ทฐ๋ฅผ ์ถ”๊ฐ€ํ•ด์•ผ ํ• ๋•Œ, ๊ทธ ์—ฌ๋Ÿฌ ์„œ๋ธŒ๋ทฐ๋“ค์˜ ํฌ๊ธฐ๋‚˜, ํ…Œ๋‘๋ฆฌ, ๋‘ฅ๊ทผ ๋ชจ์„œ๋ฆฌ์™€ ๊ฐ™์€ ์†์„ฑ์ด ๋ชจ๋‘ ๋™์ผํ•œ ๊ฒฝ์šฐ๊ฐ€ ์žˆ์„ ๊ฒƒ์ด๋‹ค. ๋งŒ์•ฝ ์ด ๋•Œ ๋ชจ๋“  ์„œ๋ธŒ๋ทฐ์˜ ์†์„ฑ์„ ์ƒ์œ„ ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์ง€์ •ํ•ด์ค€๋‹ค๋ฉด ๋ฐ˜๋ณต๋˜๋Š” ์ฝ”๋“œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๊ณ  ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ์˜ ์ฝ”๋“œ๊ฐ€ ๋น„ํšจ์œจ์ ์œผ๋กœ ๊ธธ์–ด์งˆ ๊ฒƒ์ด๋‹ค.
์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š”, UIView๋ฅผ ์ƒ์†๋ฐ›๋Š” ์ปค์Šคํ…€ ์ฝ”์ฝ”์•„ํ„ฐ์น˜ ํด๋ž˜์Šค๋ฅผ ํ•˜๋‚˜ ๋งŒ๋“ค์–ด์„œ, ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ์†์„ฑ์„ ์ง€์ •ํ•ด์ฃผ๊ณ , ์ถ”๊ฐ€ํ•  ์„œ๋ธŒ๋ทฐ๋“ค์˜ ํƒ€์ž…์„ ์ปค์Šคํ…€๋ทฐ ํƒ€์ž…์œผ๋กœ ์ง€์ • ํ•ด์ฃผ๋ฉด ๋œ๋‹ค.
์—ฌ๊ธฐ์„œ ์„œ๋ธŒ๋ทฐ๋ฅผ ์ถ”๊ฐ€ํ•˜๋Š” ๋ฐฉ๋ฒ•์—๋”ฐ๋ผ(๋ทฐ๋ฅผ ์ƒ์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์— ๋”ฐ๋ผ) ํ˜ธ์ถœ๋˜๋Š” UIView์˜ ์ดˆ๊ธฐํ™” ํ•จ์ˆ˜๊ฐ€ ๊ฒฐ์ •๋˜๊ธฐ ๋•Œ๋ฌธ์—, ์ปค์Šคํ…€๋ทฐ์˜ ์–ด๋””์— ์†์„ฑ์„ค์ • ์ฝ”๋“œ๋ฅผ ๋„ฃ์–ด์•ผ ํ•˜๋Š”์ง€๊ฐ€ ์ค‘์š”ํ•˜๋‹ค!

UIView์˜ ์ƒ์„ฑ์ž

์œ„์—์„œ ์–ธ๊ธ‰ํ–ˆ๋“ฏ์ด ๋ทฐ๊ฐ€ ์ƒ์„ฑ๋˜๋Š” ๋ฐฉ๋ฒ•์— ๋”ฐ๋ผ ํ˜ธ์ถœ๋˜๋Š” ์ดˆ๊ธฐํ™”ํ•จ์ˆ˜๋ฅผ ์•Œ์•„๋†“์œผ๋ฉด ์ดํ•ด๊ฐ€ ์‰ฌ์šธ ์ˆ˜ ์žˆ์–ด์„œ ์Šคํƒ ํฌ๋“œ iOS๊ฐ•์˜ ์ค‘ ๊ด€๋ จ ๋ถ€๋ถ„์„ ์ •๋ฆฌํ•ด๋ณด์•˜๋‹ค.

  • UIView๋Š” ๋‘๊ฐœ์˜ ํ•„์ˆ˜ ์ƒ์„ฑ์ž๊ฐ€ ์žˆ๋‹ค. ๋ฐ”๋กœ init(frame: CGRect)๊ณผ init(coder: NSCoder)์ด๋‹ค.
  • init(coder: NSCoder): ์Šคํ† ๋ฆฌ๋ณด๋“œ ์—์„œ ๋‚˜์˜ค๋ฉด์„œ UIView๋ฅผ๋งŒ๋“ค๋•Œ ๋งŒ๋“ค์–ด์ง€๋Š” ์ƒ์„ฑ์ž.
    • ๋ทฐ๋ฅผ ์Šคํ† ๋ฆฌ๋ณด๋“œ์—์„œ ๋“œ๋ž˜๊ทธํ•ด์„œ๋งŒ๋“ค์—ˆ๋Š”๋ฐ, ๋งŒ์•ฝ ์•ฑ์ด ์‹คํ–‰๋ ๋•Œ ์Šคํ† ๋ฆฌ๋ณด๋“œ๊ฐ€ ์žฌ๊ตฌ์„ฑ๋˜๋ฉด ์ด ์ƒ์„ฑ์ž๊ฐ€ ํ˜ธ์ถœ๋˜๋ฉด์„œ UIView๊ฐ€ ๋งŒ๋“ค์–ด์ง.
  • init(frame: CGRect): ์ฝ”๋“œ๋กœ ๋ทฐ๋ฅผ ๋งŒ๋“ค๋•Œ ํ˜ธ์ถœ๋จ. ๋ฐ˜๋“œ์‹œ CGRectํƒ€์ž…์œผ๋กœ ํ”„๋ ˆ์ž„์„ ์ •ํ•ด์ฃผ๊ณ  UIView๋ฅผ ์ƒ์„ฑ
    let rect = CGRect(x: 10, y: 10, width: 100, height: 100)
    let myView = UIView(frame: rect)
    

์ปค์Šคํ…€๋ทฐ์— ๋ทฐ ์†์„ฑ ์ง€์ •ํ•˜๊ธฐ

๋งŒ์•ฝ ์ปค์Šคํ…€๋ทฐ๋ฅผ ์ƒ์†๋ฐ›์€ ๋ชจ๋“  ๋ทฐ์— ๋‘ฅ๊ทผ ๋ชจ์„œ๋ฆฌ(cornerRadius)์†์„ฑ์„ ๋ถ€์—ฌํ•˜๊ณ  ์‹ถ์€ ์ƒํ™ฉ์ผ ๋•Œ๋Š” ์•„๋ž˜์˜ ๋ฐฉ๋ฒ•๋“ค์ด ์žˆ๋‹ค.

addSubVIew()๋กœ ์„œ๋ธŒ๋ทฐ๋ฅผ ์ถ”๊ฐ€ํ–ˆ์„๋•Œ

  • ์ฝ”๋“œ๋กœ ์ถ”๊ฐ€ํ•œ view์— ์†์„ฑ์„ ์ ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” init(frame:)์— ์†์„ฑ์„ ์ง€์ •ํ•ด์ค˜์•ผํ•œ๋‹ค.
  • ๋‹ค๋งŒ, init(frame:)์—๋Š” ๋ฌด์กฐ๊ฑด frame๊ฐ’์„ ๋„ฃ์–ด์ค˜์•ผํ•˜๊ธฐ๋•Œ๋ฌธ์—, ์•„๋ž˜ ์˜ˆ์‹œ์ฝ”๋“œ์™€ ๊ฐ™์€ ๋ฐฉ๋ฒ•์œผ๋กœ convenience init์— ์ž„์‹œ frame๊ฐ’์„ ๋„ฃ์–ด์ค˜๋„ ๋œ๋‹ค.
    • ์ด ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•˜๋ฉด ์›ํ•˜๋Š” frame๊ฐ’์€ ์ƒ์œ„๋ชจ๋“ˆ์—์„œ ๋ฐ”๊ฟ”์ค˜์•ผํ•œ๋‹ค.
override init(frame: CGRect) { // by code
    super.init(frame: frame)
    self.layer.cornerRadius = 5.0
    self.clipsToBounds = true
}

convenience init() {
    self.init(frame: CGRect(x: 0, y: 0, width: 0, height: 0))
}

์ธํ„ฐํŽ˜์ด์Šค ๋นŒ๋”์—์„œ ์„œ๋ธŒ๋ทฐ๋ฅผ ์ถ”๊ฐ€ํ–ˆ์„ ๋•Œ

  • ์ธํ„ฐํŽ˜์ด์Šค๋นŒ๋”์—์„œ customํด๋ž˜์Šค๋กœ ์ง€์ •ํ•œ ๋ทฐ๋Š” required init?(coder aDecoder:)๊ฐ€ ํ˜ธ์ถœ๋œ๋‹ค.
  • (์Šคํ† ๋ฆฌ๋ณด๋“œ์—์„œ ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ๊ฐ€์ง„ ๋ทฐ์˜ ํƒ€์ž…์„ ์˜ค๋ฅธ์ชฝ ํƒญ custom class์—์„œ ๋‚ด๊ฐ€ ์ถ”๊ฐ€ํ•œ ์ปค์Šคํ…€๋ทฐ ํด๋ž˜์Šค ์ด๋ฆ„ ์ž…๋ ฅํ•˜์—ฌ ์—ฐ๊ฒฐ)
  • ๋งŒ์•ฝ์— ์–ด๋””์„œ ํ˜ธ์ถœ๋ ์ง€ ๋ชจ๋ฅด๋ฉด awakeFromNib๊ณผ ๋‘ convenience init์— ์„ค์ •ํ•˜๋Š” ์ฝ”๋“œ๋ฅผ ๋„ฃ์–ด์ฃผ๋ฉด ๋œ๋‹ค. ๋Š” ๊ผผ์ˆ˜์•„๋‹Œ ๊ผผ์ˆ˜๋„ ์žˆ๋‹ค..
override func awakeFromNib() {
    // config setting code
        super.awakeFromNib()
    }

required init?(coder aDecoder: NSCoder) {
    // config setting code
    fatalError("init(coder:) has not been implemented")
}

+ ์ถ”๊ฐ€. awakeFromNib()

awakeFromNib()์€ ์ธํ„ฐํŽ˜์ด์Šค ๋นŒ๋”์—์„œ ๋ทฐ๊ฐ€ ๋งŒ๋“ค์–ด์กŒ์„๋•Œ ํ˜ธ์ถœ๋œ๋‹ค๊ณ ๋งŒ ์•Œ๊ณ ์žˆ์—ˆ๋Š”๋ฐ, ๊ทธ๋ณด๋‹ค ๋” ์ž์„ธํ•˜๊ฒŒ ์•Œ ํ•„์š”๊ฐ€ ์žˆ์–ด์„œ ์ถ”๊ฐ€

awakeFromNib์ด ํ˜ธ์ถœ๋˜๋Š” ์‹œ์ 

awakeFromNib()์€ ๊ฐ์ฒด๊ฐ€ ์ดˆ๊ธฐํ™”(์ธ์Šคํ„ด์Šคํ™”)๋œ ํ›„ ํ˜ธ์ถœ๋œ๋‹ค.

  • UIView์—์„œ ์ƒ์†๋ฐ›์€ ์ปค์Šคํ…€ View ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ์ธํ„ฐํŽ˜์ด์Šค๋นŒ๋”์— ์ง€์ •ํ•˜๋ฉด(์˜ค๋ฅธ์ชฝ ํƒญ inspector์—์„œ ์ง€์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ) ์ปค์Šคํ…€ ํด๋ž˜์Šค๋Š” ์•„์นด์ด๋ธŒ๋˜์–ด ์žˆ๋‹ค๊ฐ€ ์–ธ์•„์นด์ด๋ธŒ๋จ(xibํŒŒ์ผ์—)
  • ์ด ๋•Œ init(coder:)๊ฐ€ ํ˜ธ์ถœ๋˜๊ณ  ๋‚ด๋ถ€ ์†์„ฑ์ด ์ดˆ๊ธฐํ™”๋จ
  • ์ผ๋ถ€๋Š” ์ด ๋•Œ ์˜๋ฏธ์—†๋Š” ๊ฐ’์œผ๋กœ ์ดˆ๊ธฐํ™”๋˜๊ฑฐ๋‚˜ IBOutlet์„ ๋น„๋กฏํ•œ ๊ฐ์ฒด ์ฐธ์กฐ ๊ด€๊ณ„๊ฐ€ ๋ถˆ๋ช…ํ™•ํ•  ์ˆ˜ ์žˆ์Œ
    • init ์‹œ์ ์—์„œ๋Š” frame๊ณผ ๊ด€๋ จ๋œ ํฌ๊ธฐ, ์œ„์น˜ ๋“ฑ ๋ทฐ๊ฐ€ ์™„๋ฒฝํ•˜๊ฒŒ ๋งŒ๋“ค์–ด์ง€์ง€ ์•Š์€ ์ƒํƒœ
    • ์ด์™€๊ฐ™์ด ์ธํ„ฐํŽ˜์ด์Šค ๋นŒ๋”์—์„œ ์—ฐ๊ฒฐ๋œ ๊ฐ์ฒด์˜ ๋ณ€์ˆ˜๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๊ณ  ํ• ๋•Œ awakeFromNib()์„ ์‚ฌ์šฉํ•จ
    • ์ด๋ ‡๊ฒŒ awakeFromNib()์€ ๊ฐ์ฒด๋ฅผ ์ธ์Šคํ„ด์Šคํ™” ํ•œ ํ›„(init()์ด ํ˜ธ์ถœ๋œ ํ›„) ํ˜ธ์ถœ๋œ๋‹ค.
  • (IBOutlet์ด ์—†์–ด๋„ awakeFromNib()์€ ํ˜ธ์ถœ๋จ)

awakeFromNib()๊ณผ init()์—์„œ ๋ชจ๋‘ ์„ค์ •ํ•ด์•ผ ํ•˜๋Š” ์ด์œ 

๋ทฐ๋ฅผ ๋งŒ๋“ค๊ณ  ์ปค์Šคํ…€๋ทฐ๋ฅผ ์ธํ„ฐํŽ˜์ด์Šค๋นŒ๋”์—์„œ ์—ฐ๊ฒฐํ–ˆ์„๋• init(frame:), init(coder:)์™€ awakeFromNib()๋‘ ๊ตฐ๋ฐ ๋ชจ๋‘์—์„œ ์„ค์ •์„ ํ•ด์ค€๋‹ค์˜ ์˜๋ฏธ

  • ๊ทธ๋ž˜์„œ ์ดˆ๊ธฐํ™”๊ฐ€ ๋๋‚˜๊ณ  ์„ค์ • awakeFromNib ์‹œ์ ์—์„œ ์ถ”๊ฐ€์ ์ธ ์ž‘์—…์ด ํ•„์š”ํ•œ ๊ฒฝ์šฐ ํ•ด์•ผํ•จ.
  • ์ปค์Šคํ…€ ๋ทฐ๋ฅผ ๋งŒ๋“œ๋Š” ๊ฐœ๋ฐœ์ž ์ž…์žฅ์—์„œ๋Š” ๋‹ค๋ฅธ ๊ฐœ๋ฐœ์ž๊ฐ€ init(frame:)์„ ํ˜ธ์ถœํ•ด์„œ ์ฝ”๋“œ๋กœ ์ƒ์„ฑํ• ์ง€, ์ธํ„ฐํŽ˜์ด์Šค ๋นŒ๋”์—์„œ ์ง€์ •ํ•ด์„œ ์‚ฌ์šฉํ• ์ง€ ๋ถˆ๋ช…ํ™•ํ•˜๋‹ˆ๊นŒ ์ฝ”๋“œ๋กœ ๋งŒ๋“ค๋˜ ์ธํ„ฐํŽ˜์ด์Šค๋นŒ๋”๋กœ ์ž‘์—…ํ•˜๋˜ ๋‘˜ ๋‹ค ๋™์ผํ•œ ๋™์ž‘์ด ๊ฐ€๋Šฅํ•˜๋„๋ก ์ง€์ •ํ•˜๋Š” ๊ฒŒ ์ข‹์Œ
  • JK์˜ ์ฝ”๋ฉ˜ํŠธ ์ถ”๊ฐ€
    ๊ฒฝํ—˜์ƒ init(coder:) ์‹œ์ ์—๋Š” frame ์ด๋‚˜ Layer ๊ด€๋ จ์—†๋Š” ๊ฐ’๋“ค,
    awakeFromNib ์‹œ์ ์—๋Š” frame ์ด๋‚˜ Layer ๊ด€๋ จ๋œ ๊ฐ’๋“ค์„ ์„ค์ •ํ•˜๋„๋ก ๊ตฌํ˜„ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.
    init(frame:) ์€ ์ด๋ฏธ frame ์ •๋ณด๊ฐ€ ์žˆ์œผ๋‹ˆ๊นŒ ๊ดœ์ฐฎ๊ตฌ์š”.
    ๋ฌผ๋ก  autoLayout ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š” ๊ฒฝ์šฐ๋Š” awakeFromNib ๋ณด๋‹ค ๋” ๋’ค์— ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
    

์ฐธ๊ณ ๋งํฌ 1, ์ฐธ๊ณ ๋งํฌ 2, ์ฐธ๊ณ ๋งํฌ 3