TableView's textLabel height according to content - ios

I have made an Collapsed TableView. The size of the tableView's label is not increasing according the content. I had set WordWrap and Lines = 0 but still it's not working.
I'm using 2 tableView cell's to make the collapsed view.
extension UIView {
func rotate(toValue: CGFloat, duration: CFTimeInterval = 0.2, completionDelegate: AnyObject? = nil) {
let rotateAnimation = CABasicAnimation(keyPath: "transform.rotation")
rotateAnimation.toValue = toValue
rotateAnimation.duration = duration
rotateAnimation.removedOnCompletion = false
rotateAnimation.fillMode = kCAFillModeForwards
if let delegate: AnyObject = completionDelegate {
rotateAnimation.delegate = delegate
}
self.layer.addAnimation(rotateAnimation, forKey: nil)
}
}
class CollapsibleTableViewController: UITableViewController {
struct Section {
var name: String!
var items: [String]!
var collapsed: Bool!
init(name: String, items: [String], collapsed: Bool = false) {
self.name = name
self.items = items
self.collapsed = collapsed
}
}
var sections = [Section]()
override func viewDidLoad() {
super.viewDidLoad()
sections = [Section(name: "TEXT OVER HERE", items: ["TEXT OVER HERE."])]
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return sections.count
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return (sections[section].collapsed!) ? 0 : sections[section].items.count
}
override func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let header = tableView.dequeueReusableCellWithIdentifier("header") as! CollapsibleTableViewHeader
header.toggleButton.tag = section
header.titleLabel.text = sections[section].name
header.toggleButton.rotate(sections[section].collapsed! ? 0.0 : CGFloat(M_PI_2))
header.toggleButton.addTarget(self, action: #selector(CollapsibleTableViewController.toggleCollapse), forControlEvents: .TouchUpInside)
return header.contentView
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell!
cell.textLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping
cell.textLabel?.numberOfLines = 0
cell.textLabel?.text = sections[indexPath.section].items[indexPath.row]
return cell
}
//
// MARK: - Event Handlers
//
func toggleCollapse(sender: UIButton) {
let section = sender.tag
let collapsed = sections[section].collapsed
// Toggle collapse
sections[section].collapsed = !collapsed
// Reload section
tableView.reloadSections(NSIndexSet(index: section), withRowAnimation: .Automatic)
}
}

try this code:
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
var lblSectionName: UILabel = UILabel()
lblSectionName.text = self.sectionNames[section]
lblSectionName.numberOfLines = 0
lblSectionName.lineBreakMode = .ByWordWrapping
lblSectionName.sizeToFit()
return lblSectionName.frame.size.height
}
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
var lblSectionName: UILabel = UILabel()
lblSectionName.text = self.sectionNames[section]
lblSectionName.numberOfLines = 0
lblSectionName.lineBreakMode = .ByWordWrapping
lblSectionName.sizeToFit()
return lblSectionName
}

Better is this answer: https://stackoverflow.com/a/29763200/1054550
self.tableView.sectionHeaderHeight = UITableViewAutomaticDimension;
self.tableView.estimatedSectionHeaderHeight = 25;

Related

TableView Collapse, why it's sticking up like this?

