iyeahh / ThinkingAbout

๐Ÿ—’๏ธ ์นดํ…Œ๊ณ ๋ฆฌ ๋ณ„๋กœ ๋‚˜๋ˆ„์–ด ์ €์žฅํ•˜๋Š” ๋ฉ”๋ชจ์•ฑ (App Store ์ถœ์‹œ)

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

๐Ÿ—“ ๋ต์ปค๋ฐ”์›ƒ (Think about)

2023๋…„ 10์›” 3์ผ โ†’ 2023๋…„ 10์›” 23์ผ (3์ฃผ)

๐Ÿ—’๏ธ ์นดํ…Œ๊ณ ๋ฆฌ ๋ณ„๋กœ ๋‚˜๋ˆ„์–ด ์ €์žฅํ•˜๋Š” ๋ฉ”๋ชจ์•ฑ

  • ์นดํ…Œ๊ณ ๋ฆฌ ๋ณ„๋กœ ๋ฉ”๋ชจ๋ฅผ ์ €์žฅ
  • ๋ฉ”๋ชจ ์ž‘์„ฑ, ํ™•์ธ, ์ˆ˜์ •, ์‚ญ์ œ ๊ฐ€๋Šฅ
  • ์˜ค๋Š˜ ๋ฉ”๋ชจ๋Š” Today ํƒญ์—์„œ ํ™•์ธ
  • ๋‹คํฌ๋ชจ๋“œ ๋Œ€์‘

๐Ÿค“ ๊ธฐ์ˆ ์Šคํƒ

  • UIKit
  • UI - Storyboard
  • CoreData
  • MVC โ†’ MVVM ๋ฆฌํŒฉํ† ๋ง

๐Ÿ’ก ๋ฌธ์ œ ํ•ด๊ฒฐ

โ“ ๋ฌธ์ œ

๋ฐ˜๋ณต๋˜๋Š” ์ฝ”์–ด๋ฐ์ดํ„ฐ ์ ‘๊ทผ์œผ๋กœ ์•ฑ์˜ ๋ฒ„๋ฒ…์ž„ ๋ฐœ์ƒ ๋ฌธ์ œ (๋ฉ”๋ชจ๋ฆฌ ์บ์‹œ ํ™œ์šฉ์„ ํ†ตํ•ด (๋ฐ˜๋ณต์ ์ธ ์ฝ”์–ด๋ฐ์ดํ„ฐ ์‚ฌ์šฉ ๋นˆ๋„๋ฅผ ์ค„์—ฌ) ์•ฑ์˜ ๋ฒ„๋ฒ…์ž„ ์ค„์ด๊ธฐ)

