0

I am trying to create a table of services such that, if service has a couple of sub-services, then the cell associated with that service then has another table view showing those sub-services under the said service.

I tried implementing such a table by looking at the example shown in the link: table within a tableviewcell

I am posting related source codes associated with the tableview

BookingServiceChargeViewCell.swift

import UIKit
import PineKit
import SwiftMoment

class BookingServiceChargeViewCell: UITableViewCell, UITableViewDelegate, UITableViewDataSource {

    var service : Service? = nil
    var subServices : [Service] = []
    let content = PineCardView()
    var cover = UIImageView()
    let serviceName = PineLabel.Bold(text: " ... ")
    var itemIndex = -1
    var chosen = false
    var parentView : OnboardingChosenServicesViewController? = nil
    var anchor = UIView()
    let table = UITableView()

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        self.selectionStyle = .none
        layout()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func layout() {
        self.addSubview(content)
        content.snp.makeConstraints { (make) in
            make.top.left.right.equalTo(self).inset(5)
            make.bottom.equalTo(self)
        }
        layoutContent()
    }

    func layoutContent() {
        content.addSubviews([cover, serviceName])

        self.cover.image = UIImage(named: "gray-card")
        cover.clipsToBounds = true

        cover.snp.makeConstraints { (make) in
            make.width.equalTo(content).multipliedBy(0.15)
            make.left.equalTo(content).offset(10)
            make.top.equalTo(content.snp.top).offset(15)
            make.size.equalTo(50)
        }

        serviceName.textColor = UIColor.black
        serviceName.font = Config.Font.get(.Bold, size: 17.5)
        serviceName.snp.makeConstraints { (make) in
            make.centerY.equalTo(cover)
            make.left.equalTo(cover.snp.right).offset(20)
        }

        table.delegate = self
        table.dataSource = self
        table.register(BookingSubServicesChargeViewCell.self, forCellReuseIdentifier: "cell")
        table.separatorStyle = .none

        self.content.addSubview(table)
        table.snp.makeConstraints { (make) in
            make.top.equalTo(self.cover.snp.bottom).offset(15)
            make.left.equalTo(self.cover.snp.right).offset(10)
            make.right.equalTo(self.content.snp.right).offset(-10)
            make.height.equalTo(450)
        }
    }

    func configure(_ service: Service, subServices: [Service], index: Int, parentView: OnboardingChosenServicesViewController) {
        self.service = service
        self.subServices = subServices
        self.itemIndex = index
        self.parentView = parentView

        if (self.service!.defaultImage != nil){
            ImageLoader.sharedLoader.imageForUrl(urlString: self.service!.defaultImage!) { (image, url) in
                self.cover.image = image
            }
        }

        self.serviceName.text = self.service!.name!
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return self.subServices.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! BookingSubServicesChargeViewCell
        cell.configure(self.subServices[indexPath.row], index: indexPath.row, parentView: self.parentView!)
        return cell
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 80
    }
}

BookingSubServicesChargeViewCell.swift

import UIKit
import PineKit
import SwiftMoment

class BookingSubServicesChargeViewCell: UITableViewCell {

    var service : Service? = nil
    let content = PineCardView()
    var cover = UIImageView()
    let serviceName = PineLabel.Bold(text: " ... ")
    var itemIndex = -1
    var chosen = false
    var parentView : OnboardingChosenServicesViewController? = nil
    var anchor = UIView()

    override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        self.selectionStyle = .none
        layout()
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    func layout() {
        self.addSubview(content)
        content.snp.makeConstraints { (make) in
            make.top.left.right.equalTo(self).inset(5)
            make.bottom.equalTo(self)
        }
        layoutContent()
    }

    func layoutContent() {
        content.addSubviews([cover, serviceName])

        self.cover.image = UIImage(named: "gray-card")
        cover.clipsToBounds = true

        cover.snp.makeConstraints { (make) in
            make.width.equalTo(content).multipliedBy(0.15)
            make.left.equalTo(content).offset(10)
            make.top.equalTo(content.snp.top).offset(15)
            make.size.equalTo(50)
        }

        serviceName.textColor = UIColor.black
        serviceName.font = Config.Font.get(.Bold, size: 17.5)
        serviceName.snp.makeConstraints { (make) in
            make.centerY.equalTo(cover)
            make.left.equalTo(cover.snp.right).offset(20)
        }
        self.anchor = self.serviceName
    }

    func configure(_ service: Service, index: Int, parentView: OnboardingChosenServicesViewController) {
        self.service = service
        self.itemIndex = index
        self.parentView = parentView

        if (self.service!.defaultImage != nil){
            ImageLoader.sharedLoader.imageForUrl(urlString: self.service!.defaultImage!) { (image, url) in
                self.cover.image = image
            }
        }

        self.serviceName.text = self.service!.name!
    }
}

Here a couple of screenshots of the situation that has arisen:- 1st Screenshot 2nd Screenshot 3rd Screenshot

As you can see in the screenshots, some of the tables which have sub-services are not being shown, but sometimes they are being shown.

Can someone tell me what is it that I am missing here? What changes am I supposed to make in the source codes shown above?

FYI: I am not using storyboards in any way and I do not know what nib files are. I have constructed this programmatically and I am hoping that I can get a code snippet based solution as soon as possible.

Thanks.

Pavan Vasan
  • 391
  • 1
  • 9
  • 28

1 Answers1

1

In BookingServiceChargeViewCell class, call self.table.reloadData() at the end of configure method as below.

func configure(_ service: Service, subServices: [Service], index: Int, parentView: OnboardingChosenServicesViewController) {
        self.service = service
        self.subServices = subServices
        self.itemIndex = index
        self.parentView = parentView

        if (self.service!.defaultImage != nil){
            ImageLoader.sharedLoader.imageForUrl(urlString: self.service!.defaultImage!) { (image, url) in
                self.cover.image = image
            }
        }

        self.serviceName.text = self.service!.name!

        self.table.reloadData()
    }
Kamran
  • 14,987
  • 4
  • 33
  • 51