I'm setting up a collapsable tableView, but something strange happens on the collapsable item. When you look at the video keep an eye on the "Where are you located" line.. (I'm using a .plist for the question and answer items)
Where do I go wrong, is it somewhere in my code? I don't want to let that line stick on the top :(
Here is the code I'm using but I can't find anything strange...
class FAQViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var questionsArray = [String]()
var answersDict = Dictionary<String, [String]>() // multiple answers for a question
var collapsedArray = [Bool]()
#IBOutlet weak var tableView: UITableView!
override func viewWillAppear(_ animated: Bool) {
// Hide the navigation bar on the this view controller
self.navigationController?.setNavigationBarHidden(true, animated: true)
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
addTableStyles()
readQAFile()
tableView.delegate = self
tableView.dataSource = self
self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
}
func addTableStyles(){
navigationController?.isNavigationBarHidden = false
self.tableView?.backgroundView = {
let view = UIView(frame: self.tableView.bounds)
return view
}()
tableView.estimatedRowHeight = 43.0;
tableView.rowHeight = UITableView.automaticDimension
tableView.separatorStyle = UITableViewCell.SeparatorStyle.singleLine
}
func readQAFile(){
guard let url = Bundle.main.url(forResource: "QA", withExtension: "plist")
else { print("no QAFile found")
return
}
let QAFileData = try! Data(contentsOf: url)
let dict = try! PropertyListSerialization.propertyList(from: QAFileData, format: nil) as! Dictionary<String, Any>
// Read the questions and answers from the plist
questionsArray = dict["Questions"] as! [String]
answersDict = dict["Answers"] as! Dictionary<String, [String]>
// Initially collapse every question
for _ in 0..<questionsArray.count {
collapsedArray.append(false)
}
}
func numberOfSections(in tableView: UITableView) -> Int {
return questionsArray.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
if collapsedArray[section] {
let ansCount = answersDict[String(section)]!
return ansCount.count
}
return 0
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
// Set it to any number
return 70
}
func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return 1
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if collapsedArray[indexPath.section] {
return UITableView.automaticDimension
}
return 2
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView(frame: CGRect(x:0, y:0, width:tableView.frame.size.width, height:40))
headerView.tag = section
let headerString = UILabel(frame: CGRect(x: 10, y: 10, width: tableView.frame.size.width, height: 50)) as UILabel
headerString.text = "\(questionsArray[section])"
headerView .addSubview(headerString)
let headerTapped = UITapGestureRecognizer (target: self, action:#selector(sectionHeaderTapped(_:)))
headerView.addGestureRecognizer(headerTapped)
return headerView
}
#objc func sectionHeaderTapped(_ recognizer: UITapGestureRecognizer) {
let indexPath : IndexPath = IndexPath(row: 0, section:recognizer.view!.tag)
if (indexPath.row == 0) {
let collapsed = collapsedArray[indexPath.section]
collapsedArray[indexPath.section] = !collapsed
//reload specific section animated
let range = Range(NSRange(location: indexPath.section, length: 1))!
let sectionToReload = IndexSet(integersIn: range)
self.tableView.reloadSections(sectionToReload as IndexSet, with:UITableView.RowAnimation.fade)
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cellIdentifier = "Cell"
let cell: UITableViewCell! = self.tableView.dequeueReusableCell(withIdentifier: cellIdentifier)
cell.textLabel?.adjustsFontSizeToFitWidth = true
cell.textLabel?.numberOfLines = 0
let manyCells : Bool = collapsedArray[indexPath.section]
if (manyCells) {
let content = answersDict[String(indexPath.section)]
cell.textLabel?.text = content![indexPath.row]
}
return cell
}
override var prefersStatusBarHidden: Bool {
return true
}
}
You need to change the style of the tableView to grouped, when you initialize it:
let tableView = UITableView(frame: someFrame, style: .grouped)
or from Storyboard:
After that you will have this issue, which I solved by setting a tableHeaderView to the tableView that has CGFloat.leastNormalMagnitude as its height:
override func viewDidLoad() {
super.viewDidLoad()
var frame = CGRect.zero
frame.size.height = .leastNormalMagnitude
tableView.tableHeaderView = UIView(frame: frame)
}
Just remove your headerView from view hierarchy here
#objc func sectionHeaderTapped(_ recognizer: UITapGestureRecognizer) {
headerView.removeFromSuperview()
...
}
By the way, yes creating a openable tableview menu with using plist is one of the methods but it could be more simple. In my opinion you should refactor your code.

Problem with Custom View for header in section not rendering on tap gesture UITableView

