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

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

Related

tableview last section is scrambled when setting row height to 0 swift

I added an arrow to fold the section when clicked, when I fold the last section (e.g. setting the row height to 0 in cellForRow, all the rows in the last section get mixed up, as can be seen in the image below:
Can anyone suggest any reason why this should happen if I'm setting the height of the row to 0?
Here's the relevant code:
viewForHeaderInSection:
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if section == 0 {
let profileCompletion = clientFields?.profileCompletion ?? 0
headerView.profileComplete.text = "Profile".localized() + " \(profileCompletion)% " + "Complete".localized()
headerView.profileProgress.progress = Float(profileCompletion) * 0.01
headerView.profileProgress.progressTintColor = Constants.Client.getProfileCompletenessColor(profileCompletion)
headerView.delegate = self
headerView.section = section
headerView.isOpen = self.sectionsStatuses[section].shouldDisplaySection
return headerView
}
else {
let height = (section == 0) ? FIRST_HEADER_HEIGHT : HEADER_HEIGHT
let nib = UINib(nibName: "ClientDetailsSectionHeaderCell", bundle: nil)
guard let returnedView = nib.instantiate(withOwner: self, options: nil)[0] as? ClientDetailsSectionHeaderCell else {
return UIView()
}
returnedView.delegate = self
returnedView.section = section
returnedView.isOpen = self.sectionsStatuses[section].shouldDisplaySection
returnedView.frame = CGRect(x: 0, y: 0, width: view.frame.size.width, height: height)
returnedView.heightConstraint.constant = height
returnedView.mainView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
returnedView.mainView.backgroundColor = Constants.ParentForm.headerBgColor
// Draw separators
if DRAW_SECTION_SEPARATORS || DRAW_SECTION_TOP_SEPARATOR {
returnedView.createTopSeparator(color: Constants.ParentForm.separatorColor)
}
if DRAW_SECTION_SEPARATORS || DRAW_SECTION_BOTTOM_SEPARATOR {
returnedView.createBottomSeparator(color: Constants.ParentForm.separatorColor)
}
if isSectionTitleHidden == false {
let xOffset = HEADER_X_OFFSET
let yOffset = section == 0 ? FIRST_HEADER_Y_OFFSET : HEADER_Y_OFFSET
returnedView.title.frame = CGRect(x: xOffset, y: yOffset, width: view.frame.size.width - xOffset, height: height - yOffset)
returnedView.title.text = self.sectionsArray[section].uppercased().localized()
returnedView.title.font = Constants.ParentForm.headerFont
returnedView.title.textColor = Constants.ParentForm.headerTextColor
returnedView.title.sizeToFit()
}
return returnedView
}
}
heightForRow
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
if sectionsStatuses[indexPath.section].shouldDisplaySection {
return super.tableView(tableView, heightForRowAt: indexPath)
}
return CGFloat(0)
}
cellForRow
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if self.sectionsArray[indexPath.section] != "ADDRESSES" {
if let clientFields = self.clientFields {
self.dataMap = Utils.convertObjectToMap(item: clientFields)
let birthdayDate = clientFields.birthdayDateString
self.dataMap["birthdayDate"] = birthdayDate
let createdDate = clientFields.createdDateString
self.dataMap["createdDate"] = createdDate
}
}
else {
if let clientAddresses = self.clientAddresses, clientAddresses.count > 0 {
self.dataMap = Utils.convertObjectToMap(item: clientAddresses[Int(floor(Double(indexPath.row) / 8.0))])
}
}
return super.tableView(tableView, cellForRowAt: indexPath)
}
protocol function
func openCloseSection(openSection: Bool, section: Int) {
self.sectionsStatuses[section].shouldDisplaySection = openSection
self.tableView.reloadData()
}
ClientDetailsSectionHeaderCell
import UIKit
protocol SectionViewerProtocol {
func openCloseSection(openSection: Bool, section: Int)
}
class ClientDetailsSectionHeaderCell: UITableViewCell {
#IBOutlet weak var mainView: UIView!
#IBOutlet weak var heightConstraint: NSLayoutConstraint!
#IBOutlet weak var accessoryButton: UIButton!
#IBOutlet weak var title: UILabel!
var section = 0
var delegate: SectionViewerProtocol?
var isOpen: Bool? {
didSet {
if let isOpen = self.isOpen {
accessoryButton.setImage(UIImage(named: isOpen ? "fill588": "fill589"), for: .normal)
}
}
}
override func awakeFromNib() {
super.awakeFromNib()
}
#IBAction func openCloseSection(_ sender: UIButton) {
if let isOpen = self.isOpen {
self.isOpen = !isOpen
delegate?.openCloseSection(openSection: !isOpen, section: section)
}
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
}
Try setting clipsToBounds of your cell or any enclosing UIView to true.

