Skip to content

Log-Of-Yagom-Career/ios-diary

Repository files navigation

Diary ReadME

  • Kyo์™€ Baem๊ฐ€ ๋งŒ๋“  Diary App์ž…๋‹ˆ๋‹ค.
  • ํ…์ŠคํŠธ ๊ธฐ๋Šฅ์„ ๊ตฌํ˜„ ํ•  ๋•Œ, ์•„์ดํฐ ๋ฉ”๋ชจ ์•ฑ์˜ ํ…์ŠคํŠธ ์ž…๋ ฅ ๋กœ์ง์„ ์ฐธ๊ณ ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๋ชฉ์ฐจ

  1. ํŒ€ ์†Œ๊ฐœ
  2. GroundRule
  3. Code Convention
  4. ์‹คํ–‰ ํ™”๋ฉด
  5. ํด๋” ๊ตฌ์กฐ
  6. ํƒ€์ž„๋ผ์ธ
  7. ๊ธฐ์ˆ ์  ๋„์ „
  8. ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ… ๋ฐ ๊ณ ๋ฏผ
  9. ์ฐธ๊ณ  ๋งํฌ

ํŒ€ ์†Œ๊ฐœ

Kyo Baem

Ground Rule

Ground Rule ๋ฐ”๋กœ๊ฐ€๊ธฐ

Code Convention

Code Convention ๋ฐ”๋กœ๊ฐ€๊ธฐ

์‹คํ–‰ ํ™”๋ฉด

โ–ถ๏ธ Step-1 ์‹คํ–‰ํ™”๋ฉด

ํŽผ์ณ๋ณด๊ธฐ
์‹คํ–‰ํ™”๋ฉด ์–ธ์–ด๋ณ€๊ฒฝ

โ–ถ๏ธ Step-2 ์‹คํ–‰ํ™”๋ฉด

ํŽผ์ณ๋ณด๊ธฐ
๋ฏธ ์ž…๋ ฅ ์ผ๊ธฐ์ƒ์„ฑ Background ์ง„์ž…์‹œ ์ €์žฅ
ActivityController๊ตฌํ˜„ ์Šค์™€์ดํ”„์‚ญ์ œ ์ผ๊ธฐ๋‚ด์—์„œ ์‚ญ์ œ

โ–ถ๏ธ Step-3 ์‹คํ–‰ํ™”๋ฉด

ํŽผ์ณ๋ณด๊ธฐ
CLLocation์˜ ์‚ฌ์šฉ Cell์ฐŒ๊ทธ๋Ÿฌ์ง ๊ฐœ์„ 
AttributeString์ปค์„œ์ด๋™ ๋ณด์™„ DarkMode

ํด๋” ๊ตฌ์กฐ

โ”œโ”€โ”€ Diary
โ”‚ย ย  โ”œโ”€โ”€ AppDelegate.swift
โ”‚ย ย  โ”œโ”€โ”€ SceneDelegate.swift
โ”‚ย ย  โ”œโ”€โ”€ Info.plist
โ”‚ย ย  โ”œโ”€โ”€ Base.lproj
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ LaunchScreen.storyboard
โ”‚ย ย  โ”œโ”€โ”€ Constant
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ Error.swift
โ”‚ย ย  โ”œโ”€โ”€ Extensions
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ Formatter+Extension.swift
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ NSMutableAttributedString+Extension.swift
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ UIComponent+Extension.swift
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ UIViewController+Extension.swift
โ”‚ย ย  โ”œโ”€โ”€ Models
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ CoreData
โ”‚ย ย  โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ CoreDataManager.swift
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ CurrentDiary.swift
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ CurrentWeather.swift
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ DecoderManager.swift
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ Network
โ”‚ย ย  โ”‚ย ย      โ”œโ”€โ”€ NetworkManager.swift
โ”‚ย ย  โ”‚ย ย      โ”œโ”€โ”€ NetworkRequest.swift
โ”‚ย ย  โ”‚ย ย      โ””โ”€โ”€ WeatherAPIData.swift
โ”‚ย ย  โ”œโ”€โ”€ Views
โ”‚ย ย  |   โ”œโ”€โ”€ CustomListCell.swift
โ”‚ย ย  |   โ”œโ”€โ”€ EditDiaryView.swift
โ”‚ย ย  |   โ””โ”€โ”€ MainDiaryView.swift
โ”‚ย ย  โ”œโ”€โ”€ Controllers
โ”‚ย ย  โ”‚ย ย  โ”œโ”€โ”€ EditViewController.swift
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ MainViewController.swift
โ”‚ย ย  โ”œโ”€โ”€ MappingModelV2ToV3.xcmappingmodel
โ”‚ย ย  โ”‚ย ย  โ””โ”€โ”€ xcmapping.xml
โ”‚ย ย  โ””โ”€โ”€Diary.xcdatamodeld
โ”‚ย ย   ย ย  โ”œโ”€โ”€ Diary.xcdatamodel
โ”‚ย ย   ย ย  โ”‚ย ย  โ””โ”€โ”€ contents
โ”‚ย ย   ย ย  โ”œโ”€โ”€ Diary_v2.xcdatamodel
โ”‚ย ย   ย ย  โ”‚ย ย  โ””โ”€โ”€ contents
โ”‚ย ย   ย ย  โ”œโ”€โ”€ Diary_v3.xcdatamodel
โ”‚ย ย   ย ย  โ”‚ย ย  โ””โ”€โ”€ contents
โ”‚ย ย   ย ย  โ””โ”€โ”€ MappingModelV2ToV3.xcmappingmodel
โ”‚ย ย   ย ย      โ””โ”€โ”€ xcmapping.xml
โ”œโ”€โ”€ DiaryData+CoreDataClass.swift
โ”œโ”€โ”€ DiaryData+CoreDataProperties.swift
โ”œโ”€โ”€ WeatherData+CoreDataClass.swift
โ”œโ”€โ”€ WeatherData+CoreDataProperties.swift
โ”œโ”€โ”€ MappingModelV2ToV3.xcmappingmodel
โ”‚ย ย  โ””โ”€โ”€ xcmapping.xml
โ”œโ”€โ”€ Podfile
โ”œโ”€โ”€ Podfile.lock
โ””โ”€โ”€README.md

