-
Notifications
You must be signed in to change notification settings - Fork 2
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
base: develop
Are you sure you want to change the base?
[Step2] 사진 앨범 접근 #6
Conversation
self.imageView.frame = self.bounds | ||
self.imageView.contentMode = .scaleAspectFill | ||
self.imageView.autoresizingMask = [ | ||
.flexibleWidth, | ||
.flexibleHeight, | ||
.flexibleTopMargin, | ||
.flexibleLeftMargin, | ||
.flexibleRightMargin, | ||
.flexibleBottomMargin | ||
] |
There was a problem hiding this comment.
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 도 더 잘 이해할 수있을 것 같습니다. 감사합니다 :)
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)) | ||
} | ||
}) | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
애플 공식 문서에 있는 예제 코드를 참고했습니다.
위의 코드에 사용된 API 와 indexSet 등의 타입은 추가로 학습하겠습니다 :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
네 바뀐 부분만 처리하는 정석 같은 예제 코드입니다. 잘하셨어요
let options = PHImageRequestOptions() | ||
options.deliveryMode = .highQualityFormat |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Photos 앱처럼 썸네일을 선명하게 하고 싶어 해당 옵션을 추가했습니다만 그만큼은 안되는 것 같습니다.
Photos 프래임워크로는 선명도를 높이는데 한계가 있는 걸까요? AVFoundation 을 활용해보아야 할까요?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
썸네일의 역할이 뭘까요? 선명하게 한다는 것은 퀄리티도 있지만, 크기 자체도 영향을 많이 줍니다.
사진 앱처럼 동일한 수준으로 하려면 Photos로도 충분히 할 수 있을텐데 엄청 느릴 수도 있습니다.
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>? | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
ViewController 이름도 그냥 ViewController보다 좀 더 구체적인 이름으로 정해보세요
그러면서 Photos 프레임워크에 의존하지 않도록, 화면과 데이터를 저장하는 모듈 사이의 중계 역할만 해보세요
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
viewWillLayoutSubviews() 메소드는 언제 호출이 될까요? 한 번만 되는걸까요? 혹시 여러번 호출되는 걸까요?
그거에 따라서 여기있는 코드가 영향을 줄수도 있으니 확인해보세요
There was a problem hiding this comment.
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 |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
이 동작이 비동기로 동작하기 때문에 cell을 반복해서 그리는데 나쁜 영향을 줄수도 있습니다.
collectionView(_, cellForItemAt:) 메소드는 스크롤하고 셀을 그릴때마다 호출이 되서, 이미 스크롤되고 나서 다른 이미지가 그려질 수도 있습니다.
작업 내용
힉습 키워드
& PHChange
결과물
느낀점