Typecasting with variable - swift

I have an enum that will indicate the identifier and class to use for a tableViewCell.
enum Settings: String {
case Delete = "deleteCell"
var cellType: UITableViewCell.Type {
switch self {
case .Delete: return DeleteCell.self
}
}
}
In my tableView rowForIndexPath I am able to get the cell with the reuseIdendifyer, but it won't recognize the setting object to get the class. The error here is Use of undeclared type 'setting', specifically on the end of the line.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let setting = Settings.enabledSettings[indexPath.row]
return tableView.dequeueReusableCell(withIdentifier: setting.rawValue, for: indexPath) as! setting.cellType
}
It's not bad now with just the one object, but this will be growing soon and it's mostly the same thing, just changing the class name. Is it possible to pull the class type from another source like this so I can keep the rowForIndexPath function short and sweet, or do I need to do something like this?
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let setting = Settings.enabledSettings[indexPath.row]
var cell = tableView.dequeueReusableCell(withIdentifier: setting.rawValue, for: indexPath)
if setting == .Delete { cell = cell as! DeleteCell }
return cell
}

Related

Crash: Attempted to dequeue multiple cells for the same index path, which is not allowed

I have tableview datasource func to build a cell from a factory method function.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
return OWTableViewOrganizer.instance.configureCell(at: indexPath)!
}
The factory method is here:
func configureCell(at indexPath: IndexPath) -> UITableViewCell? {
var cell = UITableViewCell()
switch indexPath.section {
case thisWorkoutSections.barbel.sectionNumber():
cell = barebellCell(indexPath: indexPath)
break
case thisWorkoutSections.lastWorkout.sectionNumber():
cell = lastWorkoutCell(indexPath: indexPath)
break
case thisWorkoutSections.personalRecord.sectionNumber():
cell = personalRecordCell(indexPath: indexPath)
break
case thisWorkoutSections.notes.sectionNumber():
break
default:
break
}
return cell
}
I have this code to build the cell:
func lastWorkoutCell(indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: WorkoutSetTableViewCell.cellIdentifier(), for: indexPath) as! WorkoutSetTableViewCell
if OWTableViewOrganizer.instance.lastWorkoutExerciseSets.count > 0 {
if indexPath.row < OWTableViewOrganizer.instance.lastWorkoutExerciseSets.count {
let logExerciseSet = OWTableViewOrganizer.instance.lastWorkoutExerciseSets[indexPath.row]
let setNumber = indexPath.row + 1
if let weight = logExerciseSet.weight?.doubleValue, let reps = logExerciseSet.reps?.intValue {
cell.setupCellWithData(setNumber: setNumber, weight: weight, reps: reps)
}
} else {
cell.setupCellWithData(setNumber: -1, weight: 0, reps: 0)
}
} else {
cell.setupCellWithData(setNumber: -1, weight: 0, reps: 0)
}
return cell
}
But time to time this line crashes for me:
let cell = tableView.dequeueReusableCell(withIdentifier: WorkoutSetTableViewCell.cellIdentifier(), for: indexPath) as! WorkoutSetTableViewCell
With error:
Attempted to dequeue multiple cells for the same index path, which is not allowed. If you really need to dequeue more cells than the table view is requesting, use the -dequeueReusableCellWithIdentifier: method (without an index path)
I know code style and design is not ideal here, please skip this if you have comments.
I don't know where to look, I tried simply remove indexPath, but it looks does not help or bring even more issues:
let cell = tableView.dequeueReusableCell(withIdentifier: WorkoutSetTableViewCell.cellIdentifier()) as! WorkoutSetTableViewCell
I have one controller which presents another one at the top of it (like in Apple music) and I can swipe down to show bottom controller and swipe up to bring back top controller. I noticed in log that I have some presentation alert, not sure if this something I need to deal with to resolve the issue above but JFY info.
It seems like there are two table view trigger
tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
and you only dequeue cell from 1 table view at
let cell = tableView.dequeueReusableCell(withIdentifier: WorkoutSetTableViewCell.cellIdentifier(), for: indexPath) as! WorkoutSetTableViewCell
You should try to pass tableView from
tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
to
lastWorkoutCell(indexPath: IndexPath)
(which will become lastWorkoutCell(indexPath: IndexPath, tableView: UITableView)) and dequeue cell from tableView

Swift Newbie Argument labels '(_:, IndexPath:)' do not match any available overloads