ํƒ€์ž„๋ผ์ธ

๐Ÿ‘Ÿ Step 1

  • โœ… Date Formatter์˜ ์ง€์—ญ ๋ฐ ๊ธธ์ด๋ณ„ ํ‘œํ˜„์˜ ํ™œ์šฉ
  • โœ… Text View์˜ ํ™œ์šฉ
  • โœ… Notification์„ ํ™œ์šฉํ•œ ํ‚ค๋ณด๋“œ ๋™์ž‘์— ๋”ฐ๋ฅธ View ์ œ์–ด
  • โœ… Compositional Layout์„ ์ด์šฉํ•œ CollectionView ํ™œ์šฉ
  • โœ… SwiftLint ์ ์šฉ
ํŽผ์ณ๋ณด๊ธฐ

1๏ธโƒฃ MainViewController

  • ์•ฑ ๋™์ž‘ ์‹œ ๊ฐ€์žฅ ๋จผ์ € ๋ณด์—ฌ์ฃผ๋Š” View์— ๋Œ€ํ•œ Controller์ž…๋‹ˆ๋‹ค.
  • MainViewController์—์„œ CollectionView์˜ DataSource๋กœ๋Š” DiffableDataSource๋ฅผ ์‚ฌ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.

2๏ธโƒฃ AddViewController

  • Right Navigation Bar Button์„ ํด๋ฆญํ–ˆ์„ ๋•Œ ๋ณด์—ฌ์ง€๋Š” AddDiaryView์— ๋Œ€ํ•œ Controller์ž…๋‹ˆ๋‹ค.
  • ๋‚ด๋ถ€์—์„œ title์„ ์„ค์ • ์–ธ์–ด์— ๋งž๋Š” ๋‚ ์งœ๋กœ ์„ค์ •ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

3๏ธโƒฃ DecodeManager

  • ์ž„์‹œ๋ฐ์ดํ„ฐ์ธ Json ๋ฐ์ดํ„ฐ์— ๋Œ€ํ•œ Decoder์™€ decode๊ด€๋ จ ๋ฉ”์„œ๋“œ๋ฅผ ์ •์˜ํ•œ ๊ตฌ์กฐ์ฒด๊ฐ€ ์ •์˜๋œ ํŒŒ์ผ์ž…๋‹ˆ๋‹ค.

4๏ธโƒฃ Diary

  • ๋ง ๊ทธ๋Œ€๋กœ Diary์— ๋Œ€ํ•œ ๋ฐ์ดํ„ฐ์ด๋ฉฐ, Hashable์„ ๋งŒ์กฑํ•˜๊ธฐ ์œ„ํ•ด uuid๋ฅผ ์ถ”๊ฐ€ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๐Ÿ‘Ÿ Step 2

  • โœ… ์ฝ”์–ด๋ฐ์ดํ„ฐ ๋ชจ๋ธ ์ƒ์„ฑ
  • โœ… Swipe๋ฅผ ํ†ตํ•œ ์‚ญ์ œ๊ธฐ๋Šฅ ๊ตฌํ˜„
  • โœ… Swipe๋ฅผ ํ†ตํ•œ ๊ณต์œ ๊ธฐ๋Šฅ ๊ตฌํ˜„
  • โœ… ActivityController ๊ตฌํ˜„
  • โœ… NSMutableAttributeString ํ™œ์šฉ
  • โœ… UICollectionLayoutListConfiguration ํ™œ์šฉ
  • โœ… Text View Delegate์˜ ํ™œ์šฉ
ํŽผ์ณ๋ณด๊ธฐ

1๏ธโƒฃ CoreDataManager

  • CoreDataManager์—์„œ CRUD๋ฅผ ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
    • Create(Save)
    • Read(Fetch)
    • Update
    • Delete
  • ์œ„ ๋ฉ”์„œ๋“œ๋“ค์„ ์ •์˜ํ•˜์—ฌ CoreDataManager์˜ ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด์—์„œ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

2๏ธโƒฃ AddViewController โžก๏ธ EditViewController

  • Add, Modifyํ•˜๋Š” ๊ธฐ๋Šฅ์˜ Controller์„ ํ•˜๋‚˜์˜ Controller๋กœ ํ†ตํ•ฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.

3๏ธโƒฃ EditDiaryView

  • Add, Modify ํ™”๋ฉด์„ ํ•˜๋‚˜์˜ View๋กœ ํ†ตํ•ฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๐Ÿ‘Ÿ Step 3

  • โœ… Open API์˜ ํ™œ์šฉ
  • โœ… Core Location์˜ ํ™œ์šฉ
  • โœ… ์ฝ”์–ด๋ฐ์ดํ„ฐ ๋ชจ๋ธ ๋ฐ DB ๋งˆ์ด๊ทธ๋ ˆ์ด์…˜
  • โœ… ์ฝ”์–ด๋ฐ์ดํ„ฐ ๋ชจ๋ธ Relationship ์‚ฌ์šฉ
  • โœ… NSMutableAttributeString ์‚ฌ์šฉ
  • โœ… selectedTextRange ์‚ฌ์šฉ
  • โœ… NSCache ์‚ฌ์šฉ
  • โœ… DarkMode ์ ์šฉ
ํŽผ์ณ๋ณด๊ธฐ

1๏ธโƒฃ CurrentDiary

  • CoreData์˜ ManagedObject์— ์ง์ ‘ ์ ‘๊ทผํ•˜์ง€ ์•Š๊ธฐ ์œ„ํ•œ Type์ž…๋‹ˆ๋‹ค.
  • ํ•ด๋‹น ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜์—ฌ ์‚ฌ์šฉ์ž๊ฐ€ ์ž…๋ ฅํ•œ Diary ์ •๋ณด๋“ค์„ ๋„ฃ๊ณ  CoreData ๋‚ด๋ถ€์— Saveํ•˜๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

