无法在 TableView 单元格中 Select CollectionView

Can not Select CollectionView in TableView Cell

我正在制作日历。

我把集合视图放在了table视图中,但是集合视图的单元格没有被选中。

我刚刚将集合视图添加到 table 视图单元格并设置了所有数据源设置。

TableView allowSelection 关闭,tableViewCell isUserInteractionEnabled 设置为 false。

这里是我的代码

CalanderView.swift

import Foundation
import UIKit

class CalendarView: UIView {
    private var increaseYear: Int = 0
    
    internal lazy var tableView: UITableView = {
        let table = UITableView()
        table.showsVerticalScrollIndicator = false
        table.translatesAutoresizingMaskIntoConstraints = false
//        table.allowsSelection = false
        table.register(CalendarCell.self, forCellReuseIdentifier: CalendarCell.reuseIdentifier)
        table.delegate = self
        table.dataSource = self
        table.bounces = false
        table.tableFooterView = UIView(
            frame: CGRect(
                x: 0,
                y: 0,
                width: self.frame.width,
                height: 120.calculated
            )
        )
//        table.estimatedRowHeight = 600.calculated
        
        return table
    }()
    
    internal lazy var header: CalendarHeader = {
        let header = CalendarHeader(frame: self.frame)
        header.backgroundColor = .white
        
        return header
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)

        setLayoutConstraints()
    }
    
    required init(coder: NSCoder) {
        super.init(coder: coder)!
        
        setLayoutConstraints()
    }
}





// MARK: -CUSTOM FUNCTION
extension CalendarView {
    func getCurrentMonth(_ val: Int) -> Int {
        let obj = CalendarHelper.today.month + val
        let currentMonth = obj % 12 == 0 ? 12 : obj % 12
        let floatVal: Float = Float(obj) / 12.0
        let ceilVal = ceil(floatVal - 1)
        
        self.increaseYear = Int(ceilVal)
        
        return currentMonth
    }
}





// MARK: -DELEGATES, DATASOURCE
extension CalendarView: UITableViewDelegate, UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 6
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell: CalendarCell = tableView.dequeueReusableCell(for: indexPath)
        let currentMonth = getCurrentMonth(indexPath.row)
        let currentYear = CalendarHelper.today.year + self.increaseYear
        let component = DateComponents(year: currentYear, month: currentMonth)
        let days = CalendarHelper.shared.daysOfMonth[currentMonth-1]
        let dayOfMonth = CalendarHelper.dateFrom(component).isLeapMonth ? days + 1 : days
        
        cell.isUserInteractionEnabled = false
        cell.month = currentMonth
        cell.year = currentYear
        cell.dayOfWeek = CalendarHelper.dateFrom(component).weekday
        cell.dayOfMonth = dayOfMonth
        cell.separatorInset = UIEdgeInsets(top: 0, left: 20.calculated, bottom: 0, right: 20.calculated)
        
        cell.bringSubviewToFront(cell.dayCollection)
        
        return cell
    }
    
    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {

        return 550
    }
    
    func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
        return 550
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print("tableView didSelectRowAt")
    }
    
    func scrollViewDidScroll(_ scrollView: UIScrollView) {
        if let indexPath = self.tableView.indexPathsForVisibleRows {
            if indexPath.indices.contains(1) {
                let cell = tableView.cellForRow(at: indexPath[1]) as! CalendarCell
                if scrollView.contentOffset.y > cell.frame.origin.y - 10 {
                    self.header.month = cell.month
                    self.header.year = cell.year
                }
                
                let beforeCell = tableView.cellForRow(at: indexPath[0]) as! CalendarCell
                if scrollView.contentOffset.y < cell.frame.origin.y - 10 {
                    self.header.month = beforeCell.month
                    self.header.year = beforeCell.year
                }
            }
        }
        
    }
}




// MARK: -SET LAYOUT
extension CalendarView {
    func setLayoutConstraints() {
        setTableViewLayout()
        setHeaderViewLayout()
    }
    
    func setTableViewLayout() {
        self.addSubview(self.tableView)
        self.tableView.snp.makeConstraints({
            [=11=].top.bottom.left.right.equalTo(self)
        })
    }
    
    func setHeaderViewLayout() {
        self.addSubview(self.header)
        self.header.snp.makeConstraints({
            [=11=].left.right.top.equalTo(self)
            [=11=].height.equalTo(90.calculated)
        })
    }
}


