[SWIFT] I tried using UICollectionViewListCell added from Xcode12.

Will UITableView become unusable in a few years? ??

UICollectionViewListCell, which appeared in Xcode12, is a new UI part that replaces UITableView in terms of functionality. You can create a UITableView-like screen with UICollectionViewListCell.

This means that it's useless for UITableView ...

So, I will try using ʻUICollectionViewListCell`, which will be used when displaying the list format screen in the future.

1. Create layout (UICollectionViewLayout)

This time I wanted to display a list in ʻinset Grouped` format, so I set it as follows.


override func viewDidLoad() {
    super.viewDidLoad()
    navigationItem.title = "title"
    collectionView.collectionViewLayout = createLayout()
}

private func createLayout() -> UICollectionViewLayout {
    let config = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
    let layout = UICollectionViewCompositionalLayout.list(using: config)
    return layout
}

Now you are ready for a list-style layout like healthcare.

2. Acquisition of display data

This time, execute the API to get the article of Qiita and display the title on the screen. Therefore, create a process to get the list of articles. Use Alamofire

private func getData() {
    AF.request(
        "https://qiita.com/api/v2/items",
        method: .get
    ).responseJSON { response in
        switch response.result {
        case .success:
            if let data = response.data {
                let json = try! JSONDecoder().decode([ItemsResponse].self, from: data)
                print(json)
            }
        case let .failure(error):
            print(error)
        }
    }
}

struct ItemsResponse: Codable, Hashable {
    let body: String?
    let coediting: Bool?
    let commentsCount: Int?
    let createdAt: String?
    let group: String?
    let id: String?
    let likesCount: Int?
    let pageViewsCount: String?
    let privateField: Bool?
    let reactionsCount: Int?
    let renderedBody: String?
    let tags: [Tag]?
    let title: String?
    let updatedAt: String?
    let url: String?
    let user: User?
}
struct User: Codable, Hashable {
    let descriptionField: String?
    let facebookId: String?
    let followeesCount: Int?
    let followersCount: Int?
    let githubLoginName: String?
    let id: String?
    let itemsCount: Int?
    let linkedinId: String?
    let location: String?
    let name: String?
    let organization: String?
    let permanentId: Int?
    let profileImageUrl: String?
    let teamOnly: Bool?
    let twitterScreenName: String?
    let websiteUrl: String?
}

struct Tag: Codable, Hashable {
    let name: String?
    let versions: [String]?
}

You can get the json of the response by executing the method created with this.

3. Register how to display

First, set the Section configuration of the Collection View. This time I wanted to make it a simple one section, so I created the following Enum.

extension FirstViewController {
    enum Section {
        case main
    }
}

Next, register how to display. In terms of TableView, I think it is a process similar to UITableViewDataSource.

private func setupCollectionView() {
    let registration = UICollectionView.CellRegistration<UICollectionViewListCell, ItemsResponse> { cell, _, text in
        var content = cell.defaultContentConfiguration()
        //Set article title
        content.text = text.title
        cell.contentConfiguration = content
    }
    dataSource =
        UICollectionViewDiffableDataSource<Section,
                                           ItemsResponse>(collectionView: self.collectionView) { collectionView, indexPath, text in
        collectionView
            .dequeueConfiguredReusableCell(using: registration,
                                           for: indexPath,
                                           item: text)
    }
}

Create screen update process

It's like taking a snapshot and adding sections and items ...

private func populate(with response: [ItemsResponse]) {
    var snapshot = NSDiffableDataSourceSnapshot<Section, ItemsResponse>()
    snapshot.appendSections([.main])
    snapshot.appendItems(response)
    dataSource?.apply(snapshot)
}

Execute the method created according to the life life cycle

In the end, it became a class like this.

import Alamofire
import UIKit

class FirstViewController: UIViewController {

    @IBOutlet private weak var collectionView: UICollectionView!

    private var dataSource: UICollectionViewDiffableDataSource<Section, ItemsResponse>?
    private var displayData: [ItemsResponse] = []

    override func viewDidLoad() {
        super.viewDidLoad()
        navigationItem.title = "title"
        collectionView.collectionViewLayout = createLayout()
        setupCollectionView()
        getData()
    }

    private func createLayout() -> UICollectionViewLayout {
        let config = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
        let layout = UICollectionViewCompositionalLayout.list(using: config)
        return layout
    }

    private func setupCollectionView() {
        let registration = UICollectionView.CellRegistration<UICollectionViewListCell, ItemsResponse> { cell, _, text in
            var content = cell.defaultContentConfiguration()
            content.text = text.title
            cell.contentConfiguration = content
        }

        dataSource =
            UICollectionViewDiffableDataSource<Section,
                                               ItemsResponse>(collectionView: self.collectionView) { collectionView, indexPath, text in
            collectionView
                .dequeueConfiguredReusableCell(using: registration,
                                               for: indexPath,
                                               item: text)
        }
    }

