12
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

[Swift 5] スクロールに応じてページング対応APIから1ページずつコンテンツを取得する方法

Posted at

Requestパラメータでpageを指定すれば指定したページの情報を取得できるようなAPIがあるとして、
そのAPIから取得したコンテンツをアプリでページングして表示する実装の備忘録です。

読み込み状態を定義

/// APIの読み込み状況
enum APILoadingStatus {
    case initial
    case fetching
    case loadMore
    case full
    case error
}

Viewでの実装

final class ViewController: UIViewController {

    /// APIの最終取得Page
    private var pageOfLastFetched = 1
    /// APIの読み込み状況
    private var loadStatus: APILoadingStatus = .initial

}

インクリメントして使うPage数と、読み込み状態を保持するプロパティを宣言します。

    // APIを使用してコンテンツを取得する
    func fetchContents() {
        // 読み込み中またはもう次に記事がない場合にはapiを叩かない
        if loadStatus == .fetching || loadStatus == .full {
            return
        }
        // loadStatusを読み込み中に変更
        loadStatus = .fetching
      
        // 記事一覧を取得するAPIを叩く
        repository.getContents(page: pageOfLastFetched) { [weak self] result in
                                 
            guard let self = self else {
                return
            }
                                                                
            switch result {
            case .success(let contents):
                if contents.isEmpty {
                    // 結果が空だった=もう続きの記事がないのでloadStatusをfullにする
                    self.loadStatus = .full
                    return
                }
                self.pageOfLastFetched.increment()  // +1
                // 記事取得が終わった段階でloadStatusをloadMoreにする
                self.loadStatus = .loadMore
              
            case .failure(let error):
                // loadStatusをエラーにする
                self.loadStatus = .error
                // TODO: Error handling.
                print(error)
            }
        }
    }

APIをコールするメソッドを定義します。
成功したらPage数をインクリメントして、最後までFetchしたら読み込み状態を .full にして以後APIをコールしないようにします。

    // MARK: - UIScrollViewDelegate
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        // 一定割合スクロールすると次のPageを読み込む
        let currentOffsetY = scrollView.contentOffset.y
        let maximumOffset = scrollView.contentSize.height - scrollView.frame.height
        let distanceToBottom = maximumOffset - currentOffsetY
        
        // 最下部まで500pxを切ったら次のページを取得する
        if distanceToBottom < 500 {
            fetchContents()
        }
    }

ページングするタイミングですが、今回は画面最下部500pxを切るところまでスクロールされたらAPIでFecthするようにしました。

12
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
12
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?