swift 如何在声明变量后根据if和else-if语句更改自定义单元格变量的赋值?斯威夫特

2jcobegt  于 2023-06-21  发布在  Swift
关注(0)|答案(1)|浏览(62)

我尝试创建一个自定义单元格,在声明变量后,它的变量赋值会根据ifelse-if语句进行更改。
这是为了让自定义单元格(显示所选业务的营业时间)能够选择custom table view cell,该custom table view cell符合我希望为该业务显示的一周的开放和关闭时间范围对的数量(因为一些业务在一天内有多个)。
但是,我一直收到一个错误消息说:
Cannot assign value of type 'DetailsHoursContentsForAtLeastOneDayWithTwoOpenCloseTimeRangePairsTableViewCell' to type ‘DetailsHoursContentsForAllDaysWithOneOpenCloseTimeRangePairTableViewCell'
在这行代码中:

detailsHoursContentsCustomCell = scrollableCitiesRestaurantDetailsTableView.dequeueReusableCell(withIdentifier: "DetailsHoursContentsForAtLeastOneDayWithTwoOpenCloseTimeRangePairsTableViewCell", for: indexPath) as! DetailsHoursContentsForAtLeastOneDayWithTwoOpenCloseTimeRangePairsTableViewCell

这是第一个else-if语句的条件语句中的代码行,它更改了我正在使用的自定义单元格变量的变量赋值。这行代码上面有一个注解,上面有它在这篇文章下面的代码片段中得到的错误消息。else-if语句之前的if-statement中的条件语句将值设置为自定义单元格变量开始时的值,并且不会获得此类错误消息,也不会在其条件语句中获得任何类型的错误消息。
在其他else-if语句的条件语句中,我也得到了相同的错误消息,其中自定义单元格变量值被更改。在这些代码行上方还有注解,说明在下面的代码段中针对该特定代码行接收到的错误消息。

我尝试过的:

  • 调查是否使用“as?”或“as”而不是强制转换(使用“as!”)在代码行中,我得到这些相同类型的错误消息,可能会工作,但在我看来它不会。
    我如何修复这个错误消息,和/或如果我当前尝试的方式不起作用(使用“正确”的代码),我如何继续做我正在尝试做的事情?
    谢谢!
    代码在下面。

编码

ViewController.swift:

import UIKit

