How to make tableView(cellForRowAtIndexPath) with multiple UITableViewCell readable? - ios

I have UITableView with multiple UITableViewCell, every cell have a different design and high, the problem I have that now the method tableView(cellForRowAtIndexPath) look so weird and unreadable and I don't know if this is the true and the good practice implementation for the case.
My method :
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if(indexPath.section == 0){ // linked news item
let cellIdentifier = "linkedNewsTableViewCell";
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! LinkedNewsTableViewCell;
let linked_news = LinkedNews[indexPath.row];
cell.newTitle.text = linked_news.news_title;
return cell;
}else if(indexPath.section > 1 && indexPath.row == 0 && indexPath.section != sections.count+2){ // section header item
let cellIdentifier = "sectionHeaderTableViewCell";
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! SectionHeaderTableViewCell;
let sec = sections[indexPath.section-2];
cell.lblSectionTitle.text = sec.section_name;
cell.backgroundColor = Constants.Colors.lightGray;
return cell;
}else if(indexPath.section == 2+sections.count){ // all rights reserved item
let cellIdentifier = "allRightsReservedTableViewCell";
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! AllRightsReservedTableViewCell;
cell.backgroundColor = Constants.Colors.lightGray;
return cell;
}else if(indexPath.section == 1){ // slider news item
let cellIdentifier = "newsTableViewCell";
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! NewsTableViewCell;
cell.imgVideo.hidden = true;
let newsItem = SliderNews[indexPath.row];
cell.txtNews.text = newsItem.news_title;
cell.lblTime.text = Utilities.timeAgoSinceDate(NSDate(timeIntervalSince1970:newsItem.createdstamp!), numericDates: false);
do{
let isSaved = try DBManger.sharedInstance.isSaved(String(newsItem.news_id!));
cell.isSaved = isSaved;
cell.news = newsItem;
if(isSaved == true){
cell.btnSave.setImage(UIImage(named: "ic_bookmark_blue"), forState: .Normal);
}else{
cell.btnSave.setImage(UIImage(named: "ic_bookmark"), forState: .Normal);
}
}catch{
}
if(SliderNews.count-1 == indexPath.row){
cell.buttomLine.hidden = true;
}else{
cell.buttomLine.hidden = false;
}
let image = cell.imgNews.getImage(newsItem.image!, timestamp: String(newsItem.createdstamp!), size: "228", qualty: "70");
cell.imgNews.loadImage(image,contentMode: .ScaleToFill)
cell.lblType.text = newsItem.section_name;
cell.backgroundColor = Constants.Colors.lightGray;
return cell;
}else{ // section news item
let sec = sections[indexPath.section-2];
if(indexPath.row == sec.news.count+1){
let cellIdentifier = "moreNewsTableViewCell";
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! MoreNewsTableViewCell;
cell.lblSectionName.text = "المزيد من \(sec.section_name!)";
cell.backgroundColor = Constants.Colors.lightGray;
return cell;
}
let cellIdentifier = "newsTableViewCell";
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! NewsTableViewCell;
cell.imgVideo.hidden = true;
let newsItem = sec.news[indexPath.row-1];
cell.txtNews.text = newsItem.news_title;
cell.lblTime.text = Utilities.timeAgoSinceDate(NSDate(timeIntervalSince1970:newsItem.createdstamp!), numericDates: false);
cell.lblType.text = sec.section_name;
if(sec.news.count == indexPath.row){
cell.buttomLine.hidden = true;
}else{
cell.buttomLine.hidden = false;
}
let image = cell.imgNews.getImage(newsItem.image!, timestamp: String(newsItem.createdstamp!), size: "228", qualty: "70");
cell.imgNews.loadImage(image,contentMode: .ScaleToFill)
cell.backgroundColor = Constants.Colors.lightGray;
do{
let isSaved = try DBManger.sharedInstance.isSaved(String(newsItem.news_id!));
cell.isSaved = isSaved;
cell.news = newsItem;
if(isSaved == true){
cell.btnSave.setImage(UIImage(named: "ic_bookmark_blue"), forState: .Normal);
}else{
cell.btnSave.setImage(UIImage(named: "ic_bookmark"), forState: .Normal);
}
}catch{
}
return cell;
}
}

