提问人:cg1000 提问时间:6/10/2023 最后编辑:cg1000 更新时间:6/13/2023 访问量:74
声明变量后,如何根据 if 和 else-if 语句更改自定义单元格变量的分配?迅速
How to go about changing the assignment of a custom cell variable based on if and else-if statements after the variable is declared? Swift
问:
我正在尝试使用一个自定义单元格,在声明变量后,该单元格的变量赋值会根据 和 语句进行更改。if
else-if
这是为了让显示所选业务的营业时间的自定义单元格能够选择适合我想为该业务显示的一周的开放和关闭时间范围对的数量(因为某些企业在一天内有多个)。custom table view cell
但是,我不断收到一条错误消息,说:
""Cannot assign value of type 'DetailsHoursContentsForAtLeastOneDayWithTwoOpenCloseTimeRangePairsTableViewCell' to type ‘DetailsHoursContentsForAllDaysWithOneOpenCloseTimeRangePairTableViewCell'
在这行代码中:
detailsHoursContentsCustomCell = scrollableCitiesRestaurantDetailsTableView.dequeueReusableCell(withIdentifier: "DetailsHoursContentsForAtLeastOneDayWithTwoOpenCloseTimeRangePairsTableViewCell", for: indexPath) as! DetailsHoursContentsForAtLeastOneDayWithTwoOpenCloseTimeRangePairsTableViewCell
这是第一个语句的条件语句中的代码行,它更改了我正在使用的自定义单元格变量的变量赋值。这行代码上方有一个注释,其中包含在本文下方的代码片段中得到的错误消息。在此语句之前的条件语句将该值设置为与自定义单元格变量开始时的值相同的值,并且不会在其条件语句中获取此类型的错误消息或任何类型的错误消息。else-if
if-statement
else-if
我在其他语句的条件语句中也收到相同的错误消息,其中自定义单元格变量值已更改。这些代码行上方还有注释,说明在下面的代码片段中为该特定代码行收到的错误消息。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(AllDaysWithOneTimeRangeTableViewCell)
答:
在没有看到你的UI设计的情况下,我假设:
- 各种单元格类型都有一些“通用”的 UI 元素
- 差异与营业时间有关?
您可能可以使用单个单元格设计,然后根据需要显示/隐藏不同的 UI 元素。
例如:
该图像显示了 3 个不同的原型单元。
但是,底部单元格在垂直方向上有 3 个“行”。我们可以通过隐藏第 2 行和第 3 行并设置黄色和青色标签文本来轻松地将其转换为第一个单元格。UIStackView
如果你觉得你的布局/设计太复杂,并且你想坚持使用多个单元原型,那么我建议让单元类处理解析数据......
因此,每个单元格都可以具有如下功能:
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
}
据推测,每种单元格类型都会设置不同的 labels.text。
那么你的样子是这样的: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]] = []
}
示例 s - 当填充数据时:hoursArray
["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
}
}
评论
switch
Could not load NIB in bundle: 'NSBundle </Users/ etc… [Project Name].app> (loaded)' with name ‘DetailsHoursContentsForAtLeastOneDayWithGreaterThanThreeOpenCloseTimeRangePairsTableViewCell