Search code examples
iosswiftuicollectionviewuikituicollectionviewdiffabledatasource

Where do the parameters come from in the UICollectionViewDiffableDataSource closure?


Having trouble understanding the closure in UICollectionViewDiffableDataSource, particularly what's being passed into it. All of the tutorials I can find explain what to type but not why, and I'm still a bit new to Swift and programming.

I'm following along with Paul Hudson's tutorial (he's making an app store made up of App objects) and in createDataSource() he writes:

dataSource = UICollectionViewDiffableDataSource<Section, App>(collectionView: collectionView)
  { collectionView, indexPath, app in 
    //rest of the closure
  }

My confusion on the closure's parameters is about where they're coming from:

  • He happens to declare collectionView as a global variable elsewhere in the View Controller. So I suppose that's required for this to be passed in?
  • Where is indexPath coming from here?
  • Most confusing: how does it know what app is? As far as I can tell it's not declared anywhere. This is the case in all the tutorials I've seen. Where in the world is the concept of an instance of App coming from?

Thank you a ton to anyone who can help me grasp this, I've been scouring tutorials but its been tough to figure out the mechanics here.


Solution

  • This is an initializer for the object. It looks like this:

      UICollectionViewDiffableDataSource<<#SectionIdentifierType: Hashable#>, <#ItemIdentifierType: Hashable#>>(collectionView: collectionView)
    

    It's using generics which are supplied as such <Section, App> Section in this example is defined as:

     import Foundation
    
      struct Section: Decodable, Hashable {
         let id: Int
         let type: String
         let title: String
         let subtitle: String
         let items: [App]
      }
    

    App is defined in the application in this example is:

      import Foundation
    
      struct App: Decodable, Hashable {
          let id: Int
          let tagline: String
          let name: String
          let subheading: String
          let image: String
          let iap: Bool
      }
    

    These types are supplied to the initializer to fulfill the type requirements of the generic init.

    Notice the object now understands how to get information from the UICollectionView.

    It can now call the block with parameters:

    1. The collection view you supplied.
    2. The IndexPath for the items by querying the sections by the type Section. 2a. The row information by querying the collection view for type App in section.
    3. Query the collectionView for the instance of App at indexPath.

    Check out Generic Types to get a better understanding.

    https://docs.swift.org/swift-book/LanguageGuide/Generics.html