โ• ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

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

  • ์ „์ฒด ๋ฉ”๋ชจ๋ฅผ ์ฝ์–ด์˜ค๊ณ  ๋˜๋Š” ๋ฉ”๋ชจ๋ฅผ ์ƒ์„ฑ / ์ˆ˜์ • / ์‚ญ์ œ ํ• ๋•Œ๋งˆ๋‹ค ์ฝ”์–ด ๋ฐ์ดํ„ฐ์— ์ ‘๊ทผํ•˜๊ธฐ ๋ณด๋‹ค๋Š”,

  • DataManager ๋‚ด์— (๋ฉ”๋ชจ๋ฆฌ ๋‚ด์—์„œ ๋จผ์ € ์ ‘๊ทผํ•˜๊ณ  ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”) ๋ฉ”๋ชจ๋ฆฌ ์บ์‹œ(memoList ๋ฐฐ์—ด)๋ฅผ ๋งŒ๋“ค์–ด

    • CRUD๋ฅผ ๋ฉ”๋ชจ๋ฆฌ ์บ์‹œ(๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ ๋ฐฐ์—ด) ๋‚ด์—์„œ ์ฒ˜๋ฆฌํ•˜๊ณ 
    • UI๋ฅผ ๊ทธ๋ฆฌ๊ฑฐ๋‚˜ ๋‹จ์ˆœํ•˜๊ฒŒ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ง€๊ณ  ์˜ฌ ๋•Œ๋Š” ๋””์Šคํฌ์— ์ ‘๊ทผํ•˜๋Š” ๋Œ€์‹  ๋ฉ”๋ชจ๋ฆฌ ์บ์‹œ(๋ฐฐ์—ด)์— ์ ‘๊ทผํ•˜์—ฌ ์•ฑ์˜ ๋ฒ„๋ฒ…์ž„์„ ์ค„์ž„

    (์˜ˆ์‹œ) ์ฝ”์–ด๋ฐ์ดํ„ฐ ์ง์ ‘ ์ ‘๊ทผ โ†’ ๋ฉ”๋ชจ๋ฆฌ ์บ์‹œ(๋ฐฐ์—ด)์— ์ ‘๊ทผ

    ์ˆ˜์ •์ „ -> memoDataManager.getMemoListFromCoreData().count (์ฝ”์–ด๋ฐ์ดํ„ฐ ์ ‘๊ทผ)
    ์ˆ˜์ •ํ›„ -> memoDataManager.memoList.count ๋กœ ๋ณ€๊ฒฝ            (๋ฉ”๋ชจ๋ฆฌ ์บ์‹œ ์ ‘๊ทผ)

    (์˜ˆ์‹œ) ๋ฐ์ดํ„ฐ ์‚ญ์ œ์‹œ, ์ฝ”์–ด๋ฐ์ดํ„ฐ ์ง์ ‘ ์ ‘๊ทผ โ†’ ๋ฐฐ์—ด(๋ฉ”๋ชจ๋ฆฌ ์บ์‹œ)์— ๋จผ์ € ์ฒ˜๋ฆฌ ํ›„, ์ฝ”์–ด๋ฐ์ดํ„ฐ์— ํ›„ ์ฒ˜๋ฆฌ

    ์ˆ˜์ •์ „)
    func deleteMemo(_ memo: MemoData?, at index: Int) {
         //.....
    
         mainContext.delete(deletingMemo)          // ์ฝ”์–ด๋ฐ์ดํ„ฐ์— ์ง์ ‘ ์ ‘๊ทผ ์‚ญ์ œ
         saveContext()
    }
    
    ์ˆ˜์ •ํ›„)
    func deleteMemo(_ memo: MemoData?, at index: Int) {
         //.....
    
         memoList.remove(at: index)                // ๋ฉ”๋ชจ๋ฆฌ ์บ์‹œ ๋‚ด์—์„œ ์‚ญ์ œ ํ›„
         mainContext.delete(deletingMemo)          // ์ฝ”์–ด๋ฐ์ดํ„ฐ์— ์ง์ ‘ ์ ‘๊ทผ ์‚ญ์ œ
         saveContext()
    }

โ“ ๋ฌธ์ œ

๊ธฐ๋ณธ MVC์—์„œ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ ๊ณ„์ธต(Layer)์˜ ๋ถ„๋ฆฌ์™€ MVVM์œผ๋กœ ์ถ”๊ฐ€์ ์ธ ๋ฆฌํŒฉํ† ๋ง (๊ฐ์ฒด์ง€ํ–ฅ ๊ด€์ , ํ–ฅํ›„ ์œ ์ง€๋ณด์ˆ˜๋ฅผ ๊ณ ๋ คํ•œ ์„ค๊ณ„)

โ• ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

๐Ÿ’ก ๋ฌธ์ œ ์ƒํ™ฉ: ๊ธฐ๋ณธ MVC ์•„ํ‚คํ…์ฒ˜ ๊ตฌ์กฐ์—์„œ, ๊ฐ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์ฝ”์–ด๋ฐ์ดํ„ฐ์™€ ์ง์ ‘ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์„ ํ•˜๊ณ , ์ˆ˜๋งŽ์€ ๋กœ์ง์„ ๋ณด์œ ํ•จ์œผ๋กœ ๋น„๋Œ€ํ•ด์ง„ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ๋˜์—ˆ์Œ. ๋˜ํ•œ ๋น„ํšจ์œจ์ ์ธ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ๊ฐ€ ์ด๋ฃจ์–ด์ง.

  • MVC ๊ธฐ์กด๊ตฌ์กฐ - ๊ฐ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์ฝ”์–ด๋ฐ์ดํ„ฐ์— ์ง์ ‘ ์ ‘๊ทผํ•˜๋Š” CRUD ๋กœ์ง๋ณด์œ ๋กœ ์ธํ•œ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ ์–ด๋ ค์›€๊ณผ ๋น„๋Œ€ํ•ด์ง„ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ
  • ์ฝ”์–ด๋ฐ์ดํ„ฐ์™€ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜ํ•˜๋Š” ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ ๊ฐ์ฒด๋ฅผ ์ค‘๊ฐ„์— ์ถ”๊ฐ€ํ•ด์„œ, ๋กœ์ง์„ ๋ถ„๋ฆฌํ•˜๊ณ  ํšจ์œจ์ ์ธ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๋„๋ก ๊ตฌ์กฐ๋ฅผ ๋ณ€๊ฒฝ
  • ๋ฐ์ดํ„ฐ ๋ถ€๋ถ„ ๋กœ์ง์„ ๋”ฐ๋กœ ๋ถ„๋ฆฌํ•ด์„œ ๋ฐ์ดํ„ฐ ๊ด€๋ฆฌ ๊ฐ์ฒด์˜ ์—ญํ• ์„ ๋ถ„๋ฆฌ์‹œ์ผœ ๋ณด๋‹ค ๋‹จ์ˆœํ•œ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ์˜ ๊ตฌ์กฐ๋ฅผ ์œ ์ง€์‹œ์ผฐ์Œ
แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2024-01-10 แ„‹แ…ฉแ„’แ…ฎ 1 43 44 แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2024-01-10 แ„‹แ…ฉแ„’แ…ฎ 1 43 49

โ“ ๋ฌธ์ œ

๊ธฐ์กด์˜ MVCํ”„๋กœ์ ํŠธ๋ฅผ MVVM์œผ๋กœ ๋ฆฌํŒฉํ† ๋ง (ํ–ฅํ›„ ์œ ์ง€๋ณด์ˆ˜ ๋ฐ ํ…Œ์ŠคํŠธ๋ฅผ ๊ณ ๋ คํ•œ ์„ค๊ณ„๋กœ ๋ฆฌํŒฉํ† ๋ง)

โ• ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

๐Ÿ’ก ๋ฌธ์ œ ์ƒํ™ฉ: ์—ฌ์ „ํžˆ ๋น„๋Œ€ํ•œ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ์—์„œ, ํ–ฅํ›„ ์œ ์ง€๋ณด์ˆ˜๋ฅผ ๊ณ ๋ คํ•ด ๋ณด๋‹ค ํšจ์œจ์ ์ธ ํ”„๋กœ์ ํŠธ ๊ตฌ์กฐ๋ฅผ ๊ณ ๋ฏผ

  • MVVM ์•„ํ‚คํ…์ฒ˜ - ์—ฌ์ „ํžˆ ๋งŽ์€ ๋กœ์ง์ด ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์ด๋ฃจ์–ด์ง€๊ณ  ์žˆ๋‹ค๋Š” ์ ์—์„œ ๋ฒ—์–ด๋‚˜ ๋ทฐ๋ชจ๋ธ(ViewModel)์„ ๋„์ž…ํ•˜์—ฌ ๋กœ์ง์— ๋Œ€ํ•œ ์™„์ „ํ•œ ๋ถ„๋ฆฌ๋ฅผ ๊ฒฐ์ •
  • MVC์—์„œ๋Š” ์‚ฌ์‹ค์ƒ View์™€ Controller๊ฐ€ ํ•ฉ์ณ์„œ, ๋น„๋Œ€ํ•œ Controller(๋ทฐ์ปจํŠธ๋กค๋Ÿฌ)๋ฅผ ์œ ์ง€ํ–ˆ์—ˆ์ง€๋งŒ ๋ทฐ๋ชจ๋ธ์„ ์ค‘๊ฐ„ ๊ณ„์ธต์— ์‚ฝ์ž…ํ•˜์—ฌ ๋กœ์ง์„ ๋ถ„๋ฆฌ
  • ๋น„๋Œ€ํ•œ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์ด์ œ๋Š” ๋ณด๋‹ค ์‹ฌํ”Œํ•œ ๋ทฐ(๋ทฐ์ปจํŠธ๋กค๋Ÿฌ)๋ฅผ ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์—ˆ๊ณ , ๋กœ์ง์„ ๋ทฐ๋ชจ๋ธ์—์„œ ๊ด€๋ฆฌํ•ด์„œ ํ–ฅํ›„ ์œ ์ง€๋ณด์ˆ˜ ๊ด€์ ์—์„œ ๋ณด๋‹ค ํšจ์œจ์ ์ธ ํ”„๋กœ์ ํŠธ ๊ด€๋ฆฌ๊ฐ€ ๊ฐ€๋Šฅํ•ด์กŒ์Œ
แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2024-01-10 แ„‹แ…ฉแ„’แ…ฎ 1 44 52

โ“ ๋ฌธ์ œ

CoreData์—์„œ ๊ธฐ๋ณธ์œผ๋กœ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ์ปค์Šคํ…€ ํƒ€์ž… ์ €์žฅํ•˜๊ธฐ (์ปค์Šคํ…€ ๋ฐ์ดํ„ฐ ํƒ€์ž…๊ณผ CoreData ํ™œ์šฉ ๋ฌธ์ œ)

โ• ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

๐Ÿ’ก ๋ฌธ์ œ ์ƒํ™ฉ: ์ฝ”์–ด๋ฐ์ดํ„ฐ ๋‚ด์˜ ์—”ํ‹ฐํ‹ฐ์˜ ์†์„ฑ์€ ์Šค์œ„ํ”„ํŠธ์˜ Basic(๊ธฐ๋ณธ) ํƒ€์ž…์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ์ปค์Šคํ…€ ํƒ€์ž…์„ ์—”ํ‹ฐํ‹ฐ์˜ ์†์„ฑ์œผ๋กœ ์‚ฌ์šฉํ•˜๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ?

  • ์ฝ”์–ด๋ฐ์ดํ„ฐ์—์„œ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ํƒ€์ž…์„ ์ €์žฅํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” Transformable ํƒ€์ž…์„ ์‚ฌ์šฉํ•ด์•ผ ํ•˜๊ณ , 3๊ฐ€์ง€ ์š”๊ตฌ์‚ฌํ•ญ์„ ์ ์šฉํ•ด์•ผ ํ•จ
    • ์ €์žฅํ•˜๋ ค๋Š” ๋ฐ์ดํ„ฐ๊ฐ€ NSSecureCoding ํ”„๋กœํ† ์ฝœ ์ค€์ˆ˜ํ•ด์•ผ๋งŒ ํ•จ

      • NSSecureCoding ํ”„๋กœํ† ์ฝœ ์ฑ„ํƒ
      • ํ•ด๋‹น ์ž๋ฃŒํ˜•์ด NSSecureCoding ํ”„๋กœํ† ์ฝœ์„ ๋”ฐ๋ฅด์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— NSString์œผ๋กœ ๋ณ€ํ™˜ํ•˜๊ณ  ์ธ์ฝ”๋”ฉ
      • Core Data์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฒ€์ƒ‰ ํ•  ๋•Œ decodeObject(of: forKey :)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ๊ฐ์ฒด๋ฅผ ๋””์ฝ”๋”ฉ
      public class Category: NSObject, NSSecureCoding {
          public static var supportsSecureCoding: Bool = true
      
          var type: String?
          var color: UIColor?
          var image: UIImage?
      
          init(type: String? = nil, color: UIColor? = nil, image: UIImage? = nil) {
              self.type = type
              self.color = color
              self.image = image
          }
      
          public func encode(with coder: NSCoder) {
              guard let type = type, let color = color, let image = image else { return }
              coder.encode(type as NSString, forKey: "type")
              coder.encode(color as UIColor, forKey: "color")
              coder.encode(image as UIImage, forKey: "image")
          }
      
          required public convenience init?(coder: NSCoder) {
              let type = coder.decodeObject(of: NSString.self, forKey: "type") as? String
              let color = coder.decodeObject(of: UIColor.self, forKey: "color")
              let image = coder.decodeObject(of: UIImage.self, forKey: "image")
      
              self.init(type: type, color: color, image: image)
          }
      }
    • NSSecureUnarchiveFromDataTransformer subclass๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ๋“ฑ๋ก

      • ๊ฐ’ ๋ณ€ํ™˜ ํ”„๋กœ์„ธ์Šค์—์„œ ์ตœ์ƒ์œ„ ํด๋ž˜์Šค์ด๋ฏ€๋กœ allowedTopLevelClasses ๋ฐฐ์—ด์— Category ํด๋ž˜์Šค๋ฅผ ์ถ”๊ฐ€
      • custom transformer ๋ฅผ ๋“ฑ๋กํ•˜๊ธฐ ์œ„ํ•œ ๋ฉ”์„œ๋“œ
      class CategoryTransformer: NSSecureUnarchiveFromDataTransformer {
      
          override class var allowedTopLevelClasses: [AnyClass] {
              return [Category.self]
          }
      
          static func register() {
              let className = String(describing: CategoryTransformer.self)
              let name = NSValueTransformerName(className)
      
              let transformer = CategoryTransformer()
              ValueTransformer.setValueTransformer(transformer, forName: name)
          }
      }
    • ์ƒ์„ฑํ•œ data transformer ํ•˜์œ„ ํด๋ž˜์Šค๋ฅผ Transformable ํƒ€์ž… attribute์™€ ์—ฐ๊ฒฐ แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2023-11-22 แ„‹แ…ฉแ„’แ…ฎ 2 20 13