class CalendarHeader: UIView {
    var year: Int = 0 {
        willSet(newVal) {
            self._year.attributedText = String(newVal)
                .normal(fontSize: 16, color: Color.customer, spacing: -0.07)
        }
    }
    
    var month: Int = 0 {
        willSet(newVal) {
            let str = String(newVal) + "."
            self._month.attributedText = str
                .systemFont(fontSize: 28, weight: .semibold, color: Color.customer, spacing: -0.12)
        }
    }
    
    private var _year: UILabel = {
        let label = UILabel()
        label.attributedText = "2019"
            .normal(fontSize: 16, color: Color.customer, spacing: -0.07)
        
        return label
    }()
    
    private var _month: UILabel = {
        let label = UILabel()
        label.attributedText = "11."
            .systemFont(fontSize: 28, weight: .semibold, color: Color.customer, spacing: -0.12)
        
        return label
    }()
    
    private var chevron: UIImageView = {
        let imageView = UIImageView()
        imageView.image = #imageLiteral(resourceName: "chevron_bottom")
        imageView.contentMode = .scaleAspectFit
        imageView.clipsToBounds = true
        
        return imageView
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        setLayoutConstraints()
        
        defer {
            self.year = CalendarHelper.today.year
            self.month = CalendarHelper.today.month
        }
    }
    
    required init(coder: NSCoder) {
        super.init(coder: coder)!
        
        setLayoutConstraints()
        defer {
            self.year = CalendarHelper.today.year
            self.month = CalendarHelper.today.month
        }
    }
    
    func setLayoutConstraints() {
        self.addSubview(self._year)
        self._year.snp.makeConstraints({
            [=11=].left.equalTo(self).offset(20.calculated)
            [=11=].top.equalTo(self).offset(41.calculated)
        })
        
        self.addSubview(self._month)
        self._month.snp.makeConstraints({
            [=11=].left.equalTo(self._year.snp.right).offset(4.calculated)
            [=11=].top.equalTo(self).offset(28.calculated)
        })
        
        self.addSubview(self.chevron)
        self.chevron.snp.makeConstraints({
            [=11=].width.height.equalTo(CGSize.ratio(width: 26, height: 14))
            [=11=].right.equalTo(self).offset(-20.calculated)
            [=11=].centerY.equalTo(self._month)
        })
    }
}

CalanderCell.swift

import Foundation
import UIKit
import SnapKit

class CalendarCell: UITableViewCell {
    let weekdays = ["S", "M", "T", "W", "T", "F", "S"]
    var dayOfWeek = 0
    var dayOfMonth = 0
    var day = 0
    
    var year: Int = 0 {
        willSet(newVal) {
            self._year.attributedText = String(newVal)
                .normal(fontSize: 16, color: Color.customer, spacing: -0.07)
        }
    }
    
    var month: Int = 0 {
        willSet(newVal) {
            let str = String(newVal) + "."
            self._month.attributedText = str
                .systemFont(fontSize: 28, weight: .semibold, color: Color.customer, spacing: -0.12)
        }
    }
    
    internal var _year: UILabel = {
        let label = UILabel()
        label.attributedText = "2019"
            .normal(fontSize: 16, color: Color.customer, spacing: -0.07)
        
        return label
    }()
    
    internal var _month: UILabel = {
        let label = UILabel()
        label.attributedText = "11."
            .systemFont(fontSize: 28, weight: .semibold, color: Color.customer, spacing: -0.12)
        
        return label
    }()
    
    internal var dayCollection: UICollectionView = {
        let collectionViewLayout = UICollectionViewFlowLayout()
        collectionViewLayout.scrollDirection = .vertical
        
        let collection = UICollectionView(
            frame: CGRect(x: 0, y: 0, width: 0, height: 0),
            collectionViewLayout: collectionViewLayout
        )
        collection.showsVerticalScrollIndicator = false
        collection.showsHorizontalScrollIndicator = false
        collection.isMultipleTouchEnabled = false
        collection.allowsMultipleSelection = false
        collection.isScrollEnabled = false
        collection.isExclusiveTouch = true
        collection.isUserInteractionEnabled = true
        collection.backgroundColor = Color.background
        collection.register(DayCell.self, forCellWithReuseIdentifier: DayCell.reuseIdentifier)
        
        
        return collection
    }()
    
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        
        setLayoutConstraints()
        
        
        dayCollection.delegate = self
        dayCollection.dataSource = self
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}