//*Some code for a view controller for a table view file.*

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    if indexPath.row == 0 {
        
        //*Code for this cell goes here.*
        
        return custumCell
    }

    //*More "indexPath.row" code goes here for other table view cells being used.*

    if indexPath.row == 10 {
        
        var detailsHoursContentsCustomCell = scrollableCitiesRestaurantDetailsTableView.dequeueReusableCell(withIdentifier: "DetailsHoursContentsForAllDaysWithOneOpenCloseTimeRangePairTableViewCell", for: indexPath) as! DetailsHoursContentsForAllDaysWithOneOpenCloseTimeRangePairTableViewCell
        
        //If number of open hour time rnage pairs for all days is one.
        if selectedVenueDetailViewInfo.hours.numberOfOpenHoursTimeRangesAsStringTypeOfTableViewCellToUse == "OneTimeRange" {
            
            detailsHoursContentsCustomCell = scrollableCitiesRestaurantDetailsTableView.dequeueReusableCell(withIdentifier: "DetailsHoursContentsForAllDaysWithOneOpenCloseTimeRangePairTableViewCell", for: indexPath) as! DetailsHoursContentsForAllDaysWithOneOpenCloseTimeRangePairTableViewCell
        }
        
        //Else If number of open hour time rnage pairs for at least one day is two.
        else if selectedVenueDetailViewInfo.hours.numberOfOpenHoursTimeRangesAsStringTypeOfTableViewCellToUse == "TwoTimeRanges" {
            
            //Below is the line of code where I get the error message: "Cannot assign value of type 'DetailsHoursContentsForAtLeastOneDayWithTwoOpenCloseTimeRangePairsTableViewCell' to type 'DetailsHoursContentsForAllDaysWithOneOpenCloseTimeRangePairTableViewCell'".
            detailsHoursContentsCustomCell = scrollableCitiesRestaurantDetailsTableView.dequeueReusableCell(withIdentifier: "DetailsHoursContentsForAtLeastOneDayWithTwoOpenCloseTimeRangePairsTableViewCell", for: indexPath) as! DetailsHoursContentsForAtLeastOneDayWithTwoOpenCloseTimeRangePairsTableViewCell
        }
        
        //Else If number of open hour time rnage pairs for at least one day is three.
        else if selectedVenueDetailViewInfo.hours.numberOfOpenHoursTimeRangesAsStringTypeOfTableViewCellToUse == "ThreeTimeRanges" {
            
            //Below is the line of code where I get the error message: "Cannot assign value of type 'DetailsHoursContentsForAtLeastOneDayWithThreeOpenCloseTimeRangePairsTableViewCell' to type 'DetailsHoursContentsForAllDaysWithOneOpenCloseTimeRangePairTableViewCell'".
            detailsHoursContentsCustomCell = scrollableCitiesRestaurantDetailsTableView.dequeueReusableCell(withIdentifier: "DetailsHoursContentsForAtLeastOneDayWithThreeOpenCloseTimeRangePairsTableViewCell", for: indexPath) as! DetailsHoursContentsForAtLeastOneDayWithThreeOpenCloseTimeRangePairsTableViewCell
            
        }
        
        //Else If number of open hour time rnage pairs for at least one day is more than three.
        else if selectedVenueDetailViewInfo.hours.numberOfOpenHoursTimeRangesAsStringTypeOfTableViewCellToUse == "GreaterThanThreeTimeRanges" {
            
            //Below is the line of code where I get the error message: "Cannot assign value of type 'DetailsHoursContentsForAtLeastOneDayWithGreaterThanThreeOpenCloseTimeRangePairsTableViewCell' to type 'DetailsHoursContentsForAllDaysWithOneOpenCloseTimeRangePairTableViewCell'".
            detailsHoursContentsCustomCell = scrollableCitiesRestaurantDetailsTableView.dequeueReusableCell(withIdentifier: "DetailsHoursContentsForAtLeastOneDayWithGreaterThanThreeOpenCloseTimeRangePairsTableViewCell", for: indexPath) as! DetailsHoursContentsForAtLeastOneDayWithGreaterThanThreeOpenCloseTimeRangePairsTableViewCell
        }
        
        //Setting hours as labels.
        detailsHoursContentsCustomCell.sundayHoursOpenWithoutDayLabel.text = selectedVenueDetailViewInfo.hours.sundayOpenHoursWithoutDay
        detailsHoursContentsCustomCell.mondayHoursOpenWithoutDayLabel.text = selectedVenueDetailViewInfo.hours.mondayOpenHoursWithoutDay
        detailsHoursContentsCustomCell.tuesdayHoursOpenWithoutDayLabel.text = selectedVenueDetailViewInfo.hours.tuesdayOpenHoursWithoutDay
        detailsHoursContentsCustomCell.wednesdayHoursOpenWithoutDayLabel.text = selectedVenueDetailViewInfo.hours.wednesdayOpenHoursWithoutDay
        detailsHoursContentsCustomCell.thursdayHoursOpenWithoutDayLabel.text = selectedVenueDetailViewInfo.hours.thursdayOpenHoursWithoutDay
        detailsHoursContentsCustomCell.fridayHoursOpenWithoutDayLabel.text = selectedVenueDetailViewInfo.hours.fridayOpenHoursWithoutDay
        detailsHoursContentsCustomCell.saturdayHoursOpenWithoutDayLabel.text = selectedVenueDetailViewInfo.hours.saturdayOpenHoursWithoutDay
        
        return detailsHoursContentsCustomCell
    }
}

//*Some Extensions.*

选择餐厅后,用于显示在详细视图中的营业时间数据的模型部分:
DetailViewModel.swift:

import Foundation

//*Other code for getting data such as name of restaurant, street address of restaurant, etc. for the detail view not using Codable. Am using NSDictionary.*

struct OpenHoursForDaysOfWeek {
    var mondayOpenHoursWithoutDay: String
    var tuesdayOpenHoursWithoutDay: String
    var wednesdayOpenHoursWithoutDay: String
    var thursdayOpenHoursWithoutDay: String
    var fridayOpenHoursWithoutDay: String
    var saturdayOpenHoursWithoutDay: String
    var sundayOpenHoursWithoutDay: String
    var numberOfOpenHoursTimeRangesAsStringTypeOfTableViewCellToUse: String
}

我的表格视图单元格布局:

AllDaysWithOneTimeRangeTableViewCell
AtLeastOneDayWithTwoTimeRangesTableViewCell
AtLeastOneDayWithThreeTimeRangesTableViewCell

bis0qfac

bis0qfac1#