2๏ธโƒฃ CurrentWeather

  • CoreData์˜ ManagedObject์— ์ง์ ‘ ์ ‘๊ทผํ•˜์ง€ ์•Š๊ธฐ ์œ„ํ•œ Type์ž…๋‹ˆ๋‹ค.
  • ์‚ฌ์šฉ์ž Device์— ๋Œ€ํ•œ ์œ„๋„ ๊ฒฝ๋„๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ํ•ด๋‹น ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜์—ฌ Open API์—์„œ ๊ฐ€์ ธ์˜จ ๋‚ ์”จ์— ๋Œ€ํ•œ data์™€ icon์— ๋Œ€ํ•œ data๋ฅผ ๋„ฃ๊ณ  CoreData ๋‚ด๋ถ€์— Saveํ•˜๋„๋ก ํ•˜์˜€์Šต๋‹ˆ๋‹ค.

3๏ธโƒฃ NetworkManager

  • Server์— ๋ฐ์ดํ„ฐ๋ฅผ ์š”์ฒญํ•˜๊ธฐ ์œ„ํ•œ fetchData()๊ฐ€ ์†ํ•ด์žˆ๋Š” class์ž…๋‹ˆ๋‹ค.
  • ํ•ด๋‹น ํด๋ž˜์Šค๋Š” ์—ฌ๋Ÿฌ๊ฐœ ๋งŒ๋“ค ํ•„์š”๊ฐ€ ์—†๋‹ค๊ณ  ์ƒ๊ฐ๋˜์–ด ์‹ฑ๊ธ€ํ†ค ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.

4๏ธโƒฃ NetworkRequest

  • ์œ„๋„, ๊ฒฝ๋„๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ๋‚ ์”จ์— ๋Œ€ํ•œ data, ๋‚ ์”จ iconID์— ๋Œ€ํ•œ data๋ฅผ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ๋Š” URL.
  • ๋‚ ์”จ iconID์„ ์„œ๋ฒ„์— ๋ณด๋‚ด์„œ ํ•ด๋‹น ID์— ๋งž๋Š” IconImage๋ฅผ ๋ฐ›์•„์˜ฌ ์ˆ˜ ์žˆ๋Š” URL.
  • ์œ„์˜ 2๊ฐœ์˜ case์— ๋งž๋Š” URL์„ ์–ป๊ธฐ ์œ„ํ•ด ๋งŒ๋“  ๋ณ„๋„์˜ enum ํƒ€์ž…์ž…๋‹ˆ๋‹ค.

5๏ธโƒฃ WeatherAPIData

  • ์„œ๋ฒ„์—์„œ ๋ฐ›์•„์˜จ weather ๋ฐ์ดํ„ฐ๋ฅผ ๋””์ฝ”๋”ฉํ•˜๊ธฐ ์œ„ํ•œ Type์ž…๋‹ˆ๋‹ค.

๊ธฐ์ˆ ์  ๋„์ „

โš™๏ธ ModernCollectionView - CompositionalLayout

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

โš™๏ธ DiffableDataSource

ํŽผ์ณ๋ณด๊ธฐ
  • ๊ธฐ์กด์˜ DataSource๋ฅผ ๊ฒฝํ—˜ํ•ด๋ณด๊ณ  ์ƒˆ๋กญ๊ฒŒ Diffable Data Source๋ฅผ ์‚ฌ์šฉํ•ด๋ณด๊ณ ์ž ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  • DiffableDataSource์˜ ์žฅ์ ์€ ๋ฐ์ดํ„ฐ ๋™๊ธฐํ™”, ๋ฐ์ดํ„ฐ ์ถ”๊ฐ€, ์—…๋ฐ์ดํŠธ, ์‚ญ์ œ์‹œ Animate์ ์šฉ์ด ๊ฐ€๋Šฅํ•˜๋‹ค๋Š” ์  ์ž…๋‹ˆ๋‹ค.
  • ๋˜ํ•œ ๊ธฐ์กด์˜ DataSource๋ณด๋‹ค ์ฝ”๋“œ๋Ÿ‰๋„ ๊ฐ์†Œ์‹œํ‚ฌ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
  • ๊ทธ๋ฆฌ๊ณ  Section๋งˆ๋‹ค ๋‹ค๋ฅธ ๋ฐ์ดํ„ฐ๋“ค์„ ์ ์šฉํ•  ์ˆ˜๋„ ์žˆ๋‹ค๋Š” ์ ์ด ์žฅ์ ์ด๋ผ๊ณ  ์ƒ๊ฐํ•ฉ๋‹ˆ๋‹ค.
  • DiffableDataSource๋ฅผ ์ ์šฉํ•ด๋ณด๋ฉด์„œ ์ฝ”๋“œ์˜ ๊ธธ์ด๊ฐ€ ๊ธธ์–ด์ง€๋Š” ๋ถ€๋ถ„์€ typealias๋ฅผ ํ™œ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  • ์•„์ง Animation์„ ์ ์šฉํ•˜๋Š” ๋ถ€๋ถ„์ด ๋งŽ์ง€ ์•Š์•„ ๊ธฐ์กด DataSource์™€ ๋น„๊ตํ•ด์„œ ์žฅ์ ์— ๋Œ€ํ•œ ์ฒด๊ฐ์€ ๋ชปํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ถ”ํ›„ Animation์„ ์ ์šฉํ•˜๋Š” ๋ถ€๋ถ„์ด ๋งŽ์•„์ง„๋‹ค๋ฉด Diffable DataSurce๋กœ ์‚ฌ์šฉ์ž ๊ฒฝํ—˜์„ ๋†’ํž ์ˆ˜ ์žˆ๋‹ค๋Š” ์ ์€ ํฐ ์žฅ์ ์ด๋ผ๊ณ  ์ƒ๊ฐ์ด ๋˜์–ด ๋„์ž…ํ•ด๋ณด์•˜์Šต๋‹ˆ๋‹ค.