โ“ ๋ฌธ์ œ

์œ ์ง€๋ณด์ˆ˜๋ฅผ ๊ณ ๋ คํ•œ ๋””์ž์ธ/ํ…Œ๋งˆ ๋“ฑ์˜ ํŒŒ์ผ ๊ด€๋ฆฌ (ํ™•์žฅํŒŒ์ผ ์ƒ์„ฑ๊ณผ ํšจ์œจ์ ์ธ ๊ด€๋ฆฌ)

โ• ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

๐Ÿ’ก ๋ฌธ์ œ์ƒํ™ฉ: ํ˜น์‹œ๋‚˜ ํ–ฅํ›„ ์œ ์ง€๋ณด์ˆ˜ ๋“ฑ์œผ๋กœ ์ธํ•ด ๋””์ž์ธ/ํ…Œ๋งˆ ๋“ฑ์˜ ๋ณ€๊ฒฝ์ด ์ผ์–ด๋‚ฌ์„๋•Œ๋ฅผ ๋Œ€๋น„ํ•ด, ๋””์ž์ธ์ ์ธ ์š”์†Œ๋ฅผ ์–ด๋–ป๊ฒŒ ๋ฆฌํŒฉํ† ๋งํ•˜๊ธฐ ์‰ฝ๊ฒŒ ๊ด€๋ฆฌํ•  ์ˆ˜ ์žˆ์„๊นŒ?

  • ํ™•์žฅ(extension)์„ ํ†ตํ•œ ๋„ค์ž„์ŠคํŽ˜์ด์Šค ์ง€์ •๊ณผ ๋„ค์ž„์ŠคํŽ˜์ด์Šค์—์„œ ์„ ์–ธํ•œ ๊ตฌ์กฐ์ฒด๋ฅผ ๋‹ค์‹œ ํ•˜์œ„์— ์„ ์–ธํ•ด์„œ ์–ธ์ œ๋“ ์ง€ ์ƒˆ๋กœ์šด ๋””์ž์ธ/ํ…Œ๋งˆ ๋ณ€๊ฒฝ ๊ฐ€๋Šฅํ•˜๋„๋ก ๊ด€๋ฆฌ
extension UIImage {
    static let mainIcon = MainIconTheme()   // ์„ ์–ธ์œ„ํ•œ ๊ตฌ์กฐ์ฒด๋งŒ ๊ต์ฒดํ•˜๋ฉด ๋จ
    //...
}

struct MainIconTheme {
    let all: UIImage = UIImage(systemName: "list.clipboard")!
    let work: UIImage = UIImage(systemName: "text.book.closed")!
    let music: UIImage = UIImage(systemName: "beats.headphones")!
    let travel: UIImage = UIImage(named: "airplane")!
    let study: UIImage = UIImage(named: "edit")!
    let stuff: UIImage = UIImage(systemName: "house")!
    let hobby: UIImage = UIImage(systemName: "paintpalette")!
    let shopping: UIImage = UIImage(systemName: "cart")!
}

โ“ ๋ฌธ์ œ

๋ฉ”๋ชจ ์ž‘์„ฑ ํ™”๋ฉด์—์„œ ํ‚ค๋ณด๋“œ์˜ ๋†’์ด๋งŒํผ ์ €์žฅํ•˜๊ธฐ ๋ฒ„ํŠผ ์˜ฌ๋ผ์˜ค๊ฒŒ ๊ตฌํ˜„ํ•˜๊ธฐ (ํ‚ค๋ณด๋“œ์— ๋”ฐ๋ฅธ ์• ๋‹ˆ๋ฉ”์ด์…˜ ์ ์šฉ)