在没有看到你的UI设计的情况下,我假设:

  • 各种单元格类型具有一些“通用”UI元素
  • 这些差异与工作时间有关吗?

您可能会使用单单元格设计,然后根据需要显示/隐藏不同的UI元素。
例如:

这张图片显示了三种不同的原型细胞。
然而,底部单元格在垂直方向UIStackView上有3个“行”。我们可以通过隐藏第2和第3行并设置黄色和青色标签文本来轻松地将其转换为第一个单元格。
如果你觉得你的布局/设计太复杂了,并且你想坚持使用多个单元原型,那么我建议让单元类来处理解析数据……
所以每个细胞都可以有这样的功能:

public func fillTheData(_ venue: VenueStruct) {
        sundayHoursOpenWithoutDayLabel.text = venue.hours.sundayOpenHoursWithoutDay
        mondayHoursOpenWithoutDayLabel.text = venue.hours.mondayOpenHoursWithoutDay
        tuesdayHoursOpenWithoutDayLabel.text = venue.hours.tuesdayOpenHoursWithoutDay
        wednesdayHoursOpenWithoutDayLabel.text = venue.hours.wednesdayOpenHoursWithoutDay
        thursdayHoursOpenWithoutDayLabel.text = venue.hours.thursdayOpenHoursWithoutDay
        fridayHoursOpenWithoutDayLabel.text = venue.hours.fridayOpenHoursWithoutDay
        saturdayHoursOpenWithoutDayLabel.text = venue.hours.saturdayOpenHoursWithoutDay
    }

据推测,每种单元格类型都有不同的标签。要设置的文本。
然后你的cellForRowAt看起来像这样:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    if indexPath.row == 0 {
        //*Code for this cell goes here.*
        return custumCell
    }
    
    //*More "indexPath.row" code goes here for other table view cells being used.*
    
    if indexPath.row == 10 {
        
        //If number of open hour time rnage pairs for all days is one.
        if selectedVenueDetailViewInfo.hours.numberOfOpenHoursTimeRangesAsStringTypeOfTableViewCellToUse == "OneTimeRange" {
            let cell = tableView.dequeueReusableCell(withIdentifier: "DetailsHoursContentsForAllDaysWithOneOpenCloseTimeRangePairTableViewCell", for: indexPath) as! DetailsHoursContentsForAllDaysWithOneOpenCloseTimeRangePairTableViewCell
            cell.fillData(selectedVenueDetailViewInfo)
            return cell
        }
        
        //Else If number of open hour time rnage pairs for at least one day is two.
        else if selectedVenueDetailViewInfo.hours.numberOfOpenHoursTimeRangesAsStringTypeOfTableViewCellToUse == "TwoTimeRanges" {
            
            //Below is the line of code where I get the error message: "Cannot assign value of type 'DetailsHoursContentsForAtLeastOneDayWithTwoOpenCloseTimeRangePairsTableViewCell' to type 'DetailsHoursContentsForAllDaysWithOneOpenCloseTimeRangePairTableViewCell'".
            let cell = tableView.dequeueReusableCell(withIdentifier: "DetailsHoursContentsForAtLeastOneDayWithTwoOpenCloseTimeRangePairsTableViewCell", for: indexPath) as! DetailsHoursContentsForAtLeastOneDayWithTwoOpenCloseTimeRangePairsTableViewCell
            cell.fillData(selectedVenueDetailViewInfo)
            return cell
        }
        
        // and so on
    }
}

编辑- * 在评论和看到布局目标后... *

现在我看过你的布局了,这是一个更简单的任务。它可以用一个单元格类来完成,并且根本不需要显示/隐藏元素。
两种选择:

  • 将每组小时设置为属性字符串格式
  • 使用堆栈视图

每一个都有它的优点和缺点…在单个标签中使用属性化字符串会很好:

除了---iOS版本之间的属性化字符串存在差异。更熟悉它的人可能知道如何解决这个问题。
使用堆栈视图非常简单。
下面是它在黄色背景下的外观,因此我们可以看到标签框架:

没有黄色:

我不知道你是如何获取数据的,所以我做了一个Venue结构体,看起来像这样:

struct VenueStruct {
    // assuming there are some other properties
    var venueName: String = "Some Venue"
    var venueAddress: String = "123 Main Street"
    // etc...
    
    // array of operating hours
    //  this will be filled with 7 [String] arrays (one for each day of the week)
    //  each of those arrays will have 1 or more time ranges
    var hoursArray: [[String]] = []
}

示例hoursArray s -填充数据时:

["11:00 am - 10:00 pm"]
["11:00 am - 10:00 pm"]
["11:00 am - 10:00 pm"]
["11:00 am - 10:00 pm"]
["11:00 am - 10:00 pm"]
["11:00 am - 10:00 pm"]
["11:00 am - 10:00 pm"]
-----
["7:00 am - 11:00 am", "12:00 pm - 10:00 pm"]
["10:00 am - 10:00 pm"]
["7:00 am - 11:00 am", "12:00 pm - 10:00 pm"]
["10:00 am - 10:00 pm"]
["10:00 am - 10:00 pm"]
["10:00 am - 10:00 pm"]
["10:00 am - 10:00 pm"]
-----
["7:00 am - 11:00 am", "12:00 pm - 4:00 pm", "5:00 pm - 10:00 pm"]
["10:00 am - 10:00 pm"]
["7:00 am - 11:00 am", "12:00 pm - 4:00 pm", "5:00 pm - 10:00 pm"]
["10:00 am - 10:00 pm"]
["10:00 am - 10:00 pm"]
["10:00 am - 10:00 pm"]
["10:00 am - 10:00 pm"]
-----

因此,这里有一个示例单元格类-全部通过代码,因此没有Storyboard或@IBOutlet连接:

class StackHoursCell: UITableViewCell {
    static let identifier: String = "StackHoursCell"
    
    let daysFont: UIFont = .systemFont(ofSize: 15.0, weight: .regular)
    let hoursFont: UIFont = .systemFont(ofSize: 15.0, weight: .regular)
    
    let outerStackView: UIStackView = {
        let v = UIStackView()
        v.axis = .vertical
        v.spacing = 8
        return v
    }()
    
    var dayNames: [String] = [
        "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"
    ]
    
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        commonInit()
    }
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        commonInit()
    }
    func commonInit() {
        // we want to get the longest "day string" so we can align the time "column"
        //  we could use "Wednesday" but let's assume we may localize the app and
        //  "Wednesday" may not be the longest string
        
        // we could try German for example where "Donnerstag" ("Thursday") will be the longest
        //var calendar = Calendar.current
        //calendar.locale = Locale(identifier: "de_DE")
        //dayNames = calendar.weekdaySymbols
        
        var maxDayWidth: CGFloat = 0
        let v = UILabel()
        v.font = hoursFont
        dayNames.forEach { sDay in
            v.text = sDay
            v.sizeToFit()
            maxDayWidth = max(maxDayWidth, v.frame.width)
        }
        
        // fill the vertical stack view with 7 "rows"
        //  - horizontal stack views, each with Day name and Hours labels as arranged subviews
        for _ in 1...7 {
            let rowStack = UIStackView()
            rowStack.alignment = .top
            // "padding" so we have space to the time column
            rowStack.spacing = 32.0
            // day name label
            let v1 = UILabel()
            v1.font = daysFont
            v1.widthAnchor.constraint(equalToConstant: maxDayWidth).isActive = true
            // hours label
            let v2 = UILabel()
            v2.font = hoursFont
            v2.numberOfLines = 0
            v2.setContentHuggingPriority(.required, for: .vertical)
            v2.setContentCompressionResistancePriority(.required, for: .vertical)
            rowStack.addArrangedSubview(v1)
            rowStack.addArrangedSubview(v2)
            outerStackView.addArrangedSubview(rowStack)
            
            // during development, so we can see the label frames
            //[v1, v2].forEach { v in
            //  v.backgroundColor = .yellow
            //}
        }
        
        outerStackView.translatesAutoresizingMaskIntoConstraints = false
        contentView.addSubview(outerStackView)
        
        let g = contentView.layoutMarginsGuide
        NSLayoutConstraint.activate([
            // constrain outerStackView to the layoutMarginsGuid, with some
            //  left / top / bottom padding -- adjust to suit
            outerStackView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 24.0),
            outerStackView.topAnchor.constraint(equalTo: g.topAnchor, constant: 8.0),
            outerStackView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),
            outerStackView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: -8.0),
        ])
    }
    
    public func fillTheData(_ venue: VenueStruct) {
        var str: String = ""
        var row: Int = 0
        for (d, a) in zip(dayNames, venue.hoursArray) {
            // always safely unwrap optionals
            if let rowStack = outerStackView.arrangedSubviews[row] as? UIStackView {
                if let v1 = rowStack.arrangedSubviews[0] as? UILabel,
                   let v2 = rowStack.arrangedSubviews[1] as? UILabel {
                    v1.text = d
                    str = ""
                    a.forEach { hStr in
                        str += hStr
                        if hStr != a.last {
                            str += "\n"
                        }
                    }
                    v2.text = str
                }
            }
            row += 1
        }
    }
    
}