โš™๏ธ DataFormatter, Locale์˜ ์‚ฌ์šฉ

ํŽผ์ณ๋ณด๊ธฐ
  • ์ƒˆ๋กœ์šด Diary๋ฅผ ์ถ”๊ฐ€ ํ•  ๋•Œ ์ง€์—ญ์— ๋งž๋Š” ๋‚ ์งœ, ๋‚ ์งœ ํ‘œ๊ธฐ๋ฒ•์„ ์ˆ˜๋™์ ์œผ๋กœ ์„ ํƒํ•ด์ฃผ๋Š” ๊ฒƒ์ด ์•„๋‹Œ ์ž๋™์ ์œผ๋กœ ๋ฐ˜ํ™˜ํ•ด์ฃผ๊ธฐ ์œ„ํ•ด DataFormatter๋ฅผ ์ถ”๊ฐ€ํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.
  • ์‚ฌ์šฉ์ž์˜ ๊ธฐ๊ธฐ preferredLanguage์— ๋”ฐ๋ผ ๋‚ ์งœ์˜ ํ‘œ๊ธฐ๋ฐฉ๋ฒ•์ด ์ž๋™์œผ๋กœ ๋ณ€๊ฒฝ๋˜๋„๋ก ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.. (์„ธ๊ณ„ํ™”, Internationalization)
  • ์‚ฌ์šฉ์ž์˜ ์œ„์น˜์— ๋”ฐ๋ผ ๋‚ ์งœ๊ฐ€ ๋ณ€ํ•  ์ˆ˜ ์žˆ๋„๋ก, Locale์„ ํ™œ์šฉํ•˜์—ฌ Localization(์ง€์—ญํ™”)๋ฅผ ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.
extension Formatter {
    static func changeCustomDate(_ date: Date) -> String {
        let locale = NSLocale.preferredLanguages.first
        let formatter = DateFormatter()
        formatter.locale = Locale(identifier: locale ?? Locale.current.identifier)
        formatter.timeZone = TimeZone(identifier: TimeZone.current.identifier)
        ...
        return formatter.string(from: date)
    }
}

โš™๏ธ Swipe

ํŽผ์ณ๋ณด๊ธฐ
  • ๊ฐ ๋ฉ”์ธํ™”๋ฉด์˜ List์˜ Cell์„ Swipe์‹œ Share, Deleteํ•  ์ˆ˜ ์žˆ๋Š” ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  • Diary App์—์„œ UICollectionLayoutListConfiguration๋ฅผ ์‚ฌ์šฉํ•˜์˜€๊ธฐ ๋•Œ๋ฌธ์— UISwipeActionsConfiguration๋ฅผ configuration.trailingConfiguration์— ์ถ”๊ฐ€ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.
    var configuration = UICollectionLayoutListConfiguration(appearance: .plain)
        configuration.trailingSwipeActionsConfigurationProvider = .some({ indexPath in
            self.delegate?.makeSwipeActions(for: indexPath)
        })
  • ๊ทธ๋ฆฌ๊ณ  ShareAction, DeleteAction์„ ์ถ”๊ฐ€ ๊ตฌํ˜„ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

โš™๏ธ NSMutableAttributedString ์‚ฌ์šฉ

ํŽผ์ณ๋ณด๊ธฐ
  • NSMutableAttributedString์€ ๋ฌธ์ž์—ด์˜ ํŠน์ • ๋ถ€๋ถ„์— ์›ํ•˜๋Š” ์†์„ฑ์„ ์ฃผ๊ณ  ์‹ถ์„ ๋•Œ ์‚ฌ์šฉํ•˜๋Š” ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค. ํŠน์ • ๋ฌธ์ž์—ด๋งŒ ๋‹ค๋ฅธ ํฐํŠธ, ๋‹ค๋ฅธ Color์„ ๋ถ€์—ฌํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
  • ํ•˜๋‚˜์˜ TextView์—์„œ ์ฒซ์ค„(Title)์˜ Text๊ณผ ๊ทธ ์ด์™ธ์˜ Text๋ฅผ ๋‹ค๋ฅธ Font๋ฅผ ์ ์šฉํ•˜๊ณ ์ž ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  • ๋˜ํ•œ AttributeString์„ ์‚ฌ์šฉํ•จ์— ๋”ฐ๋ผ ์ปค์„œ์˜ ๋งจ๋งˆ์ง€๋ง‰์œผ๋กœ ์ด๋™๋จ์— ๋”ฐ๋ผ selectedTextRange๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์˜ฌ๋ฐ”๋ฅธ ์ปค์„œ์˜ ์œ„์น˜๋กœ ์ด๋™์‹œ์ผœ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

โš™๏ธ CoreData Migration, Relationship

ํŽผ์ณ๋ณด๊ธฐ
  • CoreData์— WeatherData ์ถ”๊ฐ€๊ฐ€ ํ•„์š”ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— Data Migration์„ ์‚ฌ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค. CoreData Migration์€ Managed Object์™€ ์›๋ณธ ๊ฐ„์˜ ์ฐจ์ด์ ์„ ์ž๋™์œผ๋กœ ์œ ์ถ”ํ•ฉ๋‹ˆ๋‹ค. ์ด๋•Œ WeatherData๋ฅผ ์ถ”๊ฐ€๋งŒ ํ–ˆ๊ธฐ๋•Œ๋ฌธ์— ๋ณ„๋„์˜ MappingModel์€ ๋งŒ๋“ค์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.
  • Migration์„ ์ง„ํ–‰์„ ํ•œ ํ›„์—, Weather Data์™€ ๊ธฐ์กด์˜ Diary Data๊ฐ€ ๋ฐ์ดํ„ฐ์˜ ์„ฑํ–ฅ์ด ๋‹ค๋ฅด๊ธฐ ๋•Œ๋ฌธ์— ํ•˜๋‚˜์˜ Entity์— ์žˆ๋Š” ๊ฒƒ์€ ๋งž์ง€ ์•Š๋‹ค๊ณ  ๋Š๊ปด์กŒ์Šต๋‹ˆ๋‹ค.
  • ๋•Œ๋ฌธ์—, Entity๋“ค ๊ฐ„์˜ ๊ด€๊ณ„๋ฅผ ์ •์˜ํ•ด ์ค„ ์ˆ˜ ์žˆ๋Š”, Entity๋“ค ๊ฐ„์˜ ์˜ํ–ฅ์„ ์„ค๋ช…ํ•ด์ค„ ์ˆ˜ ์žˆ๋Š” Relationship์„ ์ถ”๊ฐ€ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.
  • ์ถ”๊ฐ€๋ฅผ ํ•œํ›„์—๋Š” ํ•˜๋‚˜์˜ Entity์—์„œ ๋‘ ๊ฐœ์˜ Entity๋กœ ๋‚˜๋ˆ ์กŒ๊ธฐ ๋•Œ๋ฌธ์— ๋ณ„๋„์˜ MappingModel ๋˜ํ•œ ์ถ”๊ฐ€ํ•ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.