iOS Charts in a tableview: correct use of a delegate and global zoom

I'm using iOS Charts in my project, and I've been able to embed my charts in a tableview (every cell will contain a chart, up to maximum number of possible entries to keep under control the performance).
I would like to use the 'touchMatrix' feature in order zoom the x axis on one chart (in a cell) and have all of the other visible charts to follow along with the zoom scale (the x axis), possibly with a vertical axis showing the Y value on every visible chart for that x coordinate, but I'm kind of stuck, since even the delegate methods such as 'chartValueNothingSelected' are not working (I probably got it wrong when I tried to associate the delegate to the chartview, since the chart it's embedded in the cell, and it's not the tipical case of associating the delegate to a view controller).
Assigning the delegate to the cell just doesn't seem to be working.
Any tips?
Thanks in advance.
Here is the code:
import UIKit
import Charts
class CustomChartCell: UITableViewCell, ChartViewDelegate {
#IBOutlet weak var lineChartView: LineChartView!
var yValues = [Double]()
var xValues = [Double]()
var chartColor = UIColor()
var channelName = ""
var yMin = 0.0
var yMax = 0.0
var yAvg = 0.0
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
self.lineChartView.noDataFont = UIFont.systemFont(ofSize: 28.0)
self.lineChartView.noDataText = NSLocalizedString("No chart data available", comment: "No Chart Data Available Title")
self.lineChartView.xAxis.labelPosition = .bottom
self.lineChartView.highlightPerTapEnabled = true
self.lineChartView.autoScaleMinMaxEnabled = true
self.lineChartView.chartDescription?.enabled = true
self.lineChartView.dragEnabled = true
self.lineChartView.setScaleEnabled(true)
self.lineChartView.pinchZoomEnabled = false
self.lineChartView.xAxis.gridLineDashLengths = [10, 10]
self.lineChartView.xAxis.gridLineDashPhase = 0
self.lineChartView.leftAxis.gridLineDashLengths = [5, 5]
self.lineChartView.leftAxis.drawLimitLinesBehindDataEnabled = true
self.lineChartView.rightAxis.enabled = false
let marker = BalloonMarker(color: UIColor(white: 180/255, alpha: 1),
font: .systemFont(ofSize: 12),
textColor: .white,
insets: UIEdgeInsets(top: 8, left: 8, bottom: 20, right: 8))
marker.chartView = self.lineChartView
marker.minimumSize = CGSize(width: 80, height: 40)
self.lineChartView.marker = marker
self.lineChartView.legend.form = .line
self.lineChartView.delegate = self
}
func setChart(_ xValues: [Double], _ yValues: [Double]) {
var dataEntries: [ChartDataEntry] = []
for i in 0..<xValues.count {
let dataEntry = ChartDataEntry(x: xValues[i], y: yValues[i])
dataEntries.append(dataEntry)
}
let chartDataSet = LineChartDataSet(values: dataEntries, label: self.channelName)
let chartData = LineChartData(dataSets: [chartDataSet])
chartDataSet.setColor(self.chartColor.withAlphaComponent(0.5))
chartDataSet.drawCirclesEnabled = false
chartDataSet.lineWidth = 2
chartDataSet.drawValuesEnabled = false
chartDataSet.highlightEnabled = true
chartDataSet.drawFilledEnabled = false
lineChartView.data = chartData
self.lineChartView!.leftAxis.axisMinimum = self.yValues.min()! - self.yValues.max()!*0.2
self.lineChartView!.leftAxis.axisMaximum = self.yValues.max()! + self.yValues.max()!*0.2
self.lineChartView!.chartDescription?.font = UIFont.systemFont(ofSize: 11.0)
self.lineChartView!.chartDescription?.text = "y_min: \(self.yMin), y_max: \(self.yMax), y_avg: \(self.yAvg)"
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
class ChartTableViewController: UITableViewController, ChartViewDelegate {
var dataSet : [LineChartData] = []
let data = LineChartData()
var channelNames : [String] = []
let channelColors = [UIColor.blue, UIColor.green, UIColor.red,
UIColor.orange, UIColor.purple, UIColor.darkGray]
var averageValues : [Double] = []
var minValues : [Double] = []
var maxValues : [Double] = []
var xValues : [[Double]] = []
var yValues : [[Double]] = []
#IBAction func chartZoomOut(_ sender: Any) {
tableView?.visibleCells.forEach { cell in
if let cell = cell as? CustomChartCell {
cell.lineChartView.zoomOut()
}
}
}
#IBAction func chartZoom100(_ sender: Any) {
tableView?.visibleCells.forEach { cell in
if let cell = cell as? CustomChartCell {
cell.lineChartView.zoomToCenter(scaleX: 0, scaleY: 0)
}
}
}
#IBAction func chartZoomIn(_ sender: Any) {
tableView?.visibleCells.forEach { cell in
if let cell = cell as? CustomChartCell {
cell.lineChartView.zoomIn()
}
func chartValueNothingSelected(_ chartView: ChartViewBase) {
chartView.chartDescription?.text = ""
}
func chartScaled(chartView: ChartViewBase, scaleX: CGFloat, scaleY: CGFloat) {
print(scaleX)
print(scaleY)
}
func chartValueSelected(_ chartView: ChartViewBase, entry: ChartDataEntry, highlight: Highlight) {
chartView.chartDescription?.text = "x: \(entry.x), y: \(entry.y), y_min: \(minValues[0]), y_max: \(maxValues[0]), y_avg: \(averageValues[0])"
chartView.reloadInputViews()
}
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.isEditing = false
self.editButtonItem.title = NSLocalizedString("Edit", comment: "Edit Title")
self.tableView.separatorColor = UIColor.clear
self.navigationItem.rightBarButtonItem = self.editButtonItem
self.loadFile()
self.tableView.reloadData()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tableView.isEditing = false
self.editButtonItem.title = NSLocalizedString("Edit", comment: "Edit Title")
}
// MARK: Load Chart File
func loadFile() {
// Try to load the file content
do {
// get the documents folder url
let documentDirectoryURL = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
// create the destination url for the text file to be saved
let fileDestinationUrl = documentDirectoryURL.appendingPathComponent(Constants.CHART_FILE_NAME)
// reading from disk
do {
let file = try String(contentsOf: fileDestinationUrl)
let newFile = file.replacingOccurrences(of: "\r", with: "") // Get rid of additional new lines
let cleanChannels = self.generateCleanChannels(newFile) // // a function used to retrieve the channels from the file (since the file it's not a plain CSV file but something different)
channelNames.removeAll()
dataSet.removeAll()
channelNames = self.getChannelNames(newFile) // a function used to retrieve the channel names from the file (since the file it's not a plain CSV file but something different)
var lineChartEntry = [ChartDataEntry]()
data.clearValues()
for (index,channel) in cleanChannels.enumerated() {
if (index <= Constants.MAX_CHART_CHANNELS) {
let csvImage = CSV(string: channel, delimiter: ";")
var y_max = 0.0
var firstXValueSampled : Bool = false
var firstXValue : Double = 0.0
var average = 0.0
var min = 0.0
var max = 0.0
var count = 0
var new_xValues : [Double] = []
var new_yValues : [Double] = []
csvImage.enumerateAsDict { dict in
print(dict["X_Value"]!)
new_xValues.append(Double(dict["X_Value"]!)!)
new_yValues.append(Double(dict["Y_Value"]!)!)
if !firstXValueSampled {
firstXValueSampled = true
firstXValue = Double(dict["X_Value"]!)!
}
average = average + Double(dict["Y_Value"]!)!
count = count + 1
let value = ChartDataEntry(x: (Double(dict["X_Value"]!)! - firstXValue), y: Double(dict["Y_Value"]!)! )
lineChartEntry.append(value)
if Double(dict["Y_Value"]!)! > max {
max = Double(dict["Y_Value"]!)!
}
if Double(dict["Y_Value"]!)! < min {
min = Double(dict["Y_Value"]!)!
}
if Double(dict["Y_Value"]!)! > y_max {
y_max = Double(dict["Y_Value"]!)!
}
}
xValues.append(new_xValues)
yValues.append(new_yValues)
average = average / Double(count)
averageValues.append(average)
minValues.append(min)
maxValues.append(max)
let line = LineChartDataSet(values: lineChartEntry, label: channelNames[index])
line.axisDependency = .left
line.colors = [channelColors[index]] // Set the color
line.setColor(channelColors[index].withAlphaComponent(0.5))
line.setCircleColor(channelColors[index])
line.lineWidth = 2.0
line.circleRadius = 3.0
line.fillAlpha = 65 / 255.0
line.fillColor = channelColors[index]
line.highlightColor = UIColor(red: 244/255, green: 117/255, blue: 117/255, alpha: 1)
line.drawCircleHoleEnabled = false
line.highlightLineWidth = 2.0
line.drawHorizontalHighlightIndicatorEnabled = true
data.setValueFont(.systemFont(ofSize: 9))
data.addDataSet(line) // Add the line to the dataSet
let newData = LineChartData()
newData.setValueFont(.systemFont(ofSize: 9))
newData.addDataSet(line)
dataSet.append(newData)
}
}
} catch let error as NSError {
print("error loading contentsOf url \(fileDestinationUrl)")
print(error.localizedDescription)
}
} catch let error as NSError {
print("error getting documentDirectoryURL")
print(error.localizedDescription)
}
}
// MARK: - Table view data source
override func numberOfSections(in tableView: UITableView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return dataSet.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellIdentifier = "CustomChartCell"
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier,
for: indexPath) as! CustomChartCell
cell.lineChartView.delegate = self
if dataSet.count > 0 {
cell.xValues = xValues[indexPath.row]
cell.yValues = yValues[indexPath.row]
cell.chartColor = channelColors[indexPath.row]
cell.channelName = channelNames[indexPath.row]
cell.yMin = minValues[indexPath.row]
cell.yMax = maxValues[indexPath.row]
cell.yAvg = averageValues[indexPath.row]
cell.lineChartView.leftAxis.axisMaximum = cell.yValues.max()! + 1
cell.lineChartView.leftAxis.axisMinimum = cell.yValues.min()! - 1
cell.setChart(cell.xValues, cell.yValues)
} else {
cell.lineChartView.clearValues()
}
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
//tableView.deselectRow(at: indexPath, animated: true)
let selectedCell = tableView.cellForRow(at: indexPath) as! CustomChartCell
selectedCell.contentView.backgroundColor = UIColor.lightGray
//let currentMatrix = selectedCell.lineChartView.viewPortHandler.touchMatrix
//let selectedCell:UITableViewCell = tableView.cellForRow(at: indexPath)! as! CustomChartCell
//selectedCell.contentView.backgroundColor = UIColor.lightGray
//let currentMatrix = selectedCell.lineChartView.viewPortHandler.touchMatrix
/*
tableView.visibleCells.forEach { cell in
if let cell = cell as? CustomChartCell {
if cell.channelName != selectedCell.channelName {
cell.lineChartView.viewPortHandler.refresh(newMatrix: currentMatrix, chart: cell.lineChartView, invalidate: true)
}
}
}
*/
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 250
}
override func tableView(_ tableView: UITableView, editingStyleForRowAt indexPath: IndexPath) -> UITableViewCell.EditingStyle {
return .none
}
override func tableView(_ tableView: UITableView, shouldIndentWhileEditingRowAt indexPath: IndexPath) -> Bool {
return false
}
override func setEditing (_ editing:Bool, animated:Bool)
{
super.setEditing(editing,animated:animated)
if (self.isEditing) {
//self.editButtonItem.title = "Editing"
self.editButtonItem.title = NSLocalizedString("Done", comment: "Done Title")
}
else {
self.editButtonItem.title = NSLocalizedString("Edit", comment: "Edit Title")
}
}
override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let movedObject = self.dataSet[sourceIndexPath.row]
dataSet.remove(at: sourceIndexPath.row)
dataSet.insert(movedObject, at: destinationIndexPath.row)
}
}

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