โ• ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

๐Ÿ’ก ๋ฌธ์ œ์ƒํ™ฉ: ์ €์žฅํ•˜๊ธฐ ๋ฒ„ํŠผ์ด ํ‚ค๋ณด๋“œ ๋†’์ด์— ๋”ฑ ๋งž๊ฒŒ๋” ์˜ฌ๋ผ์˜ค๊ฒŒ ํ•˜๊ณ  ์‹ถ์€๋ฐ ์–ด๋–ป๊ฒŒ ํ•  ์ˆ˜ ์žˆ์„๊นŒ?

  • ์ฝ”๋“œ๊ฐ€ ์•„๋‹Œ ์Šคํ† ๋ฆฌ๋ณด๋“œ๋กœ ๋ฒ„ํŠผ์˜ ์ œ์•ฝ์„ ์ฃผ์—ˆ๊ธฐ ๋•Œ๋ฌธ์— IBOutlet ์œผ๋กœ ์ œ์•ฝ์„ ์ฝ”๋“œ์— ์—ฐ๊ฒฐํ•จ

  • keyboardWillShow(_:) keyboardWillHide(_:) ํ•จ์ˆ˜์— ๋…ธํ‹ฐํ”ผ์ผ€์ด์…˜ ์„ค์ •

  • ํ‚ค๋ณด๋“œ๊ฐ€ ์˜ฌ๋ผ์˜ฌ ๋•Œ ํƒญ๋ฐ”์™€ ํ‚ค๋ณด๋“œ์˜ height์„ ๋™์ ์œผ๋กœ ๊ณ„์‚ฐํ•˜์—ฌ ํ•ด๋‹น ๋†’์ด๋งŒํผ ์ œ์•ฝ์„ ์ฃผ๊ณ ,

  • ํ‚ค๋ณด๋“œ๊ฐ€ ๋‚ด๋ ค๊ฐˆ ๋•Œ ์ œ์•ฝ์„ 0์œผ๋กœ ์ฃผ๊ณ  ์ž์—ฐ์Šค๋Ÿฝ๊ฒŒ ๋‚ด๋ ค๊ฐ€๋„๋ก ์• ๋‹ˆ๋ฉ”์ด์…˜์„ ๋„ฃ์–ด ๋ทฐ๋ฅผ ๋‹ค์‹œ ๊ทธ๋ฆผ

    // ๋ฒ„ํŠผ์˜ ์œ„์น˜๋ฅผ ๋™์ ์œผ๋กœ ๋ณ€๊ฒฝํ•˜๊ธฐ ์œ„ํ•œ ์ œ์•ฝ ์—ฐ๊ฒฐ
    @IBOutlet weak var buttonBottomConstraint: NSLayoutConstraint!
    
    override func viewWillAppear(_ animated: Bool) {
         super.viewWillAppear(animated)
    
         NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(_:)), name: UIResponder.keyboardWillShowNotification, object: nil)
         NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(_:)), name: UIResponder.keyboardWillHideNotification, object: nil)
    }
    
    override func viewWillDisappear(_ animated: Bool) {
         super.viewWillDisappear(animated)
    
         NotificationCenter.default.removeObserver(self)
    }
    
    @objc private func keyboardWillShow(_ notification: Notification) {
         guard let tabBar = self.tabBarController?.tabBar else {
              return
         }
         let tabBarHeight = tabBar.frame.size.height
    
         guard let keyboardFrame = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue else {
              return
         }
    
         let keyboardHeight = keyboardFrame.size.height
    
         buttonBottomConstraint.constant = keyboardHeight - tabBarHeight
         UIView.animate(withDuration: 0.3) {
             self.view.layoutIfNeeded()
         }
    }
    
    @objc private func keyboardWillHide(_ notification: Notification) {
         buttonBottomConstraint.constant = 0
         UIView.animate(withDuration: 0.3) {
             self.view.layoutIfNeeded()
         }
    }

โ“ ๋ฌธ์ œ