I have tried n number of solutions, but still no luck. I designed my own Custom cell for Header of a Section. So my table renders properly.
Then for each header cell in func viewForHeaderInSection(), I've added tap gesture to handle click on header. But every time I click on any header it disappears from the table. I haven't written any code of deleting sections.
func numberOfSections(in tableView: UITableView) -> Int {
return ModelFacade.sharedInstanceModelFacade.getGenericModel().faqsArray.count
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let cell = tableView.dequeueReusableCell(withIdentifier: "AccordianHeaderPrototypeCell") as! AccordianHeaderPrototypeCell
let cellinfo = ModelFacade.sharedInstanceModelFacade.getGenericModel().faqsArray[section]
cell.headingLabel.text = cellinfo.title
cell.arrowImage.tag = kHeaderSectionTag + section
cell.arrowImage.image = Constants.DOWNARROW_IMAGE
cell.tag = section
let headerTapGesture = UITapGestureRecognizer()
headerTapGesture.addTarget(self, action: #selector(self.sectionHeaderWasTouched(_:)))
cell.addGestureRecognizer(headerTapGesture)
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if (self.expandedSectionHeaderNumber == section) {
return ModelFacade.sharedInstanceModelFacade.getGenericModel().faqsArray[section].contentArray.count
} else {
return 0;
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ProductDetailingsPrototypeCell", for: indexPath) as! ProductDetailingsPrototypeCell
cell.separatorInset = .zero
let cellinfo = ModelFacade.sharedInstanceModelFacade.getGenericModel().faqsArray[indexPath.section].contentArray[indexPath.row]
cell.descriptionLabel.attributedText = cellinfo.html2Attributed
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
#objc func sectionHeaderWasTouched(_ sender: UITapGestureRecognizer) {
let headerView = sender.view as! AccordianHeaderPrototypeCell
let section = headerView.tag
let eImageView = headerView.viewWithTag(kHeaderSectionTag + section) as? UIImageView
if (self.expandedSectionHeaderNumber == -1) {
self.expandedSectionHeaderNumber = section
tableViewExpandSection(section, imageView: eImageView!)
} else {
if (self.expandedSectionHeaderNumber == section) {
tableViewCollapeSection(section, imageView: eImageView!)
} else {
let cImageView = self.view.viewWithTag(kHeaderSectionTag + self.expandedSectionHeaderNumber) as? UIImageView
tableViewCollapeSection(self.expandedSectionHeaderNumber, imageView: cImageView!)
tableViewExpandSection(section, imageView: eImageView!)
}
}
}
func tableViewCollapeSection(_ section: Int, imageView: UIImageView) {
let sectionData = ModelFacade.sharedInstanceModelFacade.getGenericModel().faqsArray[section].contentArray
self.expandedSectionHeaderNumber = -1
if (sectionData.count == 0) {
return
} else {
UIView.animate(withDuration: 0.4, animations: {
imageView.transform = CGAffineTransform(rotationAngle: (0.0 * CGFloat(Double.pi)) / 180.0)
})
var indexesPath = [IndexPath]()
for i in 0 ..< sectionData.count {
let index = IndexPath(row: i, section: section)
indexesPath.append(index)
}
self.itemsTableView!.beginUpdates()
self.itemsTableView!.deleteRows(at: indexesPath, with: UITableView.RowAnimation.fade)
self.itemsTableView!.endUpdates()
}
}
func tableViewExpandSection(_ section: Int, imageView: UIImageView) {
let sectionData = ModelFacade.sharedInstanceModelFacade.getGenericModel().faqsArray[section].contentArray
if (sectionData.count == 0) {
self.expandedSectionHeaderNumber = -1
return
} else {
UIView.animate(withDuration: 0.4, animations: {
imageView.transform = CGAffineTransform(rotationAngle: (180.0 * CGFloat(Double.pi)) / 180.0)
})
var indexesPath = [IndexPath]()
for i in 0 ..< sectionData.count {
let index = IndexPath(row: i, section: section)
indexesPath.append(index)
}
self.expandedSectionHeaderNumber = section
self.itemsTableView.beginUpdates()
self.itemsTableView.insertRows(at: indexesPath, with: UITableView.RowAnimation.fade)
self.itemsTableView.endUpdates()
}
}
Adding two images to explain what happens before and after click.

Collapse other UITableViewCell when current cell is expanded

I am trying to expand my UITableViewCell and I can expand cells. But I want to collapse the UITableViewCell which are not selected.
What I am trying in code:
var expandedCells = [Int]()
#IBOutlet weak var tableVieww:UITableView!
#IBAction func buttonPressed(_ sender: AnyObject) {
// If the array contains the button that was pressed, then remove that button from the array
if expandedCells.contains(sender.tag) {
expandedCells = expandedCells.filter({ $0 != sender.tag})
}
// Otherwise, add the button to the array
else {
expandedCells.append(sender.tag)
}
// Reload the tableView data anytime a button is pressed
tableVieww.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! exampleCell
cell.myButton.tag = indexPath.row
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// Set the row height based on whether or not the Int associated with that row is contained in the expandedCells array
if expandedCells.contains(indexPath.row) {
return 212
} else {
return 57
}
}
You can maintain a variable for maintaining the selected index as below,
var expandedIndexPath: IndexPath?
Then update your tableView delegate as follows,
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
expandedIndexPath = indexPath // Update the expandedIndexPath with the selected index
tableView.reloadData() // Reload tableview to reflect the change
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
// Check wether expanded indexpath is the current index path and updated return the respective height
if expandedIndexPath == indexPath {
return 212
} else {
return 57
}
}
This should work fine.
1) First Create Bool Array variable
var isExpandArr = Array<Bool>()
2) Insert true at 0 index in ViewLoad()
isExpandArr.insert(true, at: 0)
3) Put Into cellForRowAt
cell.ToggleBT.addTarget(self, action: #selector(handleToggleBtn), for:.touchUpInside)
cell.ToggleBT.tag = indexPath.row
if isExpandArr[indexPath.row] == true{
cell.bottomrView.isHidden = false
}else{
cell.bottomrView.isHidden = true
}
4) set heightForRowAt
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return isExpandArr[indexPath.row] ? 204 : 60
}
5) put function
func handleToggleBtn(sender: UIButton){
print(sender.tag)
if isExpandArr.contains(true){
print("yes")
if let unwrappedIndex = isExpandArr.index(of: true){
isExpandArr[unwrappedIndex] = false
isExpandArr[sender.tag] = true
}
}
table.reloadData()
}
in #swift 2.3
Hope this will also helpful
For collapse and expand the header
define the variable above the viewDidLoad or within the class block
var headerIcon: UIImageView = UIImageView()
var sectionTitleArray : NSMutableArray = NSMutableArray()
var sectionContentEventTitleDict : NSMutableDictionary = NSMutableDictionary()
var sectionEventImagesDict : NSMutableDictionary = NSMutableDictionary()
var arrayForBool : NSMutableArray = NSMutableArray()
var arrFirstSectionItemTitle = ["Section 1 item Name 1","Section 1 item Name 2","Section 1 item Name 3","Section 1 item Name 4","Section 1 item Name 5","Section 1 item Name 6","Section 1 item Name 7"]
var arrFirstSectionItemImages = ["Section_1_icon_1","Section_1_icon_2","Section_1_icon_3","Section_1_icon_4","Section_1_icon_5","Section_1_icon_6","Section_1_icon_7"]
var arrSecondSectionItemTitle = ["Section 2 item Name 1","Section 2 item Name 2","Section 2 item Name 3","Section 2 item Name 4"]
var arrSecondSectionItemImages = ["Section_1_icon_1","Section_2_item_icon_2","Section_2_item_icon_3","Section_1_item_icon_4","Section_1_item_icon_5","Section_1_item_icon_6","Section_1_item_icon_7"]
var arrData: Array<Dictionary<String,AnyObject>> = Array<Dictionary<String,AnyObject>>()
#IBOutlet weak var tableList: UITableView!
in viewDidLoad() method write these lines of code
tableList.delegate = self
tableList.dataSource = self
tableList.backgroundColor = UIColor.getRGBColor(240, g: 240, b: 240)
let customView = UIView(frame: CGRectMake(0, 0, 200, 80))
customView.backgroundColor = UIColor.getRGBColor(240, g: 240, b: 240)
let customLine = UIView(frame: CGRectMake(0, 0, tblAllQuestion.frame.size.width, 1))
customLine.backgroundColor = UIColor.getRGBColor(240, g: 240, b: 240)
customView.addSubview(customLine)
tableList.tableFooterView = customView
now write the delegate and datasource methods as following:
//MARK: UITableViewDelegate AND UITableViewDataSource METHOD WITH SECTION
for number of sections to be collapsed and expand
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
print_debug(sectionTitleArray.count)
return sectionTitleArray.count
}
cell method:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CELL_IDENTIFIER", forIndexPath: indexPath)as! CellAllQuestionFiqhVC
//let cellIdentifier = "CellAllQuestionFiqhVC"
// cell = self.tableList.dequeueReusableCellWithIdentifier(cellIdentifier)
let manyCells : Bool = arrayForBool .objectAtIndex(indexPath.section).boolValue
if (!manyCells) {
// cell.textLabel.text = #"click to enlarge";
}
else{
let group = self.arrData[indexPath.section]
let data: Array<Dictionary<String,AnyObject>> = group["data"]as! Array<Dictionary<String,AnyObject>>
cell.configCell(data[indexPath.row], instance: self)
}
return cell
}
number cell in a section:
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if(arrayForBool.objectAtIndex(section).boolValue == true){
let count1 = arrData[section]["data"]!
if count1.count != nil {
return count1.count
}
}
return 0;
}
the height of the section
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 40
}
The height of the cell:
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if(arrayForBool.objectAtIndex(indexPath.section).boolValue == true){
return 100
}
return 2;
}
to set header tappable:
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let headerView = UIView(frame: CGRectMake(0, 0, tableView.frame.size.width, 40))
headerView.backgroundColor = UIColor.whiteColor()//Constant.kAPP_COLOR
headerView.tag = section
let headerString = UILabel(frame: CGRectMake(40/*tableView.frame.size.width/2-30*/, 10, tableView.frame.size.width, 18))
let headerLine = UIView(frame: CGRectMake(0, 39, tableView.frame.size.width, 1))
//UILabel(frame: CGRect(x: 20, y: 10, width: tableView.frame.size.width-10, height: 30)) as UILabel
//headerLine.text = sectionTitleArray.objectAtIndex(section) as? String
headerLine.backgroundColor = UIColor.getRGBColor(240, g: 240, b: 240)
headerView .addSubview(headerLine)
headerIcon = UIImageView(frame: CGRect(x: tblAllQuestion.bounds.maxX-30, y: 10, width: 8, height: 12)) as UIImageView
headerIcon.image = UIImage(named: "right_arrow")
headerView.addSubview(headerIcon)
let headerTapped = UITapGestureRecognizer(target: self, action: #selector(sectionHeaderTapped))
headerView.addGestureRecognizer(headerTapped)
return headerView
}
for rotate section icon on tapped on:
func rotateSectionIconOnTapped(indexTapped: Int) {
isActiveMap = false
if arrayForBool.objectAtIndex(indexTapped) as! NSObject == true {
print("toggle the icon at degree 90")
headerIcon.transform = CGAffineTransformMakeRotation(CGFloat(M_PI_2))
}
else if arrayForBool.objectAtIndex(indexTapped) as! NSObject == false {
print("toggle the ico at degree 0")
headerIcon.transform = CGAffineTransformMakeRotation(0)
}
}
action for section header tapped:
func sectionHeaderTapped(recognizer: UITapGestureRecognizer) {
//filterByCategoryIsOn = false
print("Tapping working")
print(recognizer.view?.tag)
//if recognizer.view!.tag != 2 {
let indexPath : NSIndexPath = NSIndexPath(forRow: 0, inSection:(recognizer.view?.tag as Int!)!)
if (indexPath.row == 0) {
for (indexx, bl) in arrayForBool.enumerate() {
if recognizer.view!.tag != indexx {
let index : NSIndexPath = NSIndexPath(forRow: 0, inSection:(indexx))
arrayForBool.replaceObjectAtIndex(index.section, withObject: false)
let range = NSMakeRange(index.section, 1)
let sectionToReload = NSIndexSet(indexesInRange: range)
self.tableList.reloadSections(sectionToReload, withRowAnimation:UITableViewRowAnimation.Fade)
}
}
var collapsed = arrayForBool.objectAtIndex(indexPath.section).boolValue
print_debug(collapsed)
collapsed = !collapsed;
print_debug(collapsed)
arrayForBool.replaceObjectAtIndex(indexPath.section, withObject: collapsed)
print(arrayForBool)
//reload specific section animated
let range = NSMakeRange(indexPath.section, 1)
let sectionToReload = NSIndexSet(indexesInRange: range)
self.tableList.reloadSections(sectionToReload, withRowAnimation:UITableViewRowAnimation.Fade)
rotateSectionIconOnTapped(recognizer.view!.tag)
}
}
get action for didselect row at index path :
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print_debug(indexPath)
print_debug(indexPath.row)
print_debug(indexPath.section)
if indexPath.section == 0 {
}
else if indexPath.section == 1 {
}
}

