[Swift] 이 시기부터 iOS 10의 새로운 기능인 UItableView UICollectionView의 개선과 Proe-Fetching API를 재검토하겠습니다.

17906 단어 Swiftios10
이전 iOS 버전은 WWDC 이전에 수정되었습니다.

왜 iOS 10입니까?


아이폰 출하 시 초기 버전은 최신 두 개 이전에 설정이에 따라 2개 전 버전부터 지원한다는 방침이다.
(회사 내부 사정으로 인해 터미널 버전을 올리지 못하는 회사도 있다)
이에 따라 이번 iOS 12 업그레이드로 iOS 10에서 사용할 수 있는 기능을 사용할 수 있게 됨에 따라 재조사한 내용을 주기적으로 기록하기로 했다.
이번에는 UItableView, UICollectionView의 기능입니다.
iOS 9은 UITObleView 및 UICollectionView를 고속으로 스크롤할 때 화면이 깜박입니다.
이것은 칸이 표시되기 전에 집중을 처리하기 때문에 칸을 다시 만드는 데 시간이 필요하다
틀이 빠져서요.
iOS 10에서 이걸 개선하기 위해서.
셀의 라이프 사이클 이벤트가 향상되고 새로운 API가 제공됩니다.

셀 라이프 사이클 이벤트 개선


두 가지 큰 변경이 있습니다.
・prepareForeuse와cellForItemAtIndexPath가 호칭될 시기가 빨라졌다
DidEnd DisplayngCell이라는 시간이 늦어졌어요.

셀 라이프 사이클에 대한 방법


주로 네 가지 방법이 관련된다.

prepareForReuse


숨겨진 칸을 다시 사용할 때
주로 칸을 초기화합니다.

cellForItemAtIndexPath


거의 모든 처리는 칸을 표시하는 데 사용됩니다. 예를 들어 칸을 생성하거나 설정하는 데 사용됩니다.

willDisplayCell


화면에 셀을 표시하기 전에 표시합니다.

didEndDisplayingCell


셀이 더 이상 표시되지 않을 때 호출됩니다.

iOS 9까지의 문제


단원격 화면이 표시되기 전에 이미 상술한 방법을 호출했기 때문이다
단원격 생성에 시간이 걸리면 처리가 늦어집니다
나오기 전에 화면이 잠시 굳어 보였다.
반대로 화면에서 숨기면 칸이 바로 폐기됩니다
스크롤 방향 변경 및 빠른 스크롤
마찬가지로 단원격을 다시 생성해야 하기 때문에 화면이 굳은 것처럼 보인다.

prepareForeuse와cellFortItemAtIndexPath가 호출될 시기가 빨라졌습니다


우선prepareForeuse와cellFortItemAtIndexPath의 시간은 화면을 표시하기 얼마 전부터 시작되었고 화면을 표시하기 전에 칸의 생성이 완료되었습니다.

didEnd DisplayngCell 호출이 늦어졌습니다.


이렇게 되면 굴러가는 방향이 갑자기 바뀌어도
셀이 남아있어서 그냥 화면에 나왔어요.

메모리 사용량 증가


성능은 개선됐지만 단순히 유지하는 셀의 수가 늘어나 메모리 사용량이 늘었다.

Pre-Fetching API


https://developer.apple.com/documentation/uikit/uicollectionviewdatasourceprefetching/prefetching_collection_view_data
상술한 개선 사항 외에 더욱 원활한 굴림을 실현할 수 있다
Pre-Fetching API를 가져왔습니다.
이것은 작은 구역을 생성하는cellForItemAtIndexPath보다 일찍 호출되었습니다
API 또는 DB에서 데이터를 가져오거나 이미지 등을 읽습니다.
사전에 매우 무거운 처리를 할 수 있다.
이렇게 하면 윌디스플레이의 부담을 분할할 수 있다.
또한 이러한 작업은 주 경로 외부에서 수행되므로 UI에 영향을 주지 않습니다.
또한 롤링 방향이 변경될 때 사용하는 API도 있습니다.
읽을 필요가 없는 칸에 대한 데이터 가져오는 것을 취소할 수도 있습니다.

UICollectionView 관찰 동작 설치


다음은 그림을 간단하게 표시하는 프로그램입니다.

여러 가지 상황에서 비교하다.

iOS 10 Pre-Fetching API가 없는 경우



iOS 10 Pre-Fetching API가 있는 경우



조금 작지만 Prefetch가 있는 경우 이미지가 더 빨리 표시됩니다.
실장 내용을 간단히 표현하다.
모델
struct FavoritePhoto {
    let id: Int
    let name: String
}
다음 Operation에서 비동기적으로 이미지를 로드합니다.
읽기 시간을 적당히 보내고 있습니다.
final class DataLoadOperation: Operation {