๋‹คํฌ๋ชจ๋“œ๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š๋Š” ์ปฌ๋Ÿฌ์˜ ๋‹คํฌ๋ชจ๋“œ ๋Œ€์‘ (๋‹คํฌ๋ชจ๋“œ ์ง€์›)

โ• ํ•ด๊ฒฐ ๋ฐฉ๋ฒ•

๐Ÿ’ก ๋ฌธ์ œ ์ƒํ™ฉ: ์œ ์ € ์ž…์žฅ์—์„œ์˜ ํŽธ๋ฆฌํ•œ ์‚ฌ์šฉ ๊ฒฝํ—˜์„ ์ œ๊ณต์„ ์œ„ํ•œ ๋‹คํฌ๋ชจ๋“œ ๋Œ€์‘์„ ํ•˜๊ณ  ์‹ถ์€๋ฐ ์–ด๋–ป๊ฒŒ ํ•ด์•ผ ํ• ๊นŒ?

  • UI ๊ธฐ๋ณธ์ปฌ๋Ÿฌ๋Š” ๋‹คํฌ๋ชจ๋“œ๋ฅผ ์ง€์›ํ•˜์ง€๋งŒ, ์ปค์Šคํ…€ ์ปฌ๋Ÿฌ๋Š” ๋‹คํฌ๋ชจ๋“œ๋ฅผ ์ง€์›ํ•˜์ง€ ์•Š์Œ
    • Assets์˜ Color Set์— ๋ผ์ดํŠธ๋ชจ๋“œ์™€ ๋‹คํฌ๋ชจ๋“œ์— ์ƒ‰์ƒ์„ ์ง€์ •ํ•˜์—ฌ ๋Œ€์‘ํ•จ แ„‰แ…ณแ„แ…ณแ„…แ…ตแ†ซแ„‰แ…ฃแ†บ 2023-11-22 แ„‹แ…ฉแ„’แ…ฎ 2 42 39

      // ๋‹คํฌ๋ชจ๋“œ์ผ ๋•Œ ๊ธ€์ž์ƒ‰ ๋ณ€๊ฒฝ
      textView.textColor = UIColor { (traitCollection: UITraitCollection) -> UIColor in
          if traitCollection.userInterfaceStyle == .dark {
               return UIColor.white
      	  } else {
               return UIColor.black
          }

โœ… 1.1 ์—…๋ฐ์ดํŠธ

  • ๋ฒ„๊ทธ ์ˆ˜์ • b201ba4

    • ์นดํ…Œ๊ณ ๋ฆฌ์—์„œ ์ˆ˜์ •ํ•˜๋Š” ํ™”๋ฉด ์ง„์ž… ์‹œ ๋‚ ์งœ ๋žœ๋ค์œผ๋กœ ๋ณด์ด๋Š” ๊ฒƒ ์ˆ˜์ •
    • ๋ชจ์•„๋ณด๊ธฐ์—์„œ ์ˆ˜์ •ํ•˜๋Š” ํ™”๋ฉด ์ง„์ž… ์‹œ ์นดํ…Œ๊ณ ๋ฆฌ ๋žœ๋ค์œผ๋กœ ๋ณด์ด๋Š” ๊ฒƒ ์ˆ˜์ •
    • ๋ฏธ๋ฆฌ๋ณด๊ธฐ ๋ฉ”๋ชจ์™€ ๋ณธ๋ฌธ์˜ ๋ฉ”๋ชจ๊ฐ€ ๋‹ค๋ฅธ ๊ฒƒ ์ˆ˜์ •
    • ๋ฉ”๋ชจ ์ˆ˜์ • ์‹œ ์นดํ…Œ๊ณ ๋ฆฌ ์ง€์ •ํ•˜์ง€ ์•Š์œผ๋ฉด ์—…๋ฌด๋กœ ์ง€์ •๋˜๋Š” ๊ฒƒ ์ˆ˜์ •
  • delete ์•ˆ๋˜๋Š” ๊ฒƒ ์ˆ˜์ • c16406b

About

๐Ÿ—’๏ธ ์นดํ…Œ๊ณ ๋ฆฌ ๋ณ„๋กœ ๋‚˜๋ˆ„์–ด ์ €์žฅํ•˜๋Š” ๋ฉ”๋ชจ์•ฑ (App Store ์ถœ์‹œ)


Languages

Language:Swift 100.0%