一个简单的样本数据类,用于生成一些样本值:

class SampleVenueData: NSObject {

    // various hours strings... just to make it easier
    //  to generate some sample data
    func hoursString(_ s: String) -> String {
        var str = ""
        switch s {
        case "11to10":
            str = "11:00 am - 10:00 pm"
        case "7to11":
            str = "7:00 am - 11:00 am"
        case "12to10":
            str = "12:00 pm - 10:00 pm"
        case "10to10":
            str = "10:00 am - 10:00 pm"
        case "12to4":
            str = "12:00 pm - 4:00 pm"
        case "5to10":
            str = "5:00 pm - 10:00 pm"
        default:
            str = "24 Hours"
        }
        return str
    }

    func sampleData() -> [VenueStruct] {
        
        var venueData: [VenueStruct] = []
        
        // some sample data
        var v: VenueStruct!
        
        v = VenueStruct()
        v.hoursArray = []
        for _ in 0..<7 {
            v.hoursArray.append([hoursString("11to10")])
        }
        venueData.append(v)
        
        v = VenueStruct()
        v.hoursArray = []
        
        v.hoursArray.append([hoursString("7to11"), hoursString("12to10")])
        v.hoursArray.append([hoursString("10to10")])
        v.hoursArray.append([hoursString("7to11"), hoursString("12to10")])
        v.hoursArray.append([hoursString("10to10")])
        v.hoursArray.append([hoursString("10to10")])
        v.hoursArray.append([hoursString("10to10")])
        v.hoursArray.append([hoursString("10to10")])
        
        venueData.append(v)
        
        v = VenueStruct()
        v.hoursArray = []
        
        v.hoursArray.append([hoursString("7to11"), hoursString("12to4"), hoursString("5to10")])
        v.hoursArray.append([hoursString("10to10")])
        v.hoursArray.append([hoursString("7to11"), hoursString("12to4"), hoursString("5to10")])
        v.hoursArray.append([hoursString("10to10")])
        v.hoursArray.append([hoursString("10to10")])
        v.hoursArray.append([hoursString("10to10")])
        v.hoursArray.append([hoursString("10to10")])
        
        venueData.append(v)

        v = VenueStruct()
        v.hoursArray = []
        
        v.hoursArray.append([hoursString("7to11"), hoursString("5to10")])
        v.hoursArray.append([hoursString("7to11"), hoursString("5to10")])
        v.hoursArray.append([hoursString("7to11"), hoursString("12to4"), hoursString("5to10")])
        v.hoursArray.append([hoursString("7to11"), hoursString("5to10")])
        v.hoursArray.append([hoursString("7to11"), hoursString("12to4"), hoursString("5to10")])
        v.hoursArray.append([hoursString("10to10")])
        v.hoursArray.append([hoursString("10to10")])
        
        venueData.append(v)
        
        // replicate it a few times to confirm scrolling works
        venueData.append(contentsOf: venueData)
        venueData.append(contentsOf: venueData)

        return venueData
    }
    
}

以及样本视图控制器:

class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
    
    var myData: [VenueStruct] = []
    
    let tableView = UITableView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        tableView.translatesAutoresizingMaskIntoConstraints = false
        view.addSubview(tableView)
        
        let g = view.safeAreaLayoutGuide
        NSLayoutConstraint.activate([
            tableView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 0.0),
            tableView.topAnchor.constraint(equalTo: g.topAnchor, constant: 0.0),
            tableView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: 0.0),
            tableView.bottomAnchor.constraint(equalTo: g.bottomAnchor, constant: 0.0),
        ])
        
        tableView.register(StackHoursCell.self, forCellReuseIdentifier: StackHoursCell.identifier)
        
        tableView.dataSource = self
        tableView.delegate = self
        
        // let's get some sample data
        myData = SampleVenueData().sampleData()
        
        myData.forEach { v in
            v.hoursArray.forEach { h in
                print(h)
            }
            print("-----")
        }
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return myData.count
    }
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let c = tableView.dequeueReusableCell(withIdentifier: StackHoursCell.identifier, for: indexPath) as! StackHoursCell
        c.fillTheData(myData[indexPath.row])
        return c
    }
    
}

相关问题