Bad performance when presenting modally over uicollectionviewcontroller on iPad - ios

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
}

Related

I am getting the error: Assertion failure in -[UICollectionView _dequeueReusableViewOfKind:withIdentifier:forIndexPath:viewCategory:]

I have a ViewController with multiple UICollectionViews on it. Initially, I started with two (myFavoritesCollectionView and allDealsCollectionView) and the app ran sufficiently. However, when I added the others the app began to crash.
I set an Exception Breakpoint and am getting the error:
2019-04-28 21:00:44.802033-0500 DiscountDays_[67279:13374922] *** Assertion failure in -[UICollectionView _dequeueReusableViewOfKind:withIdentifier:forIndexPath:viewCategory:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKitCore_Sim/UIKit-3698.103.12/UICollectionView.m:5417
And it is highlighting the line:
let cell2 = collectionView.dequeueReusableCell(withReuseIdentifier: "hello", for: indexPath) as? FastFoodCollectionViewCell
Below is the extension on my UIViewController:
extension ViewController:UICollectionViewDelegate,UICollectionViewDataSource{
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView == self.myFavoritesCollectionView{
print(myEmptyArray.count)
return self.myEmptyArray.count
}
else if collectionView == self.fastFoodCollectionView{
return self.fastFoodArray.count
}
else if collectionView == self.DessertsCollectionView{
return self.dessertsArray.count
}
else if collectionView == self.sitDownRestrauntsCollectionView{
return self.sitDownArray.count
}
else if collectionView == self.otherThanFoodCollectionView{
return self.otherArray.count
}
else {
print(allDiscounts.list.count)
return allDiscounts.list.count
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView == myFavoritesCollectionView{
let cell1 = collectionView.dequeueReusableCell(withReuseIdentifier: "theLikes", for: indexPath) as? myLikesCollectionViewCell
cell1?.companyLikedImage.image = UIImage(named: allDiscounts.list[myEmptyArray[indexPath.row]].imageName)
cell1?.companyLikedName.text = allDiscounts.list[myEmptyArray[indexPath.row]].businessName
cell1?.layer.cornerRadius = 11
print("collectionviewlikes")
return cell1!
}
else if collectionView == fastFoodCollectionView{
let cell2 = collectionView.dequeueReusableCell(withReuseIdentifier: "hello", for: indexPath) as? FastFoodCollectionViewCell
cell2?.fastCompanyLikedImage.image = UIImage(named: allDiscounts.list[fastFoodArray[indexPath.row]].imageName)
cell2?.fastCompanyLikedName.text = allDiscounts.list[fastFoodArray[indexPath.row]].businessName
cell2?.layer.cornerRadius = 11
print("collectionviewfast")
return cell2!
}
else if collectionView.isEqual(DessertsCollectionView) {
let cell3 = collectionView.dequeueReusableCell(withReuseIdentifier: "theDesserts", for: indexPath) as? DessertsCollectionViewCell
cell3?.dessertsCompanyLikedImage.image = UIImage(named: allDiscounts.list[dessertsArray[indexPath.row]].imageName)
cell3?.dessertsCompanyLikedName.text = allDiscounts.list[dessertsArray[indexPath.row]].businessName
cell3?.layer.cornerRadius = 11
print("collectionviewdesserts")
return cell3!
}
else if collectionView == sitDownRestrauntsCollectionView {
let cell4 = collectionView.dequeueReusableCell(withReuseIdentifier: "theSits", for: indexPath) as? sitDownCollectionViewCell
cell4?.sitCompanyLikedImage.image = UIImage(named: allDiscounts.list[sitDownArray[indexPath.row]].imageName)
cell4?.sitCompanyLikedName.text = allDiscounts.list[sitDownArray[indexPath.row]].businessName
cell4?.layer.cornerRadius = 11
print("collectionviewsit")
return cell4!
}
else if collectionView == otherThanFoodCollectionView {
let cell5 = collectionView.dequeueReusableCell(withReuseIdentifier: "theOthers", for: indexPath) as? OtherCollectionViewCell
cell5?.otherCompanyLikedImage.image = UIImage(named: allDiscounts.list[otherArray[indexPath.row]].imageName)
cell5?.otherCompanyLikedName.text = allDiscounts.list[otherArray[indexPath.row]].businessName
cell5?.layer.cornerRadius = 11
print("collectionviewother")
return cell5!
}
else {
let cell6 = collectionView.dequeueReusableCell(withReuseIdentifier: "allDeals", for: indexPath) as? allDealsCollectionViewCell
cell6?.companyLikedImage1.image = UIImage(named: allDiscounts.list[indexPath.row].imageName)
cell6?.companyLikedName1.text = allDiscounts.list[indexPath.row].businessName
cell6?.layer.cornerRadius = 11
print("collectionviewall")
return cell6!
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
if collectionView == self.myFavoritesCollectionView {
// handle tap events
ViewController.searchStruct.buttonTag = myEmptyArray[indexPath.row]
performSegue(withIdentifier: "gotocompany1", sender: self)
}
else if collectionView == self.fastFoodCollectionView {
ViewController.searchStruct.buttonTag = fastFoodArray[indexPath.row]
performSegue(withIdentifier: "gotocompany1", sender: self)
}
else if collectionView == self.DessertsCollectionView {
ViewController.searchStruct.buttonTag = dessertsArray[indexPath.row]
performSegue(withIdentifier: "gotocompany1", sender: self)
}
else if collectionView == self.sitDownRestrauntsCollectionView {
ViewController.searchStruct.buttonTag = sitDownArray[indexPath.row]
performSegue(withIdentifier: "gotocompany1", sender: self)
}
else if collectionView == self.otherThanFoodCollectionView {
ViewController.searchStruct.buttonTag = otherArray[indexPath.row]
performSegue(withIdentifier: "gotocompany1", sender: self)
}
else {
ViewController.searchStruct.buttonTag = indexPath.row
performSegue(withIdentifier: "gotocompany1", sender: self)
}
}
}
Ideally, if the code runs properly, there will be a UIViewController with 6 UICollectionViews that scroll horizontally each with different items displayed.

How to use multiple tableviews by using Multiple custom class

I have xib files there I used create multiple table with multiple custom xib cell, but I got the problem while load the multiple custom cell. i am getting error on code of cell rowat indexpath...i dont know how to do that with multiple tableview with multiple custom cell
any one help me to solve this issues
Thanks in Advance
func TablecellRegisternib() {
self.Hight_table.register(UINib(nibName: "tableviewcellTableViewCell", bundle: nil), forCellReuseIdentifier: "cell")
self.weight_table.register(UINib(nibName: "tableviewcellTableViewCell", bundle: nil), forCellReuseIdentifier: "cell")
self.Gender_table.register(UINib(nibName: "tableviewcellTableViewCell", bundle: nil), forCellReuseIdentifier: "cell")
self.Weekday_table.register(UINib(nibName: "tableviewcellTableViewCell", bundle: nil), forCellReuseIdentifier: "cell")
self.Gym_tableview.register(UINib(nibName: "GymTableCell", bundle: nil), forCellReuseIdentifier: "cell1")
self.Sports_tableview.register(UINib(nibName: "SpotsTableCell", bundle: nil), forCellReuseIdentifier: "cell2")
self.AdditioanlSports_tableview.register(UINib(nibName: "AdditioanlSpotsTableCell", bundle: nil), forCellReuseIdentifier: "cell3")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// Return the number of items in the sample data structure.
var count:Int?
if tableView == self.weight_table {
count = WightUnitArray.count
}
if tableView == self.Hight_table {
count = HightUnitArray.count
}
if tableView == self.Weekday_table {
count = WeekdayArray.count
}
if tableView == self.Gender_table {
count = GenderArray.count
}
if tableView == self.Sports_tableview {
count = SportsArray.count
}
if tableView == self.AdditionalSports_tableview {
count = AdditionalSportsArray.count
}
return count!
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableView == self.weight_table {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! tableviewcellTableViewCell
cell.detail_lbl.text=WightUnitArray[indexPath.row]
cell.selectionStyle = UITableViewCellSelectionStyle.none;
cell.detail_lbl.font = UIFont(name:"Roboto-Regular", size:13)
cell.detail_lbl.adjustsFontSizeToFitWidth = true
if (selectedIndex == indexPath as NSIndexPath?) {
cell.radi_btn.setImage(UIImage(named: "radio_btn_active.png"),for:UIControlState.normal)
} else {
cell.radi_btn.setImage(UIImage(named: "radio_btn.png"),for:UIControlState.normal)
}
}
if tableView == self.Hight_table {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! tableviewcellTableViewCell
cell.detail_lbl.text=HightUnitArray[indexPath.row]
cell.selectionStyle = UITableViewCellSelectionStyle.none;
cell.detail_lbl.font = UIFont(name:"Roboto-Regular", size:13)
cell.detail_lbl.adjustsFontSizeToFitWidth = true
if (selectedIndex == indexPath as NSIndexPath?) {
cell.radi_btn.setImage(UIImage(named: "radio_btn_active.png"),for:UIControlState.normal)
} else {
cell.radi_btn.setImage(UIImage(named: "radio_btn.png"),for:UIControlState.normal)
}
}
if tableView == self.Weekday_table {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! tableviewcellTableViewCell
cell.detail_lbl.text=WeekdayArray[indexPath.row]
cell.selectionStyle = UITableViewCellSelectionStyle.none;
cell.detail_lbl.font = UIFont(name:"Roboto-Regular", size:13)
cell.detail_lbl.adjustsFontSizeToFitWidth = true
if (selectedIndex == indexPath as NSIndexPath?) {
cell.radi_btn.setImage(UIImage(named: "radio_btn_active.png"),for:UIControlState.normal)
} else {
cell.radi_btn.setImage(UIImage(named: "radio_btn.png"),for:UIControlState.normal)
}
}
if tableView == self.Gender_table {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! tableviewcellTableViewCell
cell.detail_lbl.text=GenderArray[indexPath.row]
cell.selectionStyle = UITableViewCellSelectionStyle.none;
cell.detail_lbl.font = UIFont(name:"Roboto-Regular", size:13)
cell.detail_lbl.adjustsFontSizeToFitWidth = true
if (selectedIndex == indexPath as NSIndexPath?) {
cell.radi_btn.setImage(UIImage(named: "radio_btn_active.png"),for:UIControlState.normal)
} else {
cell.radi_btn.setImage(UIImage(named: "radio_btn.png"),for:UIControlState.normal)
}
}
if tableView == self.Gym_tableview {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell1") as! GymTableCell
var GymDict = GymtableArray[indexPath.row]
cell.sportlbl!.text = GymDict["name"] as? String
cell.sportlbl?.adjustsFontSizeToFitWidth = true
cell.sportlbl?.font = UIFont(name:"Roboto-Regular", size:13)
return cell
}
if tableView == self.Sports_tableview {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell3") as! SportsTableCell
var SportsDict = SportsArray[indexPath.row]
cell.sportlbl1!.text = SportsDict["name"] as? String
cell.sportlbl1?.adjustsFontSizeToFitWidth = true
cell.sportlbl1?.font = UIFont(name:"Roboto-Regular", size:13)
return cell
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if tableView == self.weight_table {
tableView.deselectRow(at: indexPath as IndexPath, animated: true)
let row = indexPath.row
selectedIndex = indexPath as NSIndexPath?
let weightstring = (WightUnitArray[row])
if( weightstring != "Pound")
{
self.WeightUnitTabletxt.text = "kg"
}
else{
self.WeightUnitTabletxt.text = "lbs"
}
self.Weight_View.isHidden = true
tableView.reloadData()
}
if tableView == self.Hight_table {
tableView.deselectRow(at: indexPath as IndexPath, animated: true)
let row = indexPath.row
selectedIndex = indexPath as NSIndexPath?
let Hightstr = (HightUnitArray[row])
if( Hightstr != "Feet")
{
self.HeightUnitTabletxt.text = "m"
}
else{
self.HeightUnitTabletxt.text = "ft"
}
self.Hight_view.isHidden = true
tableView.reloadData()
}
if tableView == self.Weekday_table {
tableView.deselectRow(at: indexPath as IndexPath, animated: true)
let row = indexPath.row
selectedIndex = indexPath as NSIndexPath?
self.FirstDayofWeek_txt.text = (WeekdayArray[row])
self.FirstdayoftheWeek_view.isHidden = true
tableView.reloadData()
}
if tableView == self.Gender_table {
tableView.deselectRow(at: indexPath as IndexPath, animated: true)
let row = indexPath.row
selectedIndex = indexPath as NSIndexPath?
self.gender_txt.text = (GenderArray[row])
self.Genderview.isHidden = true
tableView.reloadData()
}
}

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

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.

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.

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()

Resources