extension CalendarCell {

}





extension CalendarCell: UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    /// 지정된 섹션에 표시할 항목의 개수를 묻는 메서드
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        if section == 0 {
            return 7
        } else {
            print("dayOfWeek", dayOfMonth)
            return dayOfMonth + dayOfWeek - 1
        }
    }
    
    /// 컬렉션뷰의 지정된 위치에 표시할 셀을 요청하는 메서드.
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell: DayCell = collectionView.dequeueReusableCell(for: indexPath)
        cell.isUserInteractionEnabled = true
        
        if indexPath.section == 0 {
            cell.week = weekdays[indexPath.row]
        } else {
            if dayOfWeek > 1 {
                cell.day = ""
                dayOfWeek -= 1
            } else {
                day += 1
                cell.day = String(day)
                cell.isSunday = indexPath.row % 7 == 0
            }
        }
        
        return cell
    }
    
    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 2
    }
    
    /// 지정된 섹션의 여백을 반환하는 메서드.
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {
        return UIEdgeInsets(top: 0, left: 25.calculated, bottom: 25.calculated, right: 25.calculated)
    }
    
    /// 지정된 섹션의 행 사이 간격 최소 간격을 반환하는 메서드
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 25
    }
    
    /// 지정된 섹션의 셀 사이의 최소간격을 반환하는 메서드.
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
        return 25
    }
    
    /// 지정된 셀의 크기를 반환하는 메서드
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize.ratio(width: 30, height: 30)
    }
    
    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        print("indexPath: ", indexPath)
    }
}



extension CalendarCell {
    func setLayoutConstraints() {
        setHeaderLayout()
        setDayCollectionLayout()
    }
    
    func setHeaderLayout() {
        self.addSubview(self._year)
        self._year.snp.makeConstraints({
            [=12=].left.equalTo(self).offset(20.calculated)
            [=12=].top.equalTo(self).offset(61.calculated)
        })
        
        self.addSubview(self._month)
        self._month.snp.makeConstraints({
            [=12=].left.equalTo(self._year.snp.right).offset(4.calculated)
            [=12=].top.equalTo(self).offset(48.calculated)
        })
    }
    
    func setDayCollectionLayout() {
        self.addSubview(self.dayCollection)
        self.dayCollection.snp.makeConstraints({
            [=12=].height.equalTo(400.calculated)
            [=12=].left.right.equalTo(self)
            [=12=].top.equalTo(self).offset(116.calculated)
        })
    }
}

DayCell.swift

import Foundation
import UIKit

class DayCell: UICollectionViewCell {
    var isSunday: Bool = false {
        willSet(newVal) {
            self._day.textColor = newVal ? Color.customer : Color.label
        }
    }
    var isReserved: Bool = false {
        willSet(newVal) {
            self._day.textColor = Color.cancle
        }
    }
//    override var isSelected: Bool {
//        willSet(newVal) {
//            self.backgroundColor = newVal
//                ? Color.customer
//                : Color.background
//            self._day.textColor = newVal
//                ? .white
//                : (isSunday ? Color.customer : Color.label)
//        }
//    }
    var day: String = "" {
        willSet(newVal) {
            self._day.attributedText = newVal
                .systemFont(fontSize: 18, weight: .bold, color: Color.label, spacing: -0.07)
        }
    }
    var week: String = "" {
        willSet(newVal) {
            self._day.attributedText = newVal
                .systemFont(fontSize: 20, weight: .medium, color: Color.customer, spacing: -0.08)
        }
    }
    
    internal var _day: UILabel = {
        let label = UILabel()
        label.attributedText = "1"
            .systemFont(fontSize: 18, weight: .bold, color: Color.label, spacing: -0.07)
        
        return label
    }()
    
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        self.layer.cornerRadius = 7.calculated
        self.addSubview(self._day)
        self._day.snp.makeConstraints({
            [=13=].center.equalTo(self)
        })
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

这是错误的:

class DayCell: UICollectionViewCell {
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        self.layer.cornerRadius = 7.calculated
        self.addSubview(self._day) // <-- NO
        self._day.snp.makeConstraints({
            [=10=].center.equalTo(self)
        })
    }
}

切勿向单元格添加子视图。说

self.contentView.addSubview(self._day)

否则无法触及_day界面