diff --git a/README.md b/README.md index e84da7c..9089b25 100644 --- a/README.md +++ b/README.md @@ -1,20 +1,18 @@ # PhotosApp - +๐Ÿ“ท PhotoLibrary์™€ Web์˜ ์ด๋ฏธ์ง€๋ฅผ Collection์œผ๋กœ ๋ณด์—ฌ์ฃผ๊ณ , Local ์ €์žฅ ๋“ฑ์˜ ๊ธฐ๋Šฅ์„ ์—ฐ์Šตํ•˜๋Š” ํ”„๋กœ์ ํŠธ ๐Ÿ“ฑ Developer : Lollo ๐Ÿ‘ฉ๐Ÿปโ€๐Ÿ’ป , ์žญ์Šจ ๐Ÿง‘๐Ÿปโ€๐Ÿ’ป -## Step 1 : Random Color CollectionView ์ œ์ž‘ - -#### 2021.03.22 +## Step 1 : Random Color CollectionView ์ œ์ž‘ (3/22) ### ๊ตฌํ˜„ ๋‚ด์šฉ ๐Ÿ“ฑ - ๋ฌด์ž‘์œ„ ์ƒ‰์ƒ์˜ ๋ฐฐ๊ฒฝ์„ ๊ฐ€์ง„ 40๊ฐœ์˜ cell์„ ์ƒ์„ฑํ•˜๊ณ  ์„ธ๋กœ ์Šคํฌ๋กค Collection์— ๋‚˜ํƒ€๋ƒˆ๋‹ค. - + @@ -53,16 +51,14 @@
-## Step 2 : CollectionView์— PhotoLibrary ํ•ญ๋ชฉ ํ‘œ์‹œ - -#### 2021.03.23 +## Step 2 : CollectionView์— PhotoLibrary ํ•ญ๋ชฉ ํ‘œ์‹œ (3/23) ### ๊ตฌํ˜„ ๋‚ด์šฉ ๐Ÿ“ฑ - PhotoLibrary์˜ ์ฝ˜ํ…์ธ  ๋ชฉ๋ก์„ ๋ถˆ๋Ÿฌ์™€์„œ ํ‘œ์‹œํ•˜๋„๋ก ๊ตฌํ˜„ - PhotoLibrary์— ๋ณ€ํ™”๊ฐ€ ์ƒ๊ธธ ์‹œ ์ˆ˜์ • ์‚ฌํ•ญ์„ ๋ฐ˜์˜ํ•˜์—ฌ ๋ชฉ๋ก์„ ์—…๋ฐ์ดํŠธํ•˜๋„๋ก ๊ตฌํ˜„ - +
@@ -101,14 +97,10 @@ 3. **`performBatchUpdates`๋ฅผ ํ†ตํ•œ `CollectionView` ์—…๋ฐ์ดํŠธ** - CollectionView๊ฐ€ ์ œ๊ณตํ•˜๋Š” **insert/delete/reload/move** ๊ธฐ๋Šฅ์„ ํ†ตํ•ด View๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์—…๋ฐ์ดํŠธํ•˜์˜€๋‹ค. + + ---- - -## Step 3-1 : JSONํŒŒ์ผ์—์„œ Image๋ฅผ ControllerView์— ๋ณด์—ฌ์ฃผ๊ธฐ - - - -#### 2021.03.24 +## Step 3-1 : JSON ํŒŒ์‹ฑ, Modal view ๋„์šฐ๊ธฐ (3/24) ### ๊ตฌํ˜„ ๋‚ด์šฉ ๐Ÿ“ฑ @@ -116,6 +108,8 @@ - Async๋ฐฉ์‹์„ ์ด์šฉํ•˜์—ฌ ์ •๋ณด๋ฅผ ๊ฐ€์ ธ์˜ฌ ๋•Œ๋งˆ๋‹ค View์—์„œ ํ•ด๋‹น ์ด๋ฏธ์ง€๋ฅผ ๋ณด์—ฌ์ค€๋‹ค. - ์ฝ”๋“œ๋ฅผ ์ด์šฉํ•˜์—ฌ + ๋ฒ„ํŠผ์„ ๋ˆŒ๋ €์„ ๋•Œ Modal๋กœ DoodleView๋ฅผ ๋ณด์—ฌ์ค€๋‹ค. + + ### Today's ํ•™์Šต๊ฑฐ๋ฆฌ ๐Ÿ“š @@ -246,24 +240,18 @@ - - - - -## Step 3-2 : ๋‹ค์šด๋ฐ›์€ Image๋ฅผ DoodlesView์—์„œ ๋ณด์—ฌ์ฃผ๊ธฐ - +## Step 3-2 : URL์˜ Image๋ฅผ Modal view์—์„œ ๋ณด์—ฌ์ฃผ๊ธฐ (3/25) +### ๊ตฌํ˜„ ๋‚ด์šฉ ๐Ÿ“ฑ -#### 2021.03.25 +- DoodleViews๋ฅผ StoryBoard ์ด์šฉ ์—†์ด Code๋กœ ๊ตฌํ˜„. +- ์„œ๋กœ ๋‹ค๋ฅธ DispatchQueue๋ฅผ ์ด์šฉํ•˜์—ฌ ๋‹ค์šด๋ฐ›๋Š” ํ์™€ ๋ณด์—ฌ์ฃผ๋Š” ํ๋ฅผ Asyncํ•˜๊ฒŒ ์ž‘์—… -- ### ๊ตฌํ˜„ ๋‚ด์šฉ ๐Ÿ“ฑ + - - DoodleViews๋ฅผ StoryBoard ์ด์šฉ ์—†์ด Code๋กœ ๊ตฌํ˜„. - - ์„œ๋กœ ๋‹ค๋ฅธ DispatchQueue๋ฅผ ์ด์šฉํ•˜์—ฌ ๋‹ค์šด๋ฐ›๋Š” ํ์™€ ๋ณด์—ฌ์ฃผ๋Š” ํ๋ฅผ Asyncํ•˜๊ฒŒ ์ž‘์—… - - ### Today's ํ•™์Šต๊ฑฐ๋ฆฌ ๐Ÿ“š +### Today's ํ•™์Šต๊ฑฐ๋ฆฌ ๐Ÿ“š 1. DoodleViews๋ฅผ StoryBoard ์ด์šฉ ์—†์ด DoodleViewsController์—์„œ Code๋กœ ๊ตฌํ˜„ @@ -286,64 +274,44 @@ -2. `URL`์„ ํ†ตํ•œ Images๋ฅผ ์ €์žฅํ•˜๊ณ  ์ €์žฅ๋œ Images๋ฅผ View์— ๋ณด์—ฌ์ฃผ๋Š” ์ž‘์—…์„ Asyncํ•˜๊ฒŒ ๊ตฌํ˜„ - - - `ImageManager`๋ฅผ ํ†ตํ•ด ์ „๋‚  ์ž‘์—…ํ•œ JSONํŒŒ์ผ์„ ํ†ตํ•ด ์ž‘์—…ํ•˜๋Š” ImageDownload ๊ทธ๋ฆฌ๊ณ , DownLoadํ•œ ์ด๋ฏธ์ง€๋ฅผ ์ฝœ๋ ‰์…˜ ๋ทฐ์— ๋ณด์—ฌ์ฃผ๋Š” ์ž‘์—…์„ ๊ณต๋ถ€ํ•˜์˜€๋‹ค. - - - ๊ฐ๊ฐ์˜ ์ฃผ์†Œ์— ํ•ด๋‹นํ•˜๋Š” ์ด๋ฏธ์ง€๋ฅผ ๋‹ค์šด๋ฐ›๋Š” ํ•จ์ˆ˜ +2. ์•ž์„œ JSON์—์„œ ํŒŒ์‹ฑํ•œ `URL`์—์„œ ์›น ์ด๋ฏธ์ง€๋ฅผ ๋ถˆ๋Ÿฌ์˜ฌ ๋•Œ, ๋‹ค์ค‘ Queue ๋ฐ async ๋ฐฉ์‹์„ ํ™œ์šฉ (***2021.03.28 ์ˆ˜์ •**) - - ```swift - private func startDownloading() { - imageURLs.forEach { (url) in - backGroundDownloadingQueue.async { - self.downloader.downloadImage(imageURL: url, completionHandler: { (_) in }, - placeholderImage: UIImage()) - } - } - } - ``` - - - ๋‹ค์šด๋ฐ›์€ ์ด๋ฏธ์ง€๋ฅผ ํ•ด๋‹น Cell์— ์ „์†กํ•˜๋Š” ๋ฐฉ๋ฒ•์œผ๋กœ `Notification`์„ ํ™œ์šฉํ•˜์—ฌ ์ฆ‰๊ฐ์ ์œผ๋กœ ๋ณด๋‚ด๊ฒŒ ํ•˜์˜€๋‹ค. - - - ```swift - NotificationCenter.default.addObserver(self, - selector: #selector(didImageDownloadDone(_:)), - name: ImageManager.NotiKeys.imageDownloadDone, - object: imgManager) - ``` - - - `DispatchQueue`์— ๋Œ€ํ•œ `Asyn`์— ๊ณ ์ฐฐ + - - ์ผ๋ฐ˜์ ์œผ๋กœ๋Š” ๊ฐ๊ฐ์˜ ์ฃผ์†Œ์— ํ•ด๋‹นํ•˜๋Š” ์ด๋ฏธ์ง€๋ฅผ ๋‹ค์šด๋ฐ›๋„๋ก ํ•œ๋‹ค. ํ•˜์ง€๋งŒ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์ƒํ™ฉ์— ๋Œ€๋น„๋ฅผ ํ•ด์•ผํ•œ๋‹ค. +- 2๊ฐ€์ง€ ๊ฒฝ๋กœ๋กœ ์ด๋ฏธ์ง€๋ฅผ ๋‹ค์šด๋กœ๋“œํ•˜๋„๋ก ๊ตฌํ˜„ํ•˜์˜€๋‹ค. - - ๋ชจ๋“  ๋ฐ์ดํ„ฐ๊ฐ€ ๋‹ค์šด๋ฐ›๊ธฐ ์ „๊นŒ์ง€ ์ด๋ฏธ์ง€ ๋ทฐ๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š๋Š”๋‹ค. - - ์ด๋ฏธ์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๊ฒƒ์ด ์ˆœ์ฐจ์ ์ด๋ผ ์Šคํฌ๋กค ๋ทฐ๋ฅผ ๋‚ด๋ ธ์„ ๋•Œ ๋‚˜์˜ค๋Š” ์…€์— ๋Œ€ํ•œ ์ด๋ฏธ์ง€๊ฐ€ ์•„์ง ๋ณด์—ฌ์ง€์ง€ ์•Š๋Š”๋‹ค. + 1. **cell ์ƒ์„ฑ ์‹œ์ ์— ๋‹ค์šด๋กœ๋“œ** + - `DataSource delegate`์˜ ๋ฉ”์†Œ๋“œ `collectionView(cellForItemAt indexPath:)`๋ฅผ ํ†ตํ•ด ์Šคํฌ๋กค ์œ„์น˜์˜ cell๋“ค์ด ์ƒ์„ฑ๋  ๋•Œ, ์•„์ง ํ•ด๋‹น cell์˜ ์ด๋ฏธ์ง€๊ฐ€ ๋‹ค์šด๋กœ๋“œ๋œ ์ด๋ ฅ์ด ์—†๋‹ค๋ฉด download task๋ฅผ ์ƒ์„ฑํ•˜๊ณ , concurrent queue์— ์ถ”๊ฐ€ํ•˜๋„๋ก ํ–ˆ๋‹ค. + - asyncํ•˜๊ฒŒ ๋‹ค์šด๋กœ๋“œ ํ›„, ์™„๋ฃŒ๋˜๋ฉด Notification์„ ๋ณด๋‚ด๋„๋ก ํ–ˆ๋‹ค. Noti๋ฅผ ํ†ตํ•ด reload ์‹œ์ ์„ ์•Œ๋ ค์ฃผ์–ด ๋‹ค์‹œ ์Šคํฌ๋กค์„ ํ•˜์ง€ ์•Š๋”๋ผ๋„ ์›ํ™œํ•œ ๋กœ๋“œ๊ฐ€ ๊ฐ€๋Šฅํ•˜๋„๋ก ํ–ˆ๋‹ค. + - VC์—์„œ Noti๋ฅผ ๋ฐ›์œผ๋ฉด, `OperationQueue.main`์— cell์„ reloadํ•˜๋Š” task๋ฅผ ์ถ”๊ฐ€ํ•˜๋„๋ก ํ–ˆ๋‹ค. ์ด๋•Œ concurrent queue๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด view ํ‘œ์‹œ ์‹œ ๋ฐ€๋ฆผ ํ˜„์ƒ์ด ์ผ์–ด๋‚˜๋ฏ€๋กœ serial queue๋ฅผ ์‚ฌ์šฉํ–ˆ๋‹ค. + 2. **background์—์„œ ๋‹ค์šด๋กœ๋“œ** + - `DoodleViewController`์˜ viewDidLoad ์‹œ์ ์— ImageManager์˜ ๋ฉ”์†Œ๋“œ `startDownloadingAtBackground()`๋ฅผ ํ†ตํ•ด ๋ชจ๋“  URL์˜ ์ด๋ฏธ์ง€ ๋‹ค์šด๋กœ๋“œ task๋ฅผ concurrent queue์— ์ถ”๊ฐ€ํ•˜๋„๋ก ํ–ˆ๋‹ค. + - cell ์ƒ์„ฑ ์‹œ์—๋งŒ ๋‹ค์šด๋กœ๋“œ๋ฅผ ์ง„ํ–‰ํ•˜๋ฉด ์Šคํฌ๋กค ์‹œ ์ด๋ฏธ์ง€์˜ ์›ํ™œํ•œ ์ˆ˜๊ธ‰์— ์ œ์•ฝ์ด ์ƒ๊ธฐ๋ฏ€๋กœ, ์•„์ง ๋„๋‹ฌํ•˜์ง€ ์•Š์€ indexpath์— ๋Œ€ํ•ด์„œ๋„ ๋ฏธ๋ฆฌ ๋‹ค์šด๋กœ๋“œ๋ฅผ ์ง„ํ–‰ํ•˜๊ณ  ์บ์‹ฑํ•˜์—ฌ ์ €์žฅํ•ด๋‘๋„๋ก ํ–ˆ๋‹ค. - - ๋”ฐ๋ผ์„œ ๋ชจ๋“  ๋ทฐ๋ฅผ ์ˆœ์ฐจ์ ์œผ๋กœ ์ด๋ฏธ์ง€๋ฅผ ๋ฐ›๊ฒŒํ•˜๊ณ , `dequeueReusableCell` ์— ํ•ด๋‹นํ•˜๋Š” ์ƒˆ๋กœ์šด Cell์ด ๋ณด์—ฌ์ฃผ์—ˆ์„ ๋•Œ๋ฅผ ๋Œ€๋น„ํ•˜์—ฌ ์ฆ‰๊ฐ์ ์ธ ์ด๋ฏธ์ง€๋ฅผ ๋ณด์—ฌ์ฃผ๋Š” ๊ฐ๊ฐ์˜ ์“ฐ๋ ˆ๋“œ๋ฅผ ์ƒ์„ฑํ•˜์—ฌ Asynํ•˜๊ฒŒ ์ž‘์—…ํ•˜๋„๋ก ํ•˜์˜€๋‹ค. +- dictionary๋ฅผ ํ™œ์šฉํ•˜์—ฌ ์ด๋ฏธ์ง€๋ฅผ ์บ์‹ฑํ•˜๊ณ , ์ง„ํ–‰ํ•œ task ์ •๋ณด๋ฅผ ์ €์žฅํ•˜๋„๋ก ํ–ˆ๋‹ค. - - ```swift - imageDownloadQueue = DispatchQueue.init(label: "imageDownload") - backGroundDownloadingQueue = DispatchQueue.init(label: "backgroundImageDownload") - ``` + ```swift + class ImageDownloader { + private var cachedImages: [URL: UIImage] + private var imagesDownloadTasks: [URL: URLSessionDataTask] + ... + } + ``` - + - ์ด๋ฅผ ํ†ตํ•ด memory leaking์„ ๋ฐฉ์ง€ํ•˜๊ณ , error๊ฐ€ ์žˆ๋Š” task๊ฐ€ ๋ฌดํ•œํžˆ ์ง„ํ–‰๋˜์ง€ ์•Š๋„๋ก ๋ง‰์„ ์ˆ˜ ์žˆ์—ˆ๋‹ค. + - ๊ทธ๋Ÿฌ๋‚˜ dictionary.subscript.getter / setter ๋ฒ„๊ทธ๊ฐ€ ์ข…์ข… ๋ฐœ์ƒํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์—ˆ๋‹ค. ([Issue: dictionary.subscript.getter ๋ฌธ์ œ](https://github.com/codesquad-members-2021/swift-photos-06/issues/13)) + - dictionary๋Š” thread-freeํ•˜์ง€ ์•Š์•„์„œ, ๋™์‹œ ์ ‘๊ทผ ์‹œ ๋ฌธ์ œ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ์„ ์•Œ๊ฒŒ ๋˜์—ˆ๋‹ค. set ์‹œ์— `barrier`๋ฅผ ๊ฑธ๊ณ , get ์‹œ์—” syncํ•˜๊ฒŒ ์ฒ˜๋ฆฌํ•˜๋Š” ๊ฒƒ์œผ๋กœ issue๋ฅผ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค. - - - ## Step 3-3 : Image๋ฅผ ์ €์žฅํ•˜๊ธฐ - - +## Step 3-3 : Image๋ฅผ PhotoLibrary์— ์ €์žฅํ•˜๊ธฐ (3/26) -#### 2021.03.26 - - - ### ๊ตฌํ˜„ ๋‚ด์šฉ ๐Ÿ“ฑ +### ๊ตฌํ˜„ ๋‚ด์šฉ ๐Ÿ“ฑ - - Image๋ฅผ ๊ธธ๊ฒŒ ๋ˆŒ๋Ÿฌ์„œ ์ €์žฅํ•˜๊ธฐ. - - ์ €์žฅ ์‹œ ์•Œ๋ฆผ๋ฉ”์‹œ์ง€ ๋‚˜์˜ค๊ธฐ ๋ฐ ์•จ๋ฒ” ๊ฐฑ์‹ . +- Image๋ฅผ ๊ธธ๊ฒŒ ๋ˆŒ๋Ÿฌ์„œ ์ €์žฅํ•˜๊ธฐ. +- ์ €์žฅ ์‹œ ์•Œ๋ฆผ๋ฉ”์‹œ์ง€ ๋‚˜์˜ค๊ธฐ ๋ฐ ์•จ๋ฒ” ๊ฐฑ์‹ . - + ### Today's ํ•™์Šต๊ฑฐ๋ฆฌ ๐Ÿ“š @@ -363,8 +331,9 @@ 2. `Save` Btn์„ ์ด์šฉํ•˜์—ฌ ์ €์žฅํ•  ์‹œ, ์ €์žฅ์ด ๋˜์—ˆ๋Š”์ง€๋ฅผ ์•Œ๋ ค์ฃผ๋Š” ๊ธฐ๋Šฅ์ด ํ•„์š”ํ•˜๋‹ค๊ณ  ์˜๋…ผํ•˜์˜€๋‹ค. - ์ด์œ  : DoodlesView์—์™€ LocalAlbumView๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅด๊ธฐ์— ์‹ค์ œ๋กœ ์ €์žฅ๋˜์—ˆ๋Š”์ง€๋Š” View์ „ํ™˜์„ ํ†ตํ•ด์„œ๋งŒ ํ™•์ธ์ด ๊ฐ€๋Šฅ - - **์‚ฌ์šฉ์„ฑ ํŽธ์˜ ์ฆ์ง„!!** - + + - **์‚ฌ์šฉ์„ฑ ํŽธ์˜ ์ฆ์ง„!!** + - `UIAlertController` ์„ ์ด์šฉํ•˜์—ฌ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ €์žฅ ์™„๋ฃŒ ๋ผ์—ˆ์Œ์„ ์•Œ๋ ค์คŒ - ```swift @@ -389,4 +358,3 @@ } ``` -