Swift3 SearchBar Tutorial with TableView Sections

Does somebody have a good Tutorial for a Search Bar with Sections? I did not found a good one yet. Or maybe you can help me straight with my project!?
The section Title is static but i integrated some customized subtitles to show the regions and the total time i spend to make all this Locations(Liegenschaften) in this section. I create this values in the function createWinterdienstDetail. This values should not change when i search for one Location.
I get the Values for my tableview from a different ViewController as
var AllWinterdienstTourInfos: [Int:[Int:[String]]] = [:] // Section - Locationnumber - Locationinformations
Here is my ViewController File:
import UIKit
class WinterdienstTourVC: UIViewController {
var sections = ["Tour 1","Tour 2","Tour 3","Tour 4"]
var LiegenschaftDetail: [String] = []
// VARIABLEN WINTERDIENST
var WinterdienstregionTour1: [String] = []
...
var WinterdienstregionTour15: [String] = []
var WinterdienstaufwandTour1String: [String] = []
...
var WinterdienstaufwandTour15String: [String] = []
var WinterdienstaufwandTour1: [Double] = []
...
var WinterdienstaufwandTour15: [Double] = []
var Totaltouraufwand1 = Double()
...
var Totaltouraufwand15 = Double()
var AllWinterdienstTourInfos: [Int:[Int:[String]]] = [:]
// Initialisierung
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
createWinterdienstDetail()
tableView.delegate = self
tableView.dataSource = self
tableView.tableFooterView = UIView(frame: CGRect.zero)
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if (segue.identifier == "WinterdienstDetailSegue1") {
let DetailviewController = segue.destination as! WinterdienstLiegenschaftDetailVC
DetailviewController.LiegenschaftDetail = LiegenschaftDetail
}
}
func createWinterdienstDetail() {
if let liegenschaftenTour1 = AllWinterdienstTourInfos[0],
let liegenschaftenTour2 = AllWinterdienstTourInfos[1],
let liegenschaftenTour3 = AllWinterdienstTourInfos[2],
let liegenschaftenTour4 = AllWinterdienstTourInfos[3]{
self.myGroup.enter()
// DETAILS TOUR 1
for liegenschaften in liegenschaftenTour1.keys {
WinterdienstregionTour1.append(AllWinterdienstTourInfos[0]![liegenschaften]![6])
WinterdienstaufwandTour1String.append(AllWinterdienstTourInfos[0]![liegenschaften]![15])
for i in 0 ..< WinterdienstregionTour1.count-1 {
var j = WinterdienstregionTour1.count - 1
while(j > i) {
if WinterdienstregionTour1[i] == WinterdienstregionTour1[j] {
WinterdienstregionTour1.remove(at: j)
}
j -= 1
}
}
}
for WinterdienstaufwandTour1Array in WinterdienstaufwandTour1String {
WinterdienstaufwandTour1.append((WinterdienstaufwandTour1Array as NSString).doubleValue)
}
Totaltouraufwand1 = WinterdienstaufwandTour1.reduce(0,+)
// DETAILS TOUR 2
// DETAILS TOUR 3
// DETAILS TOUR 4
self.myGroup.leave()
self.myGroup.notify(queue: .main) {}
DispatchQueue.main.async {}
} // ENDE Function Create Winterdienst
} // ENDE CLASS WinterdienstTourVC
// DataSource-Methoden
extension WinterdienstTourVC: UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int
{
return sections.count
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = UIView()
// SECTION HEADER ALLGEMEIN
view.backgroundColor = UIColor.lightGray
// SECTION HEADER TOUR - NR
let tournr = UILabel()
tournr.text = sections[section]
tournr.font = UIFont.boldSystemFont(ofSize: 20.0)
tournr.frame = CGRect(x: 15,y:0, width: 100, height: 30)
view.addSubview(tournr)
// SECTION HEADER - TOURREGION / TOURAUFWAND
let tourregion = UILabel()
WinterdienstregionTour1.sort()
WinterdienstregionTour1.sort()
WinterdienstregionTour3.sort()
WinterdienstregionTour4.sort()
switch section{
case 0:
let tourregion1 = WinterdienstregionTour1.joined(separator: ", ")
tourregion.text = "\(tourregion1)"
case 1:
let tourregion2 = WinterdienstregionTour2.joined(separator: ", ")
tourregion.text = "\(tourregion2)"
.....
default:
tourregion.text = "Keine Angaben"
}
tourregion.font = UIFont.systemFont(ofSize: 16)
tourregion.frame = CGRect(x: 15,y:22, width: 200, height: 30)
view.addSubview(tourregion)
let touraufwand = UILabel()
switch section{
case 0:
touraufwand.text = "\(Totaltouraufwand1) h"
case 1:
touraufwand.text = "\(Totaltouraufwand2) h"
....
default:
touraufwand.text = "Keine Angaben"
}
touraufwand.frame = CGRect(x: -5,y:12, width: 370, height: 30)
touraufwand.font = UIFont.boldSystemFont(ofSize: 22.0)
touraufwand.textAlignment = .right
view.addSubview(touraufwand)
return view
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 50
}
func tableView(_ tableView: UITableView,
numberOfRowsInSection section: Int) -> Int
{
switch section{
case 0:
return self.AllWinterdienstTourInfos[0]!.count
// self.WinterdienstadressTourAll[0]!.count
case 1:
return self.AllWinterdienstTourInfos[1]!.count
//self.WinterdienstAlltourinfosAll[1]![section]!.count
....
default:
return 1
}
}
func tableView(_ tableView: UITableView,
cellForRowAt indexPath: IndexPath)
-> UITableViewCell
{
// versuchen, eine Zelle wiederzuverwenden
var cell = tableView.dequeueReusableCell(
withIdentifier: "cell")
if cell == nil {
// nicht möglich, daher neue Zelle erzeugen
cell = UITableViewCell(
style: .default, reuseIdentifier: "cell")
}
// Eigenschaften der Zelle einstellen
cell!.textLabel!.text = AllWinterdienstTourInfos[indexPath.section]![indexPath.row]?[4]
cell!.textLabel!.adjustsFontSizeToFitWidth = true
cell!.textLabel!.textAlignment = .left
// Zelle zurückgeben
return cell!
}
}
// TableView-Delegates
extension WinterdienstTourVC: UITableViewDelegate {
func tableView(_ tableView: UITableView,
didSelectRowAt indexPath: IndexPath)
{
LiegenschaftDetail = AllWinterdienstTourInfos[indexPath.section]![indexPath.row]!
performSegue(withIdentifier: "WinterdienstDetailSegue1", sender: self)
}
}

UITableView repeat Custom Cell with UIView in different section after scroll down

I have a ChartCell(UITableViewCell), it has an UIView that I use for showing a chart
class ChartCell: UITableViewCell {
#IBOutlet weak var itemChart: ChartView!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
but my UITableView repeat the cell after scroll down
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return items.count
}
func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return items[section]["title"].stringValue
}
func tableView(tableView: UITableView, willDisplayHeaderView view: UIView, forSection section: Int) {
let header = view as! UITableViewHeaderFooterView
header.textLabel?.font = UIFont(name: (header.textLabel?.font?.fontName)!, size: 13)!
}
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 30.0
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.items[section]["data"].count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
switch items[indexPath.section]["cell"]{
case "bar" :
let cell = tableView.dequeueReusableCellWithIdentifier("bar", forIndexPath: indexPath) as! ChartCell
cell.itemChart.data = items[indexPath.section]["data"][indexPath.row]
cell.itemChart.total = items[indexPath.section]["total"].intValue
return cell
default :
let cell = tableView.dequeueReusableCellWithIdentifier("issue", forIndexPath: indexPath) as! IssueCell
cell.itemDescription.text = items[indexPath.section]["data"][indexPath.row]["group_name"].stringValue
cell.itemAmount.text = items[indexPath.section]["data"][indexPath.row]["ticket_count"].stringValue
return cell
}
}
func loadReport(sender : AnyObject) {
let closedController = self
self.activityIndicatorView.startAnimating()
Services.getClosedReport({(status : Bool, data : JSON) -> Void in
let tR = data["data"]["summary_by_resolution"]["data"] ?? []
let tP = data["data"]["summary_by_priority"]["data"] ?? []
let tI = data["data"]["summary_by_issue_type"]["data"] ?? []
var totalR = 0
for (_, subJson) in tR {
if totalR < subJson["ticket_count"].intValue{
totalR = subJson["ticket_count"].intValue
}
}
var totalP = 0
for (_, subJson) in tP {
if totalP < subJson["ticket_count"].intValue{
totalP = subJson["ticket_count"].intValue
}
}
let tS = [
JSON(["title" : "By Top 5 Resolution Types", "data" : tR , "cell" : "bar", "total" : JSON(totalR)]),
JSON(["title" : "By Top 5 Issue Types", "data" : tI, "cell" : "issue"]),
JSON(["title" : "By Priority", "data" : tP , "cell" : "bar", "total" : JSON(totalP)]),
]
closedController.items = JSON(tS)
self.itemReportTable.reloadData()
self.activityIndicatorView.stopAnimating()
})
}
I debugged the tableView func for cellForRowAtIndexPath but the data is correct in each one section and row, the cell doesn't call the drawRect func of UIView into the custom cell, this last one repeat another cell in another section
UPDATE :
the Custom UIView is the following:
class ChartView: UIView {
var data : JSON!
var total : Int!
override func drawRect(rect: CGRect) {
let itemView = self
let data = itemView.data
let corePoint = CGPoint(x: 10, y: 10)
let viewWidth = self.bounds.width
let space = CGFloat(10.0)
// MARK : -- Description
let widthL = CGFloat(100.0)
let heightL = CGFloat(20.0)
let text = data["group_name"].stringValue
let rectL = CGRectMake(corePoint.x, corePoint.y, widthL, heightL)
let itemL = UILabel(frame: rectL)
itemL.text = text
itemL.font = UIFont(name: itemL.font.fontName, size: 13.0)
itemView.addSubview(itemL)
// MARK : -- CGRect
let heightR = CGFloat(30.0)
let toY = (heightR - heightL) / 2.0
let yR = corePoint.y - toY
let xR = corePoint.x + widthL + space
let rect = CGRectMake(xR, yR, 0, heightR)
let itemR = UIView(frame: rect)
itemR.backgroundColor = UIColor(red: 49.0/255.0, green: 149.0/255, blue: 169.0/255.0, alpha: 1.0)
itemView.addSubview(itemR)
// MARK : -- Amount
let widthA = widthL
let heightA = heightL
let textA = data["ticket_count"].stringValue
let xA = xR + space
let yA = corePoint.y
let rectA = CGRectMake(xA, yA, widthA, heightA)
let itemA = UILabel(frame: rectA)
itemA.text = textA
itemA.font = UIFont(name: itemA.font.fontName, size: 13.0)
itemView.addSubview(itemA)
// MARK : -- Animation
UIView.animateWithDuration(0.75, delay: 0.0, options: UIViewAnimationOptions.CurveLinear, animations: { () -> Void in
let widthT = (viewWidth - xR - 50) * CGFloat(data["ticket_count"].intValue) / CGFloat(self.total)
itemR.frame = CGRectOffset(CGRectMake(xR, yR, widthT, heightR), 0.0, 0.0)
itemA.frame.origin.x = xA + widthT + 5.0
}, completion: nil)
}
}

Resources