    var favoritePhoto: FavoritePhoto?
    var completionHandler: ((FavoritePhoto) -> ())?

    private let _favoritePhoto: FavoritePhoto

    init(_ favoritePhoto: FavoritePhoto) {
        _favoritePhoto = favoritePhoto
    }

    override func main() {
        if isCancelled  { return }

        let delay = arc4random_uniform(2000) + 500
        usleep(delay * 1000)

        if isCancelled { return }
        self.favoritePhoto = _favoritePhoto

        if let completionHandler = completionHandler {
            DispatchQueue.main.async {
                completionHandler(self._favoritePhoto)
            }
        }
    }
}
ViewController 처리 스플라인 방법을 설정합니다.
collectionView.prefetchDataSource = self
경계 문자의 설치
extension ViewController: UICollectionViewDataSourcePrefetching {

    func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) {
        for indexPath in indexPaths {
            // すでに実行中の場合は何もしない
            if let _ = loadingOperations[indexPath] {
                return
            }

            // Operationを作成し、画像の読み込みを開始する
            if let loader = dataStore.loadFavoritePhoto(at: indexPath.item) {
                loadingQueue.addOperation(loader)
                loadingOperations[indexPath] = loader
            }
        }
    }

    // スクロールの方向が変わった場合に呼び出される
    func collectionView(_ collectionView: UICollectionView, cancelPrefetchingForItemsAt indexPaths: [IndexPath]) {
        for indexPath in indexPaths {

            // もうデータが必要ないためOpeationのキャンセルと削除をする
            if let loader = loadingOperations[indexPath] {
                loader.cancel()
                loadingOperations.removeValue(forKey: indexPath)
            }
        }
    }
}
윌디스플레이와 디드엔드디스플레이의 실현이다.

extension ViewController: UICollectionViewDelegate {

    // collectionViewにcellが表示される直前に呼ばれる
    func collectionView(_ collectionView: UICollectionView, willDisplay cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {
        guard let cell = cell as? CollectionViewCell else {
            return
        }

        let update: (FavoritePhoto?) -> () = { [unowned self] photo in
            cell.show(photo)
            // セルの設定が完了したのでOperationを削除
            self.loadingOperations.removeValue(forKey: indexPath)
        }

        // すでにOpeationがあるか(データをロード中か)?
        if let loader = loadingOperations[indexPath] {

            // データのロードが完了しているか?
            if let photo = loader.favoritePhoto {
                cell.show(photo)
                // セルの設定が完了したのでOperationを削除
                self.loadingOperations.removeValue(forKey: indexPath)
            } else {

                // 画像のロードが未完了の場合、完了後のハンドラーを設定
                loader.completionHandler = update
            }
        } else {

            // Operationを作成する
            if let loader = dataStore.loadFavoritePhoto(at: indexPath.item) {
                loader.completionHandler = update
                loadingQueue.addOperation(loader)
                loadingOperations[indexPath] = loader
            }

        }
    }


    // collectionViewからcellが表示範囲外になった時に呼ばれる
    func collectionView(_ collectionView: UICollectionView, didEndDisplaying cell: UICollectionViewCell, forItemAt indexPath: IndexPath) {

        // Operationが存在する場合はキャンセルして削除する
        if let loader = loadingOperations[indexPath] {
            loader.cancel()
            loadingOperations.removeValue(forKey: indexPath)
        }
    }
}

추기


애플을 모방한 샘플에 숨겨진 구역을 추가했다.
배경이 회색인 부분은 사실 Collectioview가 표시되지 않는 영역입니다.
Clip to Bounds를 가짜로 설정합니다.
화면표시 영역에 들어가기 전에 그림을 설정하지만, 이미 읽었기 때문에 바로 그림을 설정할 수 있습니다.

총결산


기본 스크롤 개선 외에도 Pre-Fetching API 활용
더욱 원활한 UI 구현
이번 예는 간단해서 변화를 별로 느끼지 못했다
좀 더 복잡한 UI와 접근법에 공을 들이면 더 큰 폭으로 표현되지 않을까 생각합니다.
내일(정확히 모레)이 드디어 WWDC 2018이다.
올해는 어떤 서프라이즈가 우리를 기다리고 있을까.

관련 기사:


[Swift] 이 시기라서 수정된 iOS 10의 새로운 기능인 UIGraphicsImageRenderer와 UIViewPropertyAnimatior
[Swift] 이 시기부터 iOS 10의 새로운 기능인 UserNotifications, Notification Content Extension과 Notification Service Extension을 재검토하겠습니다.
[Swift] 이 시기이기 때문에 수정된 iOS 10의 새로운 기능인 AVcapture Photo Output AVcapture Settings 등

좋은 웹페이지 즐겨찾기