TableView's textLabel height according to content

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;

Swift - Cannot pass dictionary into custom cell

I have a controller which has a table with four cells. Each of these custom cells contain another table, in which I display row data.
Take a look at the screenshot:
Here is how I init custom cell and pass data to it:
func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
let cell = tableView.dequeueReusableCellWithIdentifier("DashCell", forIndexPath: indexPath) as! DashCell
cell.dictionary = dataArray[indexPath.row] as Dictionary!
cell.sectionTitle = sectionTitles[indexPath.row]
cell.titlesArray = columnTitles[indexPath.row]
return cell
}
And here is my custom cell code:
#objc(DashCell) class DashCell: UITableViewCell, UITableViewDelegate, UITableViewDataSource {
#IBOutlet weak var tableViewInsideCell: UITableView!
var dictionary: Dictionary<String, String>?
var sectionTitle: String?
var titlesArray: Array<String>?
var screenWidth: CGFloat!
var data: Array<String> = []
override init(style: UITableViewCellStyle, reuseIdentifier: String!) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required init(coder aDecoder: NSCoder) {
println("Dictionary in cell \(dictionary)")
let firstColumn: String = dictionary!["FirstColumn"]!
let secondColumn: String = dictionary!["SecondColumn"]!
let thirdColumn: String = dictionary!["ThirdColumn"]!
let fourthColumn: String = dictionary!["FourthColumn"]!
let fifthColumn: String = dictionary!["FifthColumn"]!
var sixthColumn: String? = dictionary!["SixthColumn"]!
var sevenColumn: String? = dictionary!["SeventhColumn"]!
data.append(firstColumn)
data.append(secondColumn)
data.append(thirdColumn)
data.append(fourthColumn)
data.append(fifthColumn)
if sixthColumn != nil {
data.append(sixthColumn!)
}
if sevenColumn != nil {
data.append(sevenColumn!)
}
super.init(coder: aDecoder)
}
override func awakeFromNib() {
super.awakeFromNib()
screenWidth = UIScreen.mainScreen().bounds.size.width
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
}
func addTitleLabel(text: String, withOffset offset: CGFloat) -> UILabel {
var label: UILabel = UILabel(frame: CGRectMake(15 + offset, 23, screenWidth / CGFloat(titlesArray!.count), 17))
label.font = UIFont.boldSystemFontOfSize(10.0)
label.numberOfLines = 1
label.backgroundColor = UIColor.clearColor()
label.textAlignment = NSTextAlignment.Left
label.text = text
return label
}
func addRowLabel(text: String, withOffset offset: CGFloat) -> UILabel {
var label: UILabel = UILabel(frame: CGRectMake(15 + offset, 2, screenWidth / CGFloat(data.count) - 10, 17))
label.font = UIFont.systemFontOfSize(9.0)
label.numberOfLines = 1
label.backgroundColor = UIColor.clearColor()
label.textAlignment = NSTextAlignment.Left
label.text = text
return label
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 8
}
func tableView(tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
var headerView: UIView = UIView()
var sectionTitleLabel: UILabel = UILabel(frame: CGRectMake(15, 3, screenWidth, 20))
sectionTitleLabel.font = UIFont.systemFontOfSize(14.0)
sectionTitleLabel.numberOfLines = 1
sectionTitleLabel.backgroundColor = UIColor.clearColor()
sectionTitleLabel.textAlignment = NSTextAlignment.Left
var lableText: String = sectionTitle!
sectionTitleLabel.text = lableText.uppercaseString
sectionTitleLabel.textColor = UIColor(red: 110 / 255.0, green: 110 / 255.0, blue: 115 / 255.0, alpha: 1.0)
sectionTitleLabel.text!.uppercaseString
headerView.addSubview(sectionTitleLabel)
var offset: CGFloat = screenWidth / CGFloat(titlesArray!.count)
for var j: Int = 0; j < titlesArray!.count; j++ {
let headerLabel: UILabel = self.addTitleLabel(titlesArray![j], withOffset: offset * CGFloat(j))
headerView.addSubview(headerLabel)
}
return headerView
}
func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 40
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 22
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var CellIdentifier: String = "Cell"
var cell = tableView.dequeueReusableCellWithIdentifier(CellIdentifier) as? UITableViewCell
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.Value1, reuseIdentifier: CellIdentifier)
}
var offset: CGFloat = screenWidth / CGFloat(data.count)
for var j = 0; j < data.count; j++ {
let string: String = data[j] as String
var label: UILabel = self.addRowLabel(string, withOffset: offset * CGFloat(j))
cell!.contentView.addSubview(label)
}
return cell!
}
The problem is that dictionary variable always comes nil, although sectionTitle and titlesArray are filled with data. Why is it so?
[UPDATE] The dictionary is set like this in parent view controller in viewDidLoad:
var one: Dictionary<String, String> = ["FirstColumn" : "R-L-1776-07-2015-1", "SecondColumn" : "Aaron Bloch", "ThirdColumn" : "$5,000.00", "FourthColumn" : "153 E 32 STREET", "FifthColumn" : "Open"]
var two: Dictionary<String, String> = ["FirstColumn" : "R-L-1776-07-2015-4", "SecondColumn" : "Test User", "ThirdColumn" : "$500.00", "FourthColumn" : "635 W 42nd St", "FifthColumn" : "Yes"]
var three: Dictionary<String, String> = ["FirstColumn" : "Bruno", "SecondColumn" : "Ricciotti", "ThirdColumn" : "bruno#bondnewyork.com", "FourthColumn" : "917-699-7151", "FifthColumn" : "Some text"]
var four: Dictionary<String, String> = ["FirstColumn" : "#448438", "SecondColumn" : "Resid. Rent", "ThirdColumn" : "$345.00", "FourthColumn" : "Studio", "FifthColumn" : "1", "SixthColumn" : "Hamilton Heights", "SeventhColumn" : "Aaron Bloch"]
dataArray = [one, two, three, four]
dataArray is inited like this:
var dataArray: Array<Dictionary<String, String>> = []

Resources