private lazy var flowLayout: UICollectionViewFlowLayout = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.minimumLineSpacing = 5
layout.itemSize = .init(width: UIScreen.main.bounds.width * 0.3, height: UIScreen.main.bounds.height * 0.1)
return layout
}()
private lazy var collectionView: UICollectionView = {
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: flowLayout)
collectionView.backgroundColor = .clear
collectionView.contentInsetAdjustmentBehavior = .never // 이거 해줘야 됨
collectionView.showsHorizontalScrollIndicator = false
collectionView.delegate = self
collectionView.dataSource = self
collectionView.register(TrackViewCell.self, forCellWithReuseIdentifier: TrackViewCell.identifier)
return collectionView
}()
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
let inset = (view.frame.width / 2)
collectionView.contentInset = UIEdgeInsets(top: 0, left: inset, bottom: 0, right: inset)
}
개발하다 보면 종종 보이는 이 메서드.
무슨 메서드인지 갑자기 너무 궁금해져서 검색을 해봤다. 알아야 할 것 들이 엄청 많았다.
차근차근 정리를 해보겠다.
When the bounds change for a view controller's view, the view adjusts the positions of its subviews and then the system calls this method. However, this method being called does not indicate that the individual layouts of the view's subviews have been adjusted. Each subview is responsible for adjusting its own layout.
Your view controller can override this method to make changes after the view lays out its subviews. The default implementation of this method does nothing.
뷰 컨트롤러의 뷰에 대한 경계가 변경되면 뷰는 하위 뷰의 위치를 조정한 다음 시스템에서 이 메서드를 호출합니다. 그러나 이 메서드가 호출되었다고 해서 뷰의 하위 뷰의 개별 레이아웃이 조정되었다는 것을 나타내는 것은 아닙니다. 각 하위 뷰는 자체 레이아웃을 조정해야 합니다.
뷰 컨트롤러는 이 메서드를 재정의하여 뷰가 하위 뷰를 레이아웃한 후에 변경할 수 있습니다. 이 메서드의 기본 구현은 아무 작업도 수행하지 않습니다.
자, 하나도 모르겠죠?
여러 블로그 글을 읽으며 대충 이해했지만 사람들은 이런 것들을 어디서 찾아내는 건지 궁금해서 공식 문서를 뒤져봤다.
그 중 도움이 되었던 글은 이것.
Displaying and managing views with a view controller - Prepare your views to appear onscreen

화면에 뷰 컨트롤러를 표시할 때 UIKit은 먼저 해당 뷰를 로드하고 구성해야 하며, 이는 다음 단계 시퀀스를 사용하여 수행합니다.

로드 타임에는 뷰 컨트롤러를 사용할 수 있도록 준비하는 데 필요한 일회성 구성 단계만 수행합니다. 로드 타임을 사용하여 스토리보드에 포함되지 않은 추가 뷰를 만들고 구성합니다. 뷰 컨트롤러가 화면에 나타날 때마다 수행해야 하는 작업을 수행하지 마세요. 예를 들어 애니메이션을 시작하거나 뷰의 값을 업데이트하지 마세요.
뷰가 처음 화면에 나타날 때 뷰와 관련된 최종 작업을 수행합니다. UIKit은 뷰가 화면에 나타날 때 소유 뷰 컨트롤러에 알리고, 다음과 같은 방식으로 현재 환경에 맞게 해당 뷰의 레이아웃을 업데이트합니다.

뷰 컨트롤러의 viewIsAppearing(_:) 메서드에서 뷰의 콘텐츠를 업데이트합니다. 시스템이 이 메서드를 호출하면 뷰가 뷰 계층에 추가되고 프레임, 경계, 여백 및 인셋이 정의됩니다. 시스템이 viewIsAppearing(:)에 추가하는 콘텐츠는 뷰가 처음 화면에 표시될 때 표시됩니다.
시스템은 뷰가 레이아웃을 수행할 때마다 viewWillLayoutSubviews() 및 viewDidLayoutSubviews() 메서드를 호출합니다. 이는 뷰가 표시되는 동안 언제든지 발생할 수 있습니다. 시스템은 각 모양 전환의 일부로 viewIsAppearing(_:)을 한 번만 호출하므로 이 메서드에서 변경한 내용은 뷰가 레이아웃을 수행할 때마다 반복되지 않습니다.
이제 언제 불리는 메서드인지는 이해를 했다. 그래서 어떻게 쓰이는지 알아봤는데 다른 블로그들에 예제가 잘 정리되어 있었다.
예제는 다른 블로그를 참고하면 좋을 것 같고, 정리를 해보자면
나는 위의 코드 예시와 같이 컬렉션뷰의 레이아웃이 모두 정해진 후 컬렉션뷰 셀의 위치를 조정하는 데에 사용했다.
https://blog.naver.com/doctor-kick/222437253619
https://ios-daniel-yang.tistory.com/entry/SwiftTIL-17-viewDidLayoutSubviews-간단-정리