Swift 4.0 multiple TableViewCell multiple request complex interface solution

Keywords: network xcode iOS Swift


This project is a multi-layer complex structure and multi request interface implementation case.

No, please advise.

Thank you:)


The interface layout of this project is mainly Moya selected by IGListKit for network request.




  • Xcode 9.0+
  • iOS 9.0+
  • Swift 4.0+
  • CocoaPods


class DemoViewController: RootListViewController {
    override func viewDidLoad() {

        // Do any additional setup after loading the view.

   func configData() {
        let gridOne = CollectionManager("gridOne", request: Home.gridItem) { () -> ListSectionController in
            return self.gridSectionController()
        let textOne = CollectionManager("textOne", request: Home.text) { () -> ListSectionController in
            return self.textSectionController()
        let imageOne = CollectionManager("imageOne", request: Home.image) { () -> ListSectionController in
            return self.imageSectionController()
        let centerTextOne = CollectionManager("centerTextOne", request: Home.centerText) { () -> ListSectionController in
            return self.embeddedSectionController()
        listManager.register([gridOne, textOne, centerTextOne, imageOne])
    override func didReceiveMemoryWarning() {
        // Dispose of any resources that can be recreated.

Content of project framework:

  • RootListdViewController: the core ViewController from which any other extension instance can inherit

    import IGListKit
    import Moya
    open class RootListViewController: UIViewController {
        ///IGListKit needs to use
        lazy var adapter: ListAdapter = {
            return ListAdapter(updater: ListAdapterUpdater(), viewController: self, workingRangeSize: 1)
        ///Display layout
        @IBOutlet public var collectionView: UICollectionView!
        ///Data configuration tool
        lazy var listManager: ListManager = {
            return ListManager(Date().description, delegate: self)
        override open func viewDidLoad() {
            if collectionView == nil {
                collectionView = UICollectionView(frame: .zero, collectionViewLayout: UICollectionViewFlowLayout())
            if collectionView.superview == nil {
            adapter.collectionView = collectionView
            adapter.dataSource = listManager
        override open func viewDidLayoutSubviews() {
            collectionView.frame = view.bounds
    extension RootListViewController: UpdateData {
        func dataUpdated() {
            self.adapter.performUpdates(animated: true, completion: nil)
  • ListManager manages all display items in the current interface

  • Collection Manager: contains each group of elements that need to be displayed. Listmanager's_ Value in itemKeyValues.

final class CollectionManager {
  ///What needs to be done after configuration is completed, not used at present
  var completion: ((CollectionManager) -> Void) = { _ in }
  ///Contained elements
  var items: [ListDiffable] = []
  ///Unique identifier of my ListManager
  var listManagerIdentifier: String = ""
  ///My unique identifier
  var identifier: String = ""
  ///Start request data
  var startRequest = true
  ///Request type
  public var request: Home = .none
  weak var delegate: UpdateData?
  init(_ identifier: String, request: Home = .none, startRequest: Bool = true, completion: @escaping (CollectionManager) -> Void = {_ in }) {
      self.identifier = identifier
      self.completion = completion
      self.request = request
      self.startRequest = startRequest
      if self.request == .none {
          self.startRequest = false
      if !self.startRequest {
      ///Recreating a model is the same as all my properties (think about whether it can be optimized by implementing NSCopy later)
      ///startRequest is set to false to prevent repeated loop requests from falling into a dead loop
      let myNewItem = CollectionManager(self.identifier,request: self.request, startRequest: false, completion: self.completion)
      homeProvider.request(request) { (result) in
          var tmpItems: [ListDiffable] = []
          //TODO: - data conversion
          switch request {
          case .gridItem:
              tmpItems = self.demoGridItems()// False data
          case .text:
              tmpItems = self.demoStrings() as [ListDiffable]// False data
          case .centerText:
              tmpItems = self.demoCenterStrings()// False data
          case .image:
              tmpItems = self.demoImageURLs() as [ListDiffable]// False data
          myNewItem.items = tmpItems
          if let listManager = ManagerCenter.shared[self.listManagerIdentifier],
              listManager.itemIdentifiers.contains(self.identifier) {
              //Re register and replace the original corresponding element
  • ManagerCenter: a single instance containing all listmanagers in the project.
  • The project is decoupled and encapsulated again on the basis of IGListKit
    • RowListSectionController
    • HorizontalSectionController
    • GridSectionController
  • YILUtilKit: others.
  • CollectionItem: the model in CollectionManager implements listdiffable (refer to IGListKit)

Request processing Moya

*Controlling multiple concurrent requests with semaphores in projects
 *Efficient loading of large image and network image spaceship
 *In the project, the random sleep (arc4random()%8) imitates the time-consuming of different threads, and the order of returning to refresh the display remains unchanged.

Thank you!

Thank you for XXX's long advice.

Posted by markjoe on Thu, 28 May 2020 08:09:38 -0700