DiaryData WeatherData

โš™๏ธ Open API

ํŽผ์ณ๋ณด๊ธฐ
  • Device์˜ ์œ„๋„ ๊ฒฝ๋„๋ฅผ ๋ฐ”ํƒ•์œผ๋กœ ํ˜„์žฌ ๋‚ ์”จ ๋ฐ ๋‚ ์”จ์™€ ๊ด€๋ จ๋œ Icon์„ ๋ฐ›์•„์˜ค๊ธฐ ์œ„ํ•ด Openweather API๋ฅผ ์‚ฌ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  • NetworkManager๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๊ณ  ๋‚ด๋ถ€์—์„œ API์™€ ํ†ต์‹ ์„ ํ•  ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.

โš™๏ธ Core Location

ํŽผ์ณ๋ณด๊ธฐ
  • Core Location์€ iOS ๊ธฐ๋ณธ Framework์ธ Core Service์— ์†ํ•ด์žˆ๋Š” Framework์ž…๋‹ˆ๋‹ค.
  • ๊ธฐ๋ณธ์ ์œผ๋กœ iPhone Device์˜ ์œ„์น˜๋ฅผ ์–ป์–ด์˜ฌ ์ˆ˜ ์žˆ๋Š” Framework์ž…๋‹ˆ๋‹ค.
  • Core Location์„ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด์„œ๋Š” CLLocationManger๋ผ๋Š” ์ธ์Šคํ„ด์Šค๋ฅผ ๋ฐ˜๋“œ์‹œ ์‚ฌ์šฉํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
  • ๋˜ํ•œ, Info.plist์—์„œ ์œ„์น˜ ๊ถŒํ•œ์„ ํ—ˆ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ์ •๋ณด ์ œ๊ณต Alert์„ ๋„์›Œ์ค˜์•ผํ•ฉ๋‹ˆ๋‹ค.
  • ํ•ด๋‹น ํ”„๋กœ์ ํŠธ์—์„œ๋Š” ์ผ๊ธฐ๋ฅผ ์ž…๋ ฅํ•  ๋•Œ, ์œ„์น˜๋ฅผ ๋ถˆ๋Ÿฌ์™€์„œ ์œ„์น˜์— ๋Œ€ํ•œ ๋‚ ์”จ ์ •๋ณด(๋‚ ์”จ ์•„์ด์ฝ˜)์„ Navigation Bar์— ๋ณด์—ฌ์ค˜์•ผํ•˜๊ณ , Main ํ™”๋ฉด์—์„œ ์ €์žฅํ•œ ๋‚ ์”จ ์ •๋ณด์— ๋Œ€ํ•œ ๋‚ ์”จ ์•„์ด์ฝ˜์„ ๋ณด์—ฌ์ค˜์•ผํ–ˆ๊ธฐ ๋•Œ๋ฌธ์— ์œ„๋„, ๊ฒฝ๋„ ์ €์žฅ์„ ์œ„ํ•ด ์‚ฌ์šฉ์„ ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