    private func populate(with response: [ItemsResponse]) {
        var snapshot = NSDiffableDataSourceSnapshot<Section, ItemsResponse>()
        snapshot.appendSections([.main])
        snapshot.appendItems(response)
        dataSource?.apply(snapshot)
    }

    private func getData() {
        AF.request(
            "https://qiita.com/api/v2/items",
            method: .get
        ).responseJSON { response in
            switch response.result {
            case .success:
                if let data = response.data {
                    let json = try! JSONDecoder().decode([ItemsResponse].self, from: data)
                    self.populate(with: json)
                }
            case let .failure(error):
                print(error)
            }
        }
    }

}

extension FirstViewController {
    enum Section {
        case main
    }
}
///For Qiita article mapping
struct ItemsResponse: Codable, Hashable {

    let body: String?
    let coediting: Bool?
    let commentsCount: Int?
    let createdAt: String?
    let group: String?
    let id: String?
    let likesCount: Int?
    let pageViewsCount: String?
    let privateField: Bool?
    let reactionsCount: Int?
    let renderedBody: String?
    let tags: [Tag]?
    let title: String?
    let updatedAt: String?
    let url: String?
    let user: User?

}
struct User: Codable, Hashable {

    let descriptionField: String?
    let facebookId: String?
    let followeesCount: Int?
    let followersCount: Int?
    let githubLoginName: String?
    let id: String?
    let itemsCount: Int?
    let linkedinId: String?
    let location: String?
    let name: String?
    let organization: String?
    let permanentId: Int?
    let profileImageUrl: String?
    let teamOnly: Bool?
    let twitterScreenName: String?
    let websiteUrl: String?
}

struct Tag: Codable, Hashable {
    let name: String?
    let versions: [String]?
}

Try to run

I was able to use it for the time being.

Swift It's been so long since I forgot how to use UICollectionViewDiffableDataSource ... Not only ʻUICollectionViewListCell but ʻUICollectionView itself has evolved considerably, so I'll do my best to keep up!

Next, I will add refresh processing and additional reading processing, etc., and proceed to a level that can be used as an application.

Recommended Posts

I tried using UICollectionViewListCell added from Xcode12.
I tried using Gson
I tried using TestNG
I tried using Galasa
I tried using azure cloud-init
I tried using Apache Wicket
I tried using Java REPL
I tried using anakia + Jing now
I tried using Spring + Mybatis + DbUnit
I tried using JOOQ with Gradle
I tried using Java8 Stream API
I tried using JWT in Java
[Android] I tried using Coordinator Layout.
I tried using Pari gp container
I tried using WebAssembly Stadio (2018/4/17 version)
I tried using Java memo LocalDate
I tried using GoogleHttpClient of Java
I tried using Realm with Swift UI
I tried using Java's diagnostic tool Arthas
I tried using Scalar DL with Docker
I tried using OnlineConverter with SpringBoot + JODConverter
It's new, but I tried using Groonga
I tried using OpenCV with Java + Tomcat
I tried to build Ruby 3.0.0 from source
I tried using Docker for the first time
I tried using Junit on Mac VScode Maven
[For beginners] I tried using DBUnit in Eclipse
[For beginners] I tried using JUnit 5 in Eclipse
[Android] I quit SQLite and tried using Realm
I tried hitting a Java method from ABCL
I made blackjack with Ruby (I tried using minitest)
I tried Spring.
[API] I tried using the zip code search API
I tried tomcat
I tried youtubeDataApi.
I tried refactoring ①
I tried FizzBuzz.
I tried to implement a server using Netty
I tried using the profiler of IntelliJ IDEA
[JDBC ③] I tried to input from the main method using placeholders and arguments.
I tried JHipster 5.1
I tried using a database connection in Android development
I tried using the Server Push function of Servlet 4.0
I tried using Alibaba Cloud's KMS (Key Management Service) service
I tried using Google Cloud Vision API in Java
I tried to operate SQS using AWS Java SDK
I tried using the Migration Toolkit for Application Binaries
I tried using Log4j2 on a Java EE server
I tried using YOLO v4 on Ubuntu and ROS
I tried calling Java / Objective-C native code from Flutter
I tried using Docker Desktop for Windows on Windows 10 Home
I tried using an extended for statement in Java
I tried scraping a stock chart using Java (Jsoup)
I tried to build an environment using Docker (beginner)
[I tried] Spring tutorial
I tried running Autoware
I tried QUARKUS immediately
I tried Spring Batch
I tried node-jt400 (Programs)
I tried node-jt400 (execute)
I tried node-jt400 (Transactions)