Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Step2] 사진 앨범 접근 #6

Open
wants to merge 12 commits into
base: develop
Choose a base branch
from

Conversation

SongTaehwan
Copy link
Collaborator

@SongTaehwan SongTaehwan commented Mar 29, 2022

작업 내용

  • Photos 라이브러리 접근 권한 얻기
  • Custom CollectionView Cell 구현
  • 라이브버리의 이미지를 CollectionVIew 에 표시
  • 옵저버를 추가해 라이브러리에 변경사항이 생기면 앱에 반영

힉습 키워드

  • PhotoKit vs. AVFoundation
  • PHPhotoLibrary
  • PHImageManager vs. PHCachingImageManger
  • PHAsset & PHFetchResult & PHFetchOptions
  • PHPhotoLibraryChangeObserver 프로토콜
    & PHChange

결과물

느낀점

  • 드로잉 앱에서 배운 MVC 패턴을 이번 과제에도 적용해보고 싶어 Model 을 만들었는데 PHPhotoLibraryChangeObserver 프로토콜을 사용하는 과정에서 복잡도만 높이는 것 같아 삭제했습니다.
  • fetch 받아온 이미지를 Model 에 저장해 활용하고 싶은데 Model 이 Photos 프래임워크를 모르게 하려니 고민이 됩니다.

@SongTaehwan SongTaehwan self-assigned this Mar 29, 2022
@SongTaehwan SongTaehwan requested a review from godrm March 29, 2022 05:20
@SongTaehwan SongTaehwan linked an issue Mar 29, 2022 that may be closed by this pull request
5 tasks
@SongTaehwan SongTaehwan removed a link to an issue Mar 29, 2022
5 tasks
@SongTaehwan SongTaehwan linked an issue Mar 29, 2022 that may be closed by this pull request
3 tasks
Comment on lines +31 to +40
self.imageView.frame = self.bounds
self.imageView.contentMode = .scaleAspectFill
self.imageView.autoresizingMask = [
.flexibleWidth,
.flexibleHeight,
.flexibleTopMargin,
.flexibleLeftMargin,
.flexibleRightMargin,
.flexibleBottomMargin
]
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

AutoLayout 없이 AutoResizingMask 를 적용해 기기 크기에 따라 이미지 크기를 다이나믹하게 설정되도록 적용해보았습니다.
JK 말씀대로 frame 과 AutoResizingMask 를 사용해 레이아웃을 만드는데 익숙해지니 AutoLayout 도 더 잘 이해할 수있을 것 같습니다. 감사합니다 :)

Comment on lines +133 to +164
func photoLibraryDidChange(_ changeInstance: PHChange) {
guard let fetchResult = self.fetchResult else { return }

DispatchQueue.main.sync {
guard let changes = changeInstance.changeDetails(for: fetchResult) else { return }
self.fetchResult = changes.fetchResultAfterChanges

guard changes.hasIncrementalChanges == true else {
self.collectionView.reloadData()
return
}

self.collectionView.performBatchUpdates({
if let removed = changes.removedIndexes, removed.count > 0 {
self.collectionView.deleteItems(at: removed.map { IndexPath(item: $0, section: 0) })
}

if let inserted = changes.insertedIndexes, inserted.count > 0 {
self.collectionView.insertItems(at: inserted.map { IndexPath(item: $0, section: 0) })
}

if let changed = changes.changedIndexes, changed.count > 0 {
self.collectionView.reloadItems(at: changed.map { IndexPath(item: $0, section: 0) })
}

changes.enumerateMoves { fromIndex, toIndex in
self.collectionView.moveItem(at: IndexPath(item: fromIndex, section: 0),
to: IndexPath(item: toIndex, section: 0))
}
})
}
}
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

애플 공식 문서에 있는 예제 코드를 참고했습니다.
위의 코드에 사용된 API 와 indexSet 등의 타입은 추가로 학습하겠습니다 :)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

네 바뀐 부분만 처리하는 정석 같은 예제 코드입니다. 잘하셨어요

Comment on lines +119 to +120
let options = PHImageRequestOptions()
options.deliveryMode = .highQualityFormat
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Photos 앱처럼 썸네일을 선명하게 하고 싶어 해당 옵션을 추가했습니다만 그만큼은 안되는 것 같습니다.
Photos 프래임워크로는 선명도를 높이는데 한계가 있는 걸까요? AVFoundation 을 활용해보아야 할까요?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

썸네일의 역할이 뭘까요? 선명하게 한다는 것은 퀄리티도 있지만, 크기 자체도 영향을 많이 줍니다.
사진 앱처럼 동일한 수준으로 하려면 Photos로도 충분히 할 수 있을텐데 엄청 느릴 수도 있습니다.

@SongTaehwan SongTaehwan marked this pull request as ready for review March 29, 2022 06:25
Comment on lines +9 to +16
import Photos

class ViewController: UIViewController {
private let reusableCellName = "photoItem"
private let cellCount = 40
private let album = Album()

@IBOutlet weak var collectionView: UICollectionView!

private let imageManager = PHCachingImageManager.default()
private var fetchResult: PHFetchResult<PHAsset>?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ViewController 이름도 그냥 ViewController보다 좀 더 구체적인 이름으로 정해보세요
그러면서 Photos 프레임워크에 의존하지 않도록, 화면과 데이터를 저장하는 모듈 사이의 중계 역할만 해보세요

Comment on lines +34 to +43
let width = view.bounds.inset(by: view.safeAreaInsets).width
let columnCount = (width / 100).rounded(.towardZero)
let spacing: CGFloat = 1.2

guard let layout = self.collectionView.collectionViewLayout as? UICollectionViewFlowLayout else { return }
let cellWidth = (width / columnCount) - spacing

layout.itemSize = CGSize(width: cellWidth, height: cellWidth)
layout.minimumInteritemSpacing = spacing
layout.minimumLineSpacing = spacing
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

viewWillLayoutSubviews() 메소드는 언제 호출이 될까요? 한 번만 되는걸까요? 혹시 여러번 호출되는 걸까요?
그거에 따라서 여기있는 코드가 영향을 줄수도 있으니 확인해보세요

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ViewController 가 가진 View 의 bounds 가 바뀔 때 마다(화면 회전, 백그라운드 상태) 실행되는 것을 확인했습니다.
위의 코드가 레이아웃을 조정하는 코드라는 점에서 viewWillLayoutSubviews() 메소드에서 사용해도 괜찮다고 생각합니다. 그러나 UICollectionViewDelegate 의 메소드 중 셀의 크기를 결정하는 메소드가 있는대도 viewWillLayoutSubviews() 를 통해 레이아웃을 조정하는 것은 workaround 라는 생각이 들어 delegate 를 사용해보겠습니다 :)

options.deliveryMode = .highQualityFormat
options.resizeMode = .fast

imageManager.requestImage(for: asset, targetSize: cell.frame.size, contentMode: .aspectFill, options: options) { image, data in
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

이 동작이 비동기로 동작하기 때문에 cell을 반복해서 그리는데 나쁜 영향을 줄수도 있습니다.
collectionView(_, cellForItemAt:) 메소드는 스크롤하고 셀을 그릴때마다 호출이 되서, 이미 스크롤되고 나서 다른 이미지가 그려질 수도 있습니다.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Step2
2 participants