if let coordinate = locations.last?.coordinate {
    let url = NetworkRequest.fetchData(lat: String(coordinate.latitude), 
    lon: String(coordinate.longitude)).generateURL()
...
  • ์œ„ ์ฝ”๋“œ์ฒ˜๋Ÿผ coordinate์—์„œ ์œ„๋„, ๊ฒฝ๋„๋ฅผ ๋ฐ›์•„ ์˜ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

ํŠธ๋Ÿฌ๋ธ” ์ŠˆํŒ… ๋ฐ ๊ณ ๋ฏผ

๐Ÿ”ฅ Keyboard ์‚ฌ์šฉ์— ๋”ฐ๋ฅธ AutoLayout Constraint ๋ณ€๊ฒฝ์— ๋Œ€ํ•œ ๊ณ ๋ฏผ

ํŽผ์ณ๋ณด๊ธฐ

๋ฌธ์ œ ๐Ÿ‘€

  • ์ €ํฌ๋Š” ํ‚ค๋ณด๋“œ ์‚ฌ์šฉ์— ๋”ฐ๋ผ TextView์˜ ์ œ์•ฝ์กฐ๊ฑด์„ ๋ณ€๊ฒฝํ•˜์—ฌ TextView๊ฐ€ ํ‚ค๋ณด๋“œ๋ฅผ ์ œ์™ธํ•˜๊ณ  ๋ณด์—ฌ์ง€๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค. ํ•˜์ง€๋งŒ TextView์˜ Bottom์ œ์•ฝ์„ ๋ณ€๊ฒฝํ•ด์ฃผ๋Š” ๋ฐฉ์‹์œผ๋กœ ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.
์œ„์˜ ์‚ฌ์ง„์ฒ˜๋Ÿผ Constarint์˜ ์ถฉ๋Œ์ด ์ผ์–ด๋‚ฌ์Šต๋‹ˆ๋‹ค. **ํ•ด๊ฒฐ ๐Ÿ”ฅ** - `func setupConstraints()` ๋‚ด๋ถ€์—์„œ ์ดˆ๊ธฐ Constraint๋ฅผ ์žก์•„ ์ค„ ๋•Œ, TextView์˜ Bottom Constraint๊นŒ์ง€ ์žก์•„์ฃผ๊ณ , ํ‚ค๋ณด๋“œ ๋‚˜ํƒ€๋‚จ์— ๋”ฐ๋ผ ๋‹ค์‹œ ์ œ์•ฝ์„ ์ถ”๊ฐ€์ ์œผ๋กœ ์žก์•„์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค. - ๋”ฐ๋ผ์„œ ๊ธฐ์กด Constraint์„ `false`๋กœ ๋ณ€๊ฒฝํ•˜๊ณ  ์ƒˆ๋กœ์šด ์ œ์•ฝ์„ `true` ํ•ด์•ผ ์ถฉ๋Œ๋‚˜์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์ฃผ์˜ํ•ด์„œ Constraint๋ฅผ ์žก์•„์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

๐Ÿ”ฅ UIComponent Object ์ƒ์„ฑ์‹œ ์ค‘๋ณต์ฝ”๋“œ ๊ฐ์†Œ์— ๋Œ€ํ•œ ๊ณ ๋ฏผ

ํŽผ์ณ๋ณด๊ธฐ

๋ฌธ์ œ ๐Ÿ‘€

  • UIComponent๋ฅผ View์—์„œ ์ƒ์„ฑํ• ๋•Œ ํด๋กœ์ €๋ฅผ ์ด์šฉํ•˜์—ฌ ์ƒ์„ฑํ•˜์˜€์—ˆ์Šต๋‹ˆ๋‹ค. ์—ฌ๋Ÿฌ๊ฐœ์˜ Label, StackView๊ฐ€ ํ•„์š”ํ•œ ์ƒํ™ฉ์—์„œ ์ฝ”๋“œ์˜ ์ค‘๋ณต์„ฑ์ด ๋Š๊ปด์กŒ๊ณ  ๋น„ํšจ์œจ์ ์ด๋ผ๊ณ  ์ƒ๊ฐ์ด ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ ๐Ÿ”ฅ

  • 2๊ฐœ ์ด์ƒ ์‚ฌ์šฉ๋˜๋Š” UIComponent๋“ค์— ๋Œ€ํ•ด์„œ Extension์œผ๋กœ ์ €ํฌ๊ฐ€ ์›ํ•˜๋Š” convenience initializer์„ ์ƒ์„ฑํ•ด์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.
  • ์ด๋ ‡๊ฒŒ ๊ตฌํ˜„์˜ ๊ฒฐ๊ณผ 1๊ฐœ์˜ UIComponent๋ฅผ ์ƒ์„ฑํ• ๋•Œ, ๊ธฐ์กด๋ณด๋‹ค ์ฝ”๋“œ๋Ÿ‰์ด 1/5 ์ค„๋กœ ๊ฐ์†Œํ•˜์˜€์Šต๋‹ˆ๋‹ค.
// Befor 
private lazy var bottomStackView: UIStackView = {
    let stackView = UIStackView(arrangedSubviews: [dateLabel, previewLabel])
    stackView.spacing = 5
    stackView.axis = .horizontal
    stackView.alignment = .center
    stackView.distribution = .fill
    return stackView
}()

// After
private lazy var bottomStackView = UIStackView(subview: [dateLabel, previewLabel],
                                            spacing: 5,
                                            axis: .horizontal,
                                            alignment: .firstBaseline,
                                            distribution: .fill)

๐Ÿ”ฅ Add, Modify ๊ธฐ๋Šฅ์„ ํ•˜๋‚˜์˜ View, ํ•˜๋‚˜์˜ Controller๋กœ ๊ตฌํ˜„

ํŽผ์ณ๋ณด๊ธฐ
  • Diary๋ฅผ ADDํ•˜๊ณ , Modifyํ•˜๋Š” Controller์˜ ์—ญํ• ๊ณผ View๊ฐ€ ๋งค์šฐ ์œ ์‚ฌํ•˜๋‹ค๊ณ  ์ƒ๊ฐ์„ ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • MainViewController์—์„œ Modify๋ฅผ ํ•  ๋•Œ๋Š” indexPath๋ฅผ ํ†ตํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ „๋‹ฌํ•˜๊ณ , + ๋ฒ„ํŠผ์„ ๋ˆŒ๋Ÿฌ ์ถ”๊ฐ€ํ• ๋•Œ๋Š” nil์„ ์ „๋‹ฌํ•˜์—ฌ Controller๊ฐ€ Add๊ธฐ๋Šฅ, Modify๊ธฐ๋Šฅ์„ ๋ถ„๊ธฐ์ฒ˜๋ฆฌ ํ•  ์ˆ˜ ์žˆ๋„๋ก ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  • ๋‘ ๊ฐ€์ง€์˜ ๊ธฐ๋Šฅ์„ ํ•˜๋‚˜๋กœ ํ•˜์˜€์„ ๋•Œ์˜ ์žฅ์ ์€ ๋กœ์ง์€ ์ถ”๊ฐ€๋˜์ง€๋งŒ ์ „์ฒด์ ์ธ ์ฝ”๋“œ๋Ÿ‰ ๊ฐ์†Œ, ๊ด€๋ฆฌํ•  Class๊ฐ€ ์ ์–ด์ง„๋‹ค๋Š” ์ ์ด๋ผ๊ณ  ์ƒ๊ฐ์ด ๋“ญ๋‹ˆ๋‹ค.
  • ํ•˜์ง€๋งŒ, ๋‘ ๊ฐœ์˜ ์ปจํŠธ๋กค๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๋กœ์ง์ด ๊ฐ„๊ฒฐํ•ด์ง„๋‹ค๋Š” ์ , ๋ช…ํ™•ํ•˜๋‹ค๋Š” ์ ์—์„œ ์ด์ ์ด ์žˆ๋‹ค๊ณ  ์ƒ๊ฐ์ด ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ”ฅ UISwipeActionsConfiguration ์ถ”๊ฐ€

ํŽผ์ณ๋ณด๊ธฐ
  • ๋ฆฌ์ŠคํŠธ๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ์œ„ํ•ด UICollectionLayoutListConfiguration์„ ์‚ฌ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  • CollectionView์˜ Configuration ๊ตฌ์„ฑ์€ View์˜ ์—ญํ• ์ด๋ผ๊ณ  ์ƒ๊ฐ์ด ๋˜์–ด View ๋‚ด๋ถ€์— CollectionView Configure์„ ํ•˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  • ํ›„์—, Swipe๋ฅผ ๊ตฌํ˜„ํ•ด์•ผํ–ˆ์„ ๋•Œ View์—์„œ ๊ตฌํ˜„ํ•œ Configureํ•˜๋Š” ๋ฉ”์„œ๋“œ์—์„œ SwipeActione๋“ค์„ ์ถ”๊ฐ€ํ•ด์ฃผ์–ด์•ผ ํ–ˆ๊ณ , Swipe ๊ธฐ๋Šฅ์„ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด์„œ๋Š” Controller์˜ Snapshot์— ๋Œ€ํ•œ ์ ‘๊ทผ, Delete Swipe ๊ธฐ๋Šฅ์„ ์œ„ํ•œ CoreData์— ๋Œ€ํ•œ ์ ‘๊ทผ์„ ํ•„์š”๋กœ ํ•˜์˜€์Šต๋‹ˆ๋‹ค.
  • ViewController์—์„œ CollectionView ํ˜น์€, Configure์„ View ์ƒ์„ฑ์‹œ์ ์— ์ฃผ์ž…ํ•˜๋Š” ๋ฐฉ๋ฒ•๋„ ์ข‹๊ฒŸ๋‹ค๊ณ  ์ƒ๊ฐํ–ˆ์ง€๋งŒ, Controller์˜ ์—ญํ• ์—์„œ ๋ฒ—์–ด๋‚œ ๊ธฐ๋Šฅ์„ ์ˆ˜ํ–‰ํ•œ๋‹ค๊ณ  ํŒ๋‹จํ•˜์—ฌ Delegate ํŒจํ„ด์„ ์‚ฌ์šฉํ•˜์—ฌ SwipeConfiguration์„ ์ „๋‹ฌํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๐Ÿ”ฅ NSMutableAttributedString ์‚ฌ์šฉ์— ๋”ฐ๋ฅธ TextView๋‚ด๋ถ€ ํ…์ŠคํŠธ ์ปค์„œ ์ด๋™

ํŽผ์ณ๋ณด๊ธฐ
  • ์ฒ˜์Œ์—๋Š” textField์™€ textView์— ๋งŒ๋“ค์—ˆ์Šต๋‹ˆ๋‹ค. ๊ฐ๊ฐ์— ํ•ด๋‹นํ•˜๋Š” ํฐํŠธ๋ฅผ ์‚ฌ์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.
    • textField : title3
    • textView : body
  • ๊ทธ๋ ‡๊ธฐ ๋•Œ๋ฌธ์— Field, View ๊ฐ„์˜ ๊ฐ„์„ญ์ด ์—†๊ธฐ ๋•Œ๋ฌธ์— ํฐํŠธ์— ๋Œ€ํ•ด์„œ ์‹ ๊ฒฝ์„ ๋งŽ์ด ์จ์ฃผ์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.
  • ๋งŽ์€ ์ƒ๊ฐ ํ›„, ์šฐ๋ฆฌ๋Š” ์•„์ดํฐ ๋ฉ”๋ชจ์•ฑ์„ ์ฐธ๊ณ ํ•˜์—ฌ ์‚ฌ์šฉ์„ ๊ณ ๋ คํ•˜์—ฌ, ํ•˜๋‚˜์˜ TextView๋กœ ๋ณด์—ฌ์ฃผ๊ณ ์ž ํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ๊ทธ๋ ‡๊ธฐ์— NSMutableAttributedString์„ ์‚ฌ์šฉํ•˜์—ฌ ์ฒซ๋ฒˆ์งธ Title ๋ถ€๋ถ„๋งŒ์„ ๋‹ค๋ฅธ ํฐํŠธ๋กœ ์ ์šฉํ•˜์˜€์Šต๋‹ˆ๋‹ค.

๋ฌธ์ œ ๐Ÿ‘€

func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { ... }
    
func textViewDidChange(_ textView: UITextView) { ... } 
  • ํ…์ŠคํŠธ ์ž…๋ ฅ์‹œ ์ฆ‰๊ฐ์ ์œผ๋กœ Font ๋ณ€๊ฒฝ์„ ์œ„ํ•ด ์œ„์˜ ๋‘ ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์˜€๋Š”๋ฐ,
  • NSMutableAttributedString ์ด ํ˜ธ์ถœ๋  ๋•Œ๋งˆ๋‹ค ํ…์ŠคํŠธ ์ปค์„œ๊ฐ€ ํ…์ŠคํŠธ์˜ ๋งˆ์ง€๋ง‰์— ์œ„์น˜ํ•˜๊ฒŒ ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.

ํ•ด๊ฒฐ๋ฐฉ๋ฒ• ๐Ÿ”ฅ

  • AttributeString์„ ์‚ฌ์šฉํ•˜๋ฉด์„œ ํ…์ŠคํŠธ ์ž…๋ ฅ์‹œ ๋งค๋ฒˆ AttributeString์ด ํ˜ธ์ถœ ๋˜๊ธฐ ๋•Œ๋ฌธ์— ํ…์ŠคํŠธ ์ปค์„œ๊ฐ€ ๋งจ ๋งˆ์ง€๋ง‰์œผ๋กœ ์›€์ง์ด๋Š” ๊ฒƒ์„ ํ™•์ธํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ๊ทธ๋ž˜์„œ ํ…์ŠคํŠธ์˜ ๋ณ€ํ™”๊ฐ€ ๊ฐ์ง€๋˜๋Š” Delegate์ธ textViewDidChange๋ฅผ ์ด์šฉํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ํ…์ŠคํŠธ๊ฐ€ ๊ฐ์ง€๋˜๊ณ  ์ปค์„œ์˜ ์œ„์น˜๋ฅผ ๊ธฐ์–ตํ•œ ํ›„ AttributeString์„ ํ˜ธ์ถœํ•ฉ๋‹ˆ๋‹ค. ๊ทธ๋‹ค์Œ ์›๋ž˜ ์ปค์„œ๋กœ ๋Œ์•„๊ฐ€๋„๋ก ๋งŒ๋“ค์–ด ์ฃผ์—ˆ์Šต๋‹ˆ๋‹ค.
  • textRange(from: to:) ๋ฐ UITextPosition()์„ ์‚ฌ์šฉํ•˜์—ฌ ์ปค์„œ์˜ ์œ„์น˜๋ฅผ ๊ธฐ์–ตํ•˜๋„๋ก ํ–ˆ์Šต๋‹ˆ๋‹ค.
func textViewDidChange(_ textView: UITextView) {
        guard let range = textView.selectedTextRange else { return }
        guard let position = textView.position(from: range.start, offset: 0) else { return }
        ...
        AttributeString()
        ...
        textView.selectedTextRange = textView.textRange(from: position, to: position)
    }
  • ์œ„์™€๊ฐ™์ด ํ…์ŠคํŠธ๋ฅผ ๊ธฐ์–ต ํ›„ selectedTextRange๋ฅผ ํ†ตํ•ด ์ปค์„œ๋ฅผ ์ด๋™์‹œ์ผœ ํ•ด๊ฒฐํ–ˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ”ฅ prepareForReuse ์‚ฌ์šฉ ์‹œ Super ํ˜ธ์ถœ

ํŽผ์ณ๋ณด๊ธฐ
  • ์…€ ์žฌ์‚ฌ์šฉ์‹œ ์ดˆ๊ธฐํ™”๋ฅผ ์œ„ํ•ด prepareForReuse๋ฅผ ํ˜ธ์ถœํ–ˆ์Šต๋‹ˆ๋‹ค.
  • ํ•˜์ง€๋งŒ ์•„๋ž˜์˜ ์‚ฌ์ง„๊ณผ ๊ฐ™์ด super๋ฅผ ํ˜ธ์ถœํ•˜์ง€ ์•Š๊ณ  ์‚ฌ์šฉํ•˜๋‹ค๋ณด๋‹ˆ ์…€์˜ ๋ชจ์–‘์ด ๋ณ€ํ˜•๋˜๋Š” ํ˜„์ƒ์ด ๋ฐœ์ƒํ–ˆ์Šต๋‹ˆ๋‹ค.
super ํ˜ธ์ถœ super ๋ฏธํ˜ธ์ถœ
  • ๊ทธ๋ž˜์„œ override ํ•  ๋•Œ๋Š” super ํ˜ธ์ถœ์— ๋Œ€ํ•ด ํ•œ๋ฒˆ๋” ์ƒ๊ฐํ•ด์•ผ ํ•œ๋‹ค๋Š” ๊ตํ›ˆ์„ ์–ป์—ˆ์Šต๋‹ˆ๋‹ค....

๐Ÿ”ฅ Image load ์†๋„ ๊ฐœ์„ 

ํŽผ์ณ๋ณด๊ธฐ
  • Data(contentsOf: url)๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์ด๋ฏธ์ง€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ฐ€์ ธ์™”์—ˆ์Šต๋‹ˆ๋‹ค.
  • ํ•˜์ง€๋งŒ ๋งค์šฐ ๋Š๋ฆฌ๊ฒŒ ์•„์ด์ฝ˜์ด ์—…๋กœ๋“œ๊ฐ€ ๋˜์—ˆ๊ณ , Data(contentsOf: url) ๋ฉ”์„œ๋“œ๋ฅผ ์•Œ์•„๋ณธ ๊ฒฐ๊ณผ ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ ๋™๊ธฐ๋กœ ๋™์ž‘ํ•˜๊ธฐ ๋•Œ๋ฌธ์—, ๋™์ž‘์ด ๋งค์šฐ ๋Š๋ฆฌ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ๋˜์—ˆ์Šต๋‹ˆ๋‹ค.
  • ๋˜ํ•œ ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋Š” URLSession๊ณผ ๋‹ฌ๋ฆฌ ์ž‘์—…์— ๋Œ€ํ•œ ์ง„๋‹จ์„ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.
  • URLSession์—์„œ๋Š” ์˜ค๋ฅ˜๊ฐ€ ๋„คํŠธ์›Œํฌ ์˜ค๋ฅ˜์ธ์ง€, HTTP ์˜ค๋ฅ˜์ธ์ง€, contents ์˜ค๋ฅ˜ ์ธ์ง€ ๋“ฑ์„ ํŒํ•  ์ˆ˜ ์žˆ๋Š” ๋ฐ˜๋ฉด Data(contentsOf:)์—์„œ๋Š” ์ด๋ฅผ ํ™•์ธํ•  ์ˆ˜ ์—†์—ˆ์Šต๋‹ˆ๋‹ค.
  • ๋”ฐ๋ผ์„œ ์ด๋ฏธ์ง€๋“ค์„ dataTask๋ฅผ ํ™œ์šฉํ•˜๋Š” dataTask๋ฅผ ํ™œ์šฉํ•œ fetchData() ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜์—ฌ ์†๋„๋ฅผ ๊ฐœ์„ ํ•  ์ˆ˜ ์žˆ์—ˆ์Šต๋‹ˆ๋‹ค.

์ฐธ๊ณ  ๋งํฌ

[๊ณต์‹๋ฌธ์„œ]

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 3

  •  
  •  
  •