Reputation: 5896
How can I cast an object using a type (stored in a parameter)?
Example:
Let's assume I have a simple enum
like so:
enum SettingsAction {
case contactUs
var cellType: UITableViewCell.Type {
return TitleSettingsTableViewCell.self
}
}
And then I'm trying to create an object with cellType
, like so:
let settingsAction = SettingsAction.contactUs
let cellType = settingsAction.cellType
let cell = tableView.dequeueReusableCell(withIdentifier: "\(cellType)", for: indexPath) as! cellType
I'm getting the following error:
Cannot find type 'cellType' in scope
Seems like it's impossible to use a parameter to cast, resulting in some weird pre-complier error.
Is there a right way to achieve what I'm trying?
Upvotes: 1
Views: 165
Reputation: 10112
Try something like this -
enum SettingsAction {
case contactUs
func cellForRow(at indexPath: IndexPath, in tableView: UITableView) -> UITableViewCell {
switch self {
case .contactUs:
return tableView.dequeueReusableCell(withIdentifier: "TitleSettingsTableViewCell", for: indexPath) as! TitleSettingsTableViewCell
}
}
}
Update
Swift won't allow you to work with Type
information stored in a variable that's only available at runtime. This information is needed at compile time for the type inference.
You have to give up flexibility in one way or another.
Here's another attempt at solving the same problem - far from ideal - it does work as needed for this use case.
class UserInfoTableViewCell: UITableViewCell {
var userProperty: Bool = false
}
class ContactUsTableViewCell: UITableViewCell {
var contactProperty: Bool = false
}
class LegalTableViewCell: UITableViewCell {
var legalProperty: Bool = false
}
class SettingsCellCreator<T: UITableViewCell> {
func cellForRow(at indexPath: IndexPath, in tableView: UITableView) -> T {
tableView.dequeueReusableCell(withIdentifier: "\(T.self)", for: indexPath) as! T
}
}
private let userInfoCellCreator = SettingsCellCreator<UserInfoTableViewCell>()
private let contactUsCellCreator = SettingsCellCreator<ContactUsTableViewCell>()
private let legalCellCreator = SettingsCellCreator<LegalTableViewCell>()
class ViewController: UIViewController, UITableViewDataSource {
enum CellType {
case userInfo
case contactUs
case legal
}
private var rows: [CellType] = [
.userInfo,
.contactUs,
.contactUs,
.legal,
.legal
]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
rows.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch rows[indexPath.row] {
case .userInfo:
let cell = userInfoCellCreator.cellForRow(at: indexPath, in: tableView)
cell.userProperty = true
return cell
case .contactUs:
let cell = contactUsCellCreator.cellForRow(at: indexPath, in: tableView)
cell.contactProperty = true
return cell
case .legal:
let cell = legalCellCreator.cellForRow(at: indexPath, in: tableView)
cell.legalProperty = true
return cell
}
}
}
Upvotes: 1
Reputation: 9925
In Swift the right side of downcasting as
and type checking is
operators must be given in place of use of those operators.
So, it's impossible to cast or type check an object using a meta type stored or computed.
Upvotes: 1