When I call the tableView function I get the error in the title. My question is why won't the function take the two arguments even though they are of the requested type? Again I'm a newbie so please forgive me if the answer is obvious.
class TableViewController: UITableViewController {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "itemCell") as! UITableViewCell
let name = Array(shopItems.keys) [indexPath.row]
let cost = Array(shopItems.values) [indexPath.row]
cell.textLabel?.text = name + String(cost)
return cell
}
}
When I call the function like this:
"TableViewController.tableView(shopTableView, IndexPath: NSIndexPath)" I get the error: "Argument labels '(_:, IndexPath:)' do not match any available overloads"
Try use
let name = shopItems.keys[indexPath.row]
Instead of
let name = Array(shopItems.keys) [indexPath.row]
Better don't use force wrap, when it's not nesesery.
Try change
let cell = tableView.dequeueReusableCell(withIdentifier: "itemCell") as! UITableViewCell
to
guard let cell = tableView.dequeueReusableCell(withIdentifier: "itemCell") as? UITableViewCell else {
return UITableViewCell()
}
EDIT: As #Sh_Khan say replace
func tableView(_ tableView: UITableView, cellForRowAt indexPath: NSIndexPath) -> UITableViewCell {
to
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
There is an easy and quick way to figure out yourself the proper overload
Select the entire method and press ⌘/ to comment out the code.
On the top level of the class type cellForRow. The first item in the code completion list is the proper method.
Press Return to insert the correct method.
Comment in the wrong method by selecting it again and pressing ⌘/.
Copy and paste the body of the wrong method into the correct one.
Delete the rest of the wrong method.

Remove index from sidemenu user type wise

I have implemented side menu in tableview and now my scenario is like, I have to manage sidemenu options as user types
Let me show my code
var items = ["Social Media Post", "Messages", "Manage User","My Account","Information","Logout"]
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! MenuTableViewCell
cell.lblTitle.text = items[indexPath.row]
cell.imgMenuLogo.image = image[indexPath.row]
print(User_type)
if User_type == 2{
items.remove(at: 0)
}
return cell
}
but now i want . to de like this
if user_type == "3"{
// Social Media , Messages And Manage User options i want to remove
}
I am not able to understand how to remove from index.
Try something like this:
override func viewDidLoad() {
super.viewDidLoad()
getList()
}
func getList(){
switch userType{
case 0:
items = ["UserTypeOne_Home","UserType_One Settings","etc"]
break
case 1:
items = ["UserTypeTwo_Home","UserType_Two Settings","etc"]
break
default:
break
}
self.tableView.reloadData()
}
extension ViewController: UITableViewDelegate,UITableViewDataSource{
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "Some ID")
cell?.textLabel?.text = items[indexPath.row]
return cell!
}
}
Try not to change the array from within the cellForRowAt indexPath method using indexPath.row, that will not give you the result you want. Modulate the array from outside the protocol method overrides, and just call the reloadData() method.
Try to use enum of UserType and check type of current user than Make an array with default options available to every user and then append specific data in array according to user type. Hope it clarifies :)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell") as! MenuTableViewCell
cell.lblTitle.text = items[indexPath.row]
cell.imgMenuLogo.image = image[indexPath.row]
print(User_type)
if User_type == 2{
items.remove(at: 0)
}
return cell
}
This will work, But you have done a small mistake here.
You have removed from array after setting label. So you need to remove the item from array first then do set label.
Btw, I will not recommend this method as you need to add/remove from array for every cellForRowAt method.

Create object that conform to protocol in Swift

I want to create cell that i know, is conformable to specific protocol.
However, when i try to do :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell<ModelBinding> = tableView.dequeueReusableCell(withIdentifier: "VacanciesCell", for: indexPath as IndexPath)
return cell
}
I got an error. How to fix it?
You have to subclass cell , which confirms the protocol that you want to use. Here i have created a sample protocol and CustomCell which confirming the protocol i have created.
1. Sample protocol
protocol MyProtocol {
func protocolMethod()
}
2. Custom subClassed cell
class CustomCell:UITableViewCell,MyProtocol {
//Implementation of Protol method
func protocolMethod() {
}
}
3. Use of that cell on tableview
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:CustomCell = tableView.dequeueReusableCell(withIdentifier: "VacanciesCell", for: indexPath as IndexPath) as! CustomCell
return cell
}

Use of undeclared type 'ContactsTableViewCell'

I am working on to fetch phone contacts. But I got an error like use of undeclared type ContactsTableViewCell. I tried UITableViewCell but it didn't work. What should I do ?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCell(withIdentifier: "TableCell", for: indexPath) as! ContactsTableViewCell
let data = dataArray![indexPath.row] as! Data;
cell.lblName.text = data.name
cell.imgContact.image = data.image
return cell
}
First you should make a class named ContactsTableViewCell which inherit UITableViewCell or if you already created it be sure you added this class to your targets.