After playing around with your code, you have a few issues thats needs to be resolved before the code can look much better:
1. You need a model that reflects your tableView data source , it should look something like:
let currentSectionModel = self.sections[indexPath.section]
let currentRowModel = currentSectionModel[]
and then you can use something more generic with your cells to set the model object:
cell.setRowModel(currentRowModel)
2. Your if statements that decides witch section to present, are very complicated,
for example this line:
if indexPath.section > 1 && indexPath.row == 0 && indexPath.section != sections.count+2 {
You have to find a better logic for this. Once you orgenize the model like I sad in section 1, This should look much more clear and you can change it to a switch statement, that questions an enum.
3. All cell logic, I prefer to do Inside the cell itself, for cleaner viewController, I've done so at the example code at the end.
4. Don't use strings for identifier, It can cause bugs. that's the reason I prefer to use an extension on UITableViewCell witch returns the class name as the identifier.
5. Don't use semi columns is swift.
6. All your cells should have a base class, that way you can use polymorphism when returning cells.
7. Once you have a model that represent the data source, you can use Switch statement instead of if statement.
This is the example code I've written, you have to work on your code a bit before it will compile. I'ts just a better practice example. (I didn't use switch statements only because your cases are too complexed to use a simple enum. Like I sad, I'ts something you have to work on, and make it more simple)
class BaseCellType: UITableViewCell {
}
class AllRightsReservedTableViewCell: BaseCellType {
// Your implementation
}
class LinkedNewsTableViewCell: BaseCellType {
func setLinkedNews(linedNews: LinkedNews) {
// Your implementation
}
}
class SectionHeaderTableViewCell: BaseCellType {
func setSectionModel(sectionModel: SectionModel) {
// Your implementation
}
}
class MoreNewsTableViewCell: BaseCellType {
func setSection(section: SectionModel) {
// Your implementation
}
}
class NewsTableViewCell: BaseCellType {
// Your implementation
}
class SectionsModel {
let rows: [RowModel]
}
extension UITableViewCell {
static var cellIdentifer: String {
get {
return String(self.dynamicType).componentsSeparatedByString("__").last!
}
}
}
enum SectionType: Int {
case AllRightsReserevedSection = 1, LinkedNewItem = 0
}
class ViewController: UIViewController {
var sections: [SectionsModel]!
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: BaseCellType
switch (section: indexPath.section,row: indexPath.row) {
case (SectionType.AllRightsReserevedSection.rawValue, _):
cell = tableView.dequeueReusableCellWithIdentifier(AllRightsReservedTableViewCell.cellIdentifer, forIndexPath: indexPath) as! AllRightsReservedTableViewCell;
case (SectionType.LinkedNewItem.rawValue, _):
cell = tableView.dequeueReusableCellWithIdentifier(LinkedNewsTableViewCell.cellIdentifer, forIndexPath: indexPath) as! LinkedNewsTableViewCell;
cell.setLinkedNews(LinkedNews[indexPath.row])
case let index where index.section > 1 , index.row == 0, index.section != secrion+2:
cell = tableView.dequeueReusableCellWithIdentifier(SectionHeaderTableViewCell.cellIdentifer, forIndexPath: indexPath) as! SectionHeaderTableViewCell
cell.setSectionModel(sections[indexPath.section-2])
case let index where index.section == section.count + 2:
cell = tableView.dequeueReusableCellWithIdentifier(AllRightsReservedTableViewCell.cellIdentifer, forIndexPath: indexPath) as! AllRightsReservedTableViewCell;
case let index where index.row == (sec.news.count + 1) :
cell = tableView.dequeueReusableCellWithIdentifier(MoreNewsTableViewCell.cellIdentifer, forIndexPath: indexPath) as! MoreNewsTableViewCell;
cell.setSection(sections[indexPath.section-2])
default:
cell = tableView.dequeueReusableCellWithIdentifier(NewsTableViewCell.cellIdentifer, forIndexPath: indexPath) as! NewsTableViewCell;
cell.setNewsItem(sec.news[indexPath.row-1])
}
}
return cell
}

Try this one
func makeBasicTableCell(title:String,details:String,indexPath:NSIndexPath) -> CustomHeaderCell{
let cell = tableProfile.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as! CustomHeaderCell
cell.titleLable.text = title
cell.detLable.text = details
return cell
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
var tblCell: UITableViewCell!
tableView.registerNib(UINib(nibName: "profile_details", bundle: nil), forCellReuseIdentifier: "cell")
if indexPath.section == 0 {
switch(indexPath.row) {
case 0:
return makeBasicTableCell("Text1", details: "TextDetail1", indexPath: indexPath)
case 1:
return makeBasicTableCell("Text2", details: "TextDetail2", indexPath: indexPath)
case 2:
return makeBasicTableCell("Text3", details: "TextDetail3", indexPath: indexPath)
case 3:
return makeBasicTableCell("Text4", details: "TextDetail4", indexPath: indexPath)
default:
return makeBasicTableCell("", details: "", indexPath: indexPath)
}
} else if indexPath.section == 1 {
switch(indexPath.row) {
case 0:
return makeBasicTableCell("Text5", details: "TextDetail5", indexPath: indexPath)
case 1:
return makeBasicTableCell("Text6", details: "TextDetail6", indexPath: indexPath)
case 2:
return makeBasicTableCell("Text7", details: "TextDetail7", indexPath: indexPath)
default:
return makeBasicTableCell("", details: "", indexPath: indexPath)
}
}
return tblCell
}

In your cellForRowAtIndexPath -> *Objective-C
if(your first condition){
static NSString *cellIdentifier = #"cell";
MANewsCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
tableView.rowHeight=30;
}else if(second condition ){
static NSString *cellIdentifier = #"cell1";
MANewsCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
tableView.rowHeight=40;
}else
{
static NSString *cellIdentifier = #"cell2";
MANewsCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier forIndexPath:indexPath];
tableView.rowHeight=50;
}
I hope I help you.

Related

Multiple implementation of custom uitableviewcell using dynamic prototype cells

Three different, dynamic prototype tableviewcells are used in my project.
Two are stock cells(basic with different options), and one is a custom cell. And this, may change as required.
The problem I face is while dequeuing the cells.
If they are done normally as UITableViewCells, I'm not able to use my custom cell outlets or actions.
let cell = tableView.dequeueReusableCellWithIdentifier(identifier, forIndexPath: indexPath)
And, If they are done the other way, the app crashes with the below error.
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! SwitchTableViewCell
Error:
Could not cast value of type 'UITableViewCell' (0x38595c58) to 'AppName.SwitchTableViewCell' (0x13cdf8).
Below is the implementation of cellForRowAtIndexPath method,
// MARK: - UITableViewDelegate Methods
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Setup a cellIdentifer string to store the cell reuse identifier you want to use for each row.
var cellIdentifier: String
// Switch through each row and set the appropriate cell reuse identifier
switch sections[indexPath.section].items[indexPath.row] {
case .AudioDevices, .Acknowledgments:
cellIdentifier = "DisclosureCell"
case .AllowNotifications, .ShowCloudMusic:
cellIdentifier = "SwitchCell"
case .Version:
cellIdentifier = "RightDetailCell"
}
// Populate your cell reuse identifier into the cell
if cellIdentifier == "SwitchCell" {
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! SwitchTableViewCell
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath)
return cell
}
// Switch through each cell, and implement the labels/setup for each row
// The order of the cases is irrelevant!
switch sections[indexPath.section].items[indexPath.row] {
case .AudioDevices:
cell.textLabel?.text = "Audio Devices"
cell.detailTextLabel?.text = String(userDefaults.integerForKey(audioDeviceListKey))
case .AllowNotifications:
cell.switchCellLabel?.text = "Allow Notifications"
cell.userInteractionEnabled = false
case .ShowCloudMusic:
cell.switchCellLabel?.text = "Show Cloud Music"
case .Acknowledgments:
cell.textLabel?.text = "Acknowledgements"
cell.detailTextLabel?.text = ""
case .Version:
cell.textLabel?.text = "Version"
cell.detailTextLabel?.text = buildVersion
cell.detailTextLabel?.textColor = UIColor.lightGrayColor()
cell.userInteractionEnabled = false
}
// Return the cell
return cell
}
Screenshot:
To use multiple kinds of cell in Table View, you have to put some condition to check to see which cell be used for certain condition.
func tableView cellForRowAtInd....... {
//depends on what base you separate both cells
if condition = true {
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! SwitchTableViewCell
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier(identifier, forIndexPath: indexPath)
return cell
}
}
Update based upon your cellForRowAtIndexPath code:
You are already returning before cell before your other part of code run. Hence the cell is already returned and its of no use for other part of code.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// Setup a cellIdentifer string to store the cell reuse identifier you want to use for each row.
var cellIdentifier: String
// Switch through each row and set the appropriate cell reuse identifier
switch sections[indexPath.section].items[indexPath.row] {
case .AudioDevices, .Acknowledgments:
cellIdentifier = "DisclosureCell"
case .AllowNotifications, .ShowCloudMusic:
cellIdentifier = "SwitchCell"
case .Version:
cellIdentifier = "RightDetailCell"
}
// Populate your cell reuse identifier into the cell
if cellIdentifier == "SwitchCell" {
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! SwitchTableViewCell
// Switch through each cell, and implement the labels/setup for each row
// The order of the cases is irrelevant!
switch sections[indexPath.section].items[indexPath.row] {
case .AudioDevices:
cell.textLabel?.text = "Audio Devices"
cell.detailTextLabel?.text = String(userDefaults.integerForKey(audioDeviceListKey))
case .AllowNotifications:
cell.switchCellLabel?.text = "Allow Notifications"
cell.userInteractionEnabled = false
case .ShowCloudMusic:
cell.switchCellLabel?.text = "Show Cloud Music"
case .Acknowledgments:
cell.textLabel?.text = "Acknowledgements"
cell.detailTextLabel?.text = ""
case .Version:
cell.textLabel?.text = "Version"
cell.detailTextLabel?.text = buildVersion
cell.detailTextLabel?.textColor = UIColor.lightGrayColor()
cell.userInteractionEnabled = false
}
// Return the cell
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath)
// Switch through each cell, and implement the labels/setup for each row
// The order of the cases is irrelevant!
switch sections[indexPath.section].items[indexPath.row] {
case .AudioDevices:
cell.textLabel?.text = "Audio Devices"
cell.detailTextLabel?.text = String(userDefaults.integerForKey(audioDeviceListKey))
case .AllowNotifications:
cell.switchCellLabel?.text = "Allow Notifications"
cell.userInteractionEnabled = false
case .ShowCloudMusic:
cell.switchCellLabel?.text = "Show Cloud Music"
case .Acknowledgments:
cell.textLabel?.text = "Acknowledgements"
cell.detailTextLabel?.text = ""
case .Version:
cell.textLabel?.text = "Version"
cell.detailTextLabel?.text = buildVersion
cell.detailTextLabel?.textColor = UIColor.lightGrayColor()
cell.userInteractionEnabled = false
}
// Return the cell
return cell
}
}
plz use this
if cellIdentifier == "SwitchCell" {
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! SwitchTableViewCell
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath)
return cell
}
access the label with tag like this in that cell where yon not define outlets
if let theLabel = self.view.viewWithTag(123) as? UILabel {
theLabel.text = "some text"
}

How to get cells with different cell classes

I need to get the text from the textfield i.e from KgCustomCell and KgRepsCustomCell. I need to fetch the data from the field, when i run the buttonClicked method.
I have tried to add to instance variables, which contains kg and reps, but the first time i click the button, it's empty. The second time it's okay. But how can i load the data in the most correct way?
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let index = indexPath.row
if indexPath.row == 0 && indexPath.section == 0 {
let exerciseName = tableView.dequeueReusableCellWithIdentifier("Exercise Name", forIndexPath: indexPath) as! LoggedExerciseNameCell
exerciseName.lblExerciseName.text = self.exercise?.name
return exerciseName
}
if index == 0 && indexPath.section == 1 {
let txtFieldKg = tableView.dequeueReusableCellWithIdentifier("Text KG", forIndexPath: indexPath) as! KgCustomCell
return txtFieldKg
}
if index == 1 && indexPath.section == 1 {
let txtFieldReps = tableView.dequeueReusableCellWithIdentifier("Text Reps", forIndexPath: indexPath) as! KgRepsCustomCell
//kg = txtFieldReps.textReps.text
return txtFieldReps
}
if index == 2 && indexPath.section == 1 {
let btnLog = tableView.dequeueReusableCellWithIdentifier("Button Log", forIndexPath: indexPath) as! ButtonLogWorkoutCustomCell
btnLog.btnLogExercise.addTarget(self, action: #selector(AddLogViewController.buttonClicked(_:)), forControlEvents: UIControlEvents.TouchUpInside)
// kg = txtFieldReps.textReps.text
return btnLog
}
if indexPath.section == 2 {
let loggedExerciseInformation = tableView.dequeueReusableCellWithIdentifier("Logged Exercise", forIndexPath: indexPath) as! LoggedExerciseCustomCell
return loggedExerciseInformation
}
let noCell = tableView.dequeueReusableCellWithIdentifier("Button Log", forIndexPath: indexPath)
return noCell
}
func buttonClicked(sender:UIButton) {
let button = sender as UIButton
if let superview = button.superview {
if (superview.superview as? ButtonLogWorkoutCustomCell) != nil {
try! LogManagerDAO.sharedInstance.realm.write({
exercise?.loggedKg = 4//Int(txtKG.text!)!
exercise?.loggedReps = 4//Int(txtReps.text!)!
log!.addExerciseToLog(exercise!)
loadLoggedExercise()
tableView.reloadData()
})
}
}
}
If you just want the text of that textField than you can use delegate method of UITextField like this, first declare two instance var for that 2 textField's value
var strKG: String = ""
var strReps: String = ""
Now set delegate with textField in cellForRowAtIndexPath
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let index = indexPath.row
if indexPath.row == 0 && indexPath.section == 0 {
let exerciseName = tableView.dequeueReusableCellWithIdentifier("Exercise Name", forIndexPath: indexPath) as! LoggedExerciseNameCell
exerciseName.lblExerciseName.text = self.exercise?.name
return exerciseName
}
if index == 0 && indexPath.section == 1 {
let txtFieldKg = tableView.dequeueReusableCellWithIdentifier("Text KG", forIndexPath: indexPath) as! KgCustomCell
txtFieldReps.textField.tag = index
txtFieldKg.textField.delegate = self
return txtFieldKg
}
if index == 1 && indexPath.section == 1 {
let txtFieldReps = tableView.dequeueReusableCellWithIdentifier("Text Reps", forIndexPath: indexPath) as! KgRepsCustomCell
txtFieldReps.textField.tag = index
txtFieldReps.textField.delegate = self
return txtFieldReps
}
if index == 2 && indexPath.section == 1 {
let btnLog = tableView.dequeueReusableCellWithIdentifier("Button Log", forIndexPath: indexPath) as! ButtonLogWorkoutCustomCell
btnLog.btnLogExercise.addTarget(self, action: #selector(AddLogViewController.buttonClicked(_:)), forControlEvents: UIControlEvents.TouchUpInside)
// kg = txtFieldReps.textReps.text
return btnLog
}
if indexPath.section == 2 {
let loggedExerciseInformation = tableView.dequeueReusableCellWithIdentifier("Logged Exercise", forIndexPath: indexPath) as! LoggedExerciseCustomCell
return loggedExerciseInformation
}
let noCell = tableView.dequeueReusableCellWithIdentifier("Button Log", forIndexPath: indexPath)
return noCell
}
Now add delegate method of UITextField
func textFieldDidEndEditing(textField: UITextField) {
if(textField.tag == 0) {
self.strKG = textField.text
}
else {
self.strReps = textField.text
}
}
Now just use this two string object in your button action method.

Use of unresolved identifier 'cell'

I am creating multiple UITableViews in one view controller, and i have used the following code to check for which tableView it is. I keep getting the problem "Use of unresolved identifier 'cell' in the very last line. I have tried searching for this, but there are not many which are up to date at Xcode 7. Forgive me for my lack of terminology as well as experience, for i am just starting off. Please feel free to ask me of any questions that you might encounter. Thank you all in advance who took the time to read this!
#IBOutlet var tableView1: UITableView!
#IBOutlet var tableView2: UITableView!
// Mens games Variables
var dates = ["7/23", "7/24","7/25","7/26","7/27","7/28","7/29"]
var times = ["7:30","8:00","8:30","9:00","9:30","10:00","10:30"]
var teamsOne = ["VU Reserves 1","VU Reserves 3","VU Reserves 5","VU Reserves 7","VU Reserves 9","VU Reserves 11","VU Reserves 13"]
var teamsTwo = ["VU Reserves 2","VU Reserves 4","VU Reserves 6","VU Reserves 8","VU Reserves 10","VU Reserves 12","VU Reserves 14"]
var fields = ["Turf","Field 1","Field 2","Field 3","Field 4","Field 5","Field 6"]
// Womens games Variables
var womensDates = ["7/23", "7/24","7/25","7/26","7/27","7/28","7/29"]
var womensTimes = ["7:30","8:00","8:30","9:00","9:30","10:00","10:30"]
var womensTeamsOne = ["VU Girls 1","VU Girls 3","VU Girls 5","VU Girls 7","VU Girls 9","VU Girls 11","VU Girls 13"]
var womensTeamsTwo = ["VU Girls 2","VU Girls 4","VU Girls 6","VU Girls 8","VU Girls 10","VU Girls 12","VU Girls 14"]
var womensFields = ["Turf","Field 1","Field 2","Field 3","Field 4","Field 5","Field 6"]
override func viewDidLoad() {
super.viewDidLoad()
tableView1.dataSource = self
tableView1.delegate = self
tableView1.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell1")
tableView2.dataSource = self
tableView2.delegate = self
tableView2.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell2")
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (tableView == tableView1) {
return teamsOne.count
}
else if (tableView == tableView2) {
return womensTeamsOne.count
} else{
return 0 }
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if (tableView == tableView1) {
let cell = self.tableView1.dequeueReusableCellWithIdentifier("cell1", forIndexPath: indexPath) as! gamesCustomCell
cell.date.text = dates[indexPath.row]
cell.time.text = times[indexPath.row]
cell.teamOne.text = teamsOne[indexPath.row]
cell.teamTwo.text = teamsTwo[indexPath.row]
cell.field.text = fields[indexPath.row]
return cell
} else if (tableView == tableView2) {
let cell = self.tableView2.dequeueReusableCellWithIdentifier("cell2", forIndexPath: indexPath) as! womensGamesCustomCell
cell.womensDate.text = womensDates[indexPath.row]
cell.womensTime.text = womensTimes[indexPath.row]
cell.womensTeamOne.text = womensTeamsOne[indexPath.row]
cell.womensTeamTwo.text = womensTeamsTwo[indexPath.row]
return cell
}
return cell
}
}
Just replace cellForRowAtIndexPath with below code
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell?
if (tableView == tableView1) {
cell = self.tableView1.dequeueReusableCellWithIdentifier("cell1", forIndexPath: indexPath) as! gamesCustomCell
cell.date.text = dates[indexPath.row]
cell.time.text = times[indexPath.row]
cell.teamOne.text = teamsOne[indexPath.row]
cell.teamTwo.text = teamsTwo[indexPath.row]
cell.field.text = fields[indexPath.row]
}
if (tableView == tableView2) {
cell = self.tableView2.dequeueReusableCellWithIdentifier("cell2", forIndexPath: indexPath) as! womensGamesCustomCell
cell.womensDate.text = womensDates[indexPath.row]
cell.womensTime.text = womensTimes[indexPath.row]
cell.womensTeamOne.text = womensTeamsOne[indexPath.row]
cell.womensTeamTwo.text = womensTeamsTwo[indexPath.row]
}
return cell!
}
Try this, it worked for me
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if (tableView == tableView1) {
let cell = self.tableView1.dequeueReusableCellWithIdentifier("cell1", forIndexPath: indexPath) as! gamesCustomCell
cell.date.text = dates[indexPath.row]
cell.time.text = times[indexPath.row]
cell.teamOne.text = teamsOne[indexPath.row]
cell.teamTwo.text = teamsTwo[indexPath.row]
cell.field.text = fields[indexPath.row]
return cell
} else if (tableView == tableView2) {
let cell = self.tableView2.dequeueReusableCellWithIdentifier("cell2", forIndexPath: indexPath) as! womensGamesCustomCell
cell.womensDate.text = womensDates[indexPath.row]
cell.womensTime.text = womensTimes[indexPath.row]
cell.womensTeamOne.text = womensTeamsOne[indexPath.row]
cell.womensTeamTwo.text = womensTeamsTwo[indexPath.row]
return cell
}
return UITableViewCell()
}

Better way to initialize different cell types inside an if statement

In my code, a cell will be of one type if it is in the first tableView section, and another if it is not.
var cell = UITableViewCell()
if indexPath.section == 0 {
cell = tableView.dequeueReusableCellWithIdentifier("UpcomingWorkoutCell", forIndexPath: indexPath) as! MyWorkoutsTableViewCell
cell.nameLabel.text = workout.trainer.name
cell.dateLabel.text = workout.getDateString()
cell.timeLabel.text = workout.getTimeString()
cell.trainerImage.image = workout.image
} else {
cell = tableView.dequeueReusableCellWithIdentifier("PastWorkoutCell", forIndexPath: indexPath) as! PastWorkoutTableViewCell
cell.nameLabel.text = workout.trainer.name
cell.dateLabel.text = workout.getDateString()
cell.timeLabel.text = workout.getTimeString()
cell.trainerImage.image = workout.image
cell.ratingControl.rating = workout.rating // Exclusive to PastWorkoutCell
}
Is there a better way to write this? Can I somehow get rid of the initial declaration as a UITableViewCell and shorten my code by a line?
Also, MyWorkoutsTableViewCell and PastWorkoutCell have almost all their properties in common. Can I avoid repeating code in each of the branches of the if statement to set all of them? Right now cell is a UITableViewCell that doesn't have any properties so I can't seem to do it outside the two branches.
Have you try this
var cell = tableView.dequeueReusableCellWithIdentifier("UpcomingWorkoutCell", forIndexPath: indexPath) as! MyWorkoutsTableViewCell
if indexPath.section != 0 {
cell = tableView.dequeueReusableCellWithIdentifier("PastWorkoutCell", forIndexPath: indexPath) as! PastWorkoutTableViewCell
cell.ratingControl.rating = workout.rating
}
cell.nameLabel.text = workout.trainer.name
cell.dateLabel.text = workout.getDateString()
cell.timeLabel.text = workout.getTimeString()
cell.trainerImage.image = workout.image
The only thing that's unpleasant about your code is that the cell declared in the first line is immediately replaced by the real cell. To avoid that, use a define-and-call function:
let cell : UITableViewCell = {
if indexPath.section == 0 {
let cell = // ...
return cell
}
else {
let cell = // ...
return cell
}
}()
The duplication can be avoided through a common (abstract) superclass.
class MyCell : UITableViewCell {
// declare nameLabel, dateLabel, timeLabel etc.
}
class MyWorkoutsTableViewCell: MyCell {}
class PastWorkoutCell: MyCell {}
Now we can restructure like this:
let cell : MyCell = {
if indexPath.section == 0 {
let cell = // ...
return cell
}
else {
let cell = // ...
return cell
}
}()
// configure MyCell once, here, and return it
var cell = UITableViewCell()
if indexPath.section == 0 {
cell = tableView.dequeueReusableCellWithIdentifier("UpcomingWorkoutCell", forIndexPath: indexPath) as! MyWorkoutsTableViewCell
} else {
cell = tableView.dequeueReusableCellWithIdentifier("PastWorkoutCell", forIndexPath: indexPath) as! PastWorkoutTableViewCell
}
cell.nameLabel.text = workout.trainer.name
cell.dateLabel.text = workout.getDateString()
cell.timeLabel.text = workout.getTimeString()
cell.trainerImage.image = workout.image
Nirav's answer is good except for a bit changes
var cell = tableView.dequeueReusableCellWithIdentifier("UpcomingWorkoutCell", forIndexPath: indexPath) as! MyWorkoutsTableViewCell
if indexPath.section != 0 {
cell = tableView.dequeueReusableCellWithIdentifier("PastWorkoutCell", forIndexPath: indexPath) as! PastWorkoutTableViewCell
cell.ratingControl.rating = workout.rating
}
cell.nameLabel.text = workout.trainer.name
cell.dateLabel.text = workout.getDateString()
cell.timeLabel.text = workout.getTimeString()

Bad performance when presenting modally over uicollectionviewcontroller on iPad

in have a simple uicollectionviewcontroller with some simpel views in. In the UINavigationBar i have a button, when pressed presents modally (as formsheet) segue to a navigation controller, with a tableview as rootview.
On iPhone, it all works well, but on iPad the animation when it presents and when the presented tableview scroll, is bad and have low fps.
How can this be?
Please tell what kind of information from my app is needed to help me.
I am working in swift, iOS 8.3
UPDATE:
Okay, so i got 8 different kinds of prototypecells in my tableview, all with auto-layout in my storyboard. I have a subclass for each of them with IBOutlets.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if (indexPath.section == 0) {
if indexPath.row == 0 {
let calendar = NSCalendar.currentCalendar()
let components = calendar.components(NSCalendarUnit.CalendarUnitWeekOfYear, fromDate: NSDate())
let cell = tableView.dequeueReusableCellWithIdentifier("weekCell", forIndexPath: indexPath) as! WeekChooserTableViewCell
cell.stepper.value = Double(components.weekOfYear)
cell.weekNumber.text = String(components.weekOfYear)
return cell
} else if indexPath.row == 1 {
let cell = tableView.dequeueReusableCellWithIdentifier("customerCell", forIndexPath: indexPath) as! CustomerTableViewCell
cell.customerTextField.tag = "\(indexPath.row+1)\(indexPath.section+1)".toInt()!
cell.customerTextField.delegate = self
return cell
}
} else if indexPath.section > 0 && indexPath.section <= 5 {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCellWithIdentifier("hourpayCell", forIndexPath: indexPath) as! HourpayTableViewCell
if arrayOfHourpay[indexPath.section-1] == 9999999999 {
cell.hourpayTextField.text = ""
} else {
cell.hourpayTextField.text = String("\(arrayOfHourpay[indexPath.section-1])")
}
cell.hourpayTextField.tag = "\(indexPath.row+1)\(indexPath.section+1)".toInt()!
cell.hourpayTextField.delegate = self
return cell
} else if indexPath.row == 1 {
let cell = tableView.dequeueReusableCellWithIdentifier("casepayCell", forIndexPath: indexPath) as! CasepayTableViewCell
if arrayOfCasepay[indexPath.section-1] == 9999999999 {
cell.casepayTextField.text = ""
} else {
cell.casepayTextField.text = String("\(arrayOfCasepay[indexPath.section-1])")
}
cell.casepayTextField.tag = "\(indexPath.row+1)\(indexPath.section+1)".toInt()!
cell.casepayTextField.delegate = self
return cell
} else if indexPath.row == 2 {
let cell = tableView.dequeueReusableCellWithIdentifier("machinepayCell", forIndexPath: indexPath) as! MachinepayTableViewCell
if arrayOfMachinepay[indexPath.section-1] == 9999999999 {
cell.machinepayTextField.text = ""
} else {
cell.machinepayTextField.text = String("\(arrayOfMachinepay[indexPath.section-1])")
}
cell.machinepayTextField.tag = "\(indexPath.row+1)\(indexPath.section+1)".toInt()!
cell.machinepayTextField.delegate = self
return cell
} else if indexPath.row == 3 {
let cell = tableView.dequeueReusableCellWithIdentifier("daycommentCell", forIndexPath: indexPath) as! DayCommentTableViewCell
cell.textView?.tag = "\(indexPath.row+1)\(indexPath.section+1)".toInt()!
cell.textView?.text = arrayOfDayComments[indexPath.section-1]
return cell
}
} else if indexPath.section == 6 {
if indexPath.row + 1 == rowsInMaterialSection {
let cell = tableView.dequeueReusableCellWithIdentifier("addMaterialCell", forIndexPath: indexPath) as! AddNewMaterialTableViewCell
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier("materialTextfieldCell", forIndexPath: indexPath) as! MaterialTextfieldTableViewCell
cell.MaterialTextField.text = arrayOfMaterials[indexPath.row]
cell.MaterialTextField.tag = "\(indexPath.row+1)\(indexPath.section+1)".toInt()!
cell.MaterialTextField.delegate = self
return cell
}
}
let cell = tableView.dequeueReusableCellWithIdentifier("daycommentCell", forIndexPath: indexPath) as! DayCommentTableViewCell
return cell
}

Resources