"Generate" labels from data swift - ios

I have
["06:58"]
["07:13", "07:38", "07:53"]
["08:13", "08:38", "08:53"]
["09:13", "09:33", "09:53"]
and I want to show it in tableView as in picture:
every element - it's UILabel, I created class TimeViewCell: UITableViewCell where have property var labels = [UILabel]() but I don't know how to push data from my array in my function:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellTime", for: indexPath) as! TimeViewCell
let showHour = self.infoWripper.sorted(by: { $0.hour < $1.hour })
cell.labelTime.text = showHour[indexPath.row].showHour()
for data in showHour {
print(data.showFullTime()) //here you see my example of data in console
}
return cell
}

I would add a UIStackView to your UITableViewCell. You can add the labels with the text to the UIStackView.
I wrapped your data into an array.
let tableViewData = [["06:58"],
["07:13", "07:38", "07:53"],
["08:13", "08:38", "08:53"],
["09:13", "09:33", "09:53"]]
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellTime", for: indexPath) as! TimeViewCell
cell.configure(data: tableViewData[indexPath.row])
return cell
}
Then, in for your TimeViewCell, you have to add your UIStackView IBOulet (or add it programmatically) and the configure method.
class TimeViewCell: UITableViewCell {
#IBOutlet var labelStackView: UIStackView!
func configure(data: Array<String>) {
for time in data {
let timeLabel = UILabel()
timeLabel.text = time
labelStackView.addArrangedSubview(label)
}
}
}

Related

unable to customize tableView for side menu in swift

I want to add spacing between rows and set the header
here my code is -
#IBOutlet weak var sideMenu: UITableView!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arr.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! TownTalkTableViewCell
cell.logo.setImage(arr[indexPath.row]["icon"] as? UIImage, for: .normal)
cell.grupName.text = array[indexPath.row]["groupname"] as? String
return cell
First Add tableview Delegate and Data Source for both tableview in storyboard by taping control+draging into viewcontroller
Then use the same delegate function to access sidemenu tableview.
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var sideMenu: UITableView!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableview == sideMenu{
return 2
}else{
//this is for tableView
return 3
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if tableview == sideMenu{
//use slide menu tableview cell
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! TownTalkTableViewCell
cell.grupImage.image = array[indexPath.row]["groupImage"] as? UIImage
cell.grupName.text = array[indexPath.row]["groupname"] as? String
return cell
}else{
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! TownTalkTableViewCell
cell.grupImage.image = array[indexPath.row]["groupImage"] as? UIImage
cell.grupName.text = array[indexPath.row]["groupname"] as? String
return cell
}
}
2 ways.
make the view controller data source & delegate for both the tableviews & in the methods add the below check.
if tableview === self.tableview {
//its for table view
return ...
}
// else its for side menu
return ...
Create a separate class (Call it SideMenuTableViewHelper or something) for SideMenu tableView datasource & delegate.
First one is simpler, 2nd one is cleaner for datasource, messier for handling delegate (did select row) methods as they will most likely be triggering code in view controller (which can be done via View controller acting as custom delegate to the SideMenuTableViewHelper). For a beginner, I reckon go with (1).

Adding UIButton to detailTextLabel/right side of UITableView

I'm quite new to Swift and I would like to know what is the easiest and simplest way for me to add in 10 buttons to 10 of my cell rows in my TableViewController.
P.S: It would be nice if the 10 buttons perform differently instead of duplicate.
import UIKit
import FirebaseDatabase
var ref: DatabaseReference?
var databaseHandle: DatabaseHandle?
var postData = [String]()
class TableViewController5: UITableViewController {
override func viewDidLoad() {
super.viewDidLoad()
ref = Database.database().reference() //set the firebase reference
// Retrieve the post and listen for changes
databaseHandle = ref?.child("Posts3").observe(.value, with: { (snapshot) in
postData.removeAll()
for child in snapshot.children {
let snap = child as! DataSnapshot
let key = snap.key
postData.append(key)
}
self.tableView.reloadData()
})
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return postData.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.font = UIFont.init(name: "Helvetica", size: 23)
cell.textLabel?.text = postData[indexPath.row]
return cell
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat
{
return 80
}
}
From what I can understand, you should use prototype cell and add an IBAction in the cell and in that cell you should perform the segue and pass whatever data you need to customise the page you load.
In your tableView(_:cellForRowAt:) method, you can set a tag for the button.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as? prototypeCell
cell.voteButton.tag = indexPath.row
return cell
}
Then in your cell's class, in the IBAction I mentioned earlier, check for the tag and set the data to pass accordingly.
Then in your prepareForSegue:sender: method, just pass the data you want to pass to the next view controller and all should work fine.
Check if it helps You
//Common cell Variable
var cell = UITableViewCell()
//UIButton commonly Declared
var acceptRequest = UIButton()
var declineRequest = UIButton()
My TableView Cell contains two button as shown Accept & Decline
In my tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) I added Handlers for button
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//Cell for dequeuing
cell = self.RequestListTableView.dequeueReusableCell(withIdentifier: "Cell")!
//Used Tags here
//You can Make use of TableViewCell class here and Access Buttons from there
acceptRequest = cell.viewWithTag(4) as! UIButton
//Adding action Handlers for UIbuttons
self.acceptRequest.addTarget(self, action: #selector(RequestListView.AcceptRequest(sender:)), for: .touchUpInside)
return cell
}
my Button handler
func AcceptRequest (sender: UIButton) {
//Dequeue cell with identifier can be ignored
cell = self.RequestListTableView.dequeueReusableCell(withIdentifier: "Cell")!
//Get button position from TableView : Required
let buttonPosition : CGPoint = sender.convert(CGPoint.zero, to: self.RequestListTableView)
//Get index Path of selected Cell from TableView
//Returns Table Cell index same as didSelect
let indexPath : IndexPath = self.RequestListTableView.indexPathForRow(at: buttonPosition)!
//Can be used if you need to update a view
cell = self.RequestListTableView.cellForRow(at: indexPath)!
//Now time to access using index Path
cell.textLabel.text = array[indexPath.row] //Example
}
Can use this Procedure for even single Button or for multiple buttons too
In case if you have more than one button in one cell, this will help you

Custom MKMarkerAnnotationView not displayed correctly in UITableViewCell the first time

I have a tableview where I want to display in UITableViewCell a custom MKMarkerAnnotationView. This tableview is displayed in a dedicated ViewController and the ViewController is in a TabBarController. The second Tab display a Map (but it's not important here).
I have created a class "EdgePinViewAnnotation" that inherits from the MKMarkerAnnotationView
In my storyboard, in the TableView I have added a UITableViewCell that contains some labels and a view with the class "EdgePinViewAnnotation"
In the implementation of a UITableViewCell, I'm initializing my custom "EdgePinViewAnnotation".
Unfortunately when the Cell is displayed in the table, it's a default MKMarkerAnnotationView that is displayed and not my customized "EdgePinViewAnnotation".
When I scroll my TableView and the cell goes out of screen and then it's refreshed it displays my "EdgePinViewAnnotation" correctly.
Why it's not displaying correctly the first time?
Here the code I have implemented for my custom MKMarkerAnnotationView
class EdgePinViewAnnotation: MKMarkerAnnotationView {
override var annotation: MKAnnotation? {
willSet {
if let edgeAnnotation = newValue as? EdgePin {
animatesWhenAdded = true
isDraggable = true
canShowCallout = true
initRenderingProperties(pin: edgeAnnotation)
}
}
}
func initWith(edgePin:EdgePin) {
animatesWhenAdded = false
isDraggable = false
canShowCallout = false
initRenderingProperties(pin: edgePin)
}
func initRenderingProperties(pin edgePin:EdgePin) {
glyphTintColor = UIColor.white
glyphText = "\(edgePin.index)"
markerTintColor = edgePin.renderingColor
}
}
Here the code from my UITableView
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
if let cell = tableView.dequeueReusableCell(withIdentifier: CellId.DistanceConfigurationCellId, for: indexPath) as? DistanceConfigurationTableViewCell {
cell.theLabel.text = findMe.edgePoints[indexPath.row].address
let coord = findMe.edgePoints[indexPath.row].coordinate
cell.coordinates.text = "Lat:\(coord.latitude) / Long:\(coord.longitude)"
cell.theTextField.text = "\(findMe.edgePoints[indexPath.row].distance)"
cell.theTextField.delegate = self
cell.theTextField.tag = indexPath.row
cell.theMarker.initWith(edgePin:findMe.edgePoints[indexPath.row])
return cell
}
} else {
return UITableViewCell()
}
}
class DistanceConfigurationTableViewCell: UITableViewCell {
#IBOutlet weak var theLabel: UILabel!
#IBOutlet weak var coordinates: UILabel!
#IBOutlet weak var theTextField: UITextField!
#IBOutlet weak var theMarker: EdgePinViewAnnotation!
}
I found the solution, even if I don't really understand it.
The MKMarkerAnnotationView must be configured in
tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)
instead of
tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
and then the following code is working and the MKMarkerAnnotationView is displayed correctly in each UITableViewCell
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
if let cell = tableView.dequeueReusableCell(withIdentifier: CellId.DistanceConfigurationCellId, for: indexPath) as? DistanceConfigurationTableViewCell {
cell.theLabel.text = findMe.edgePoints[indexPath.row].address
let coord = findMe.edgePoints[indexPath.row].coordinate
cell.coordinates.text = "Lat:\(coord.latitude) / Long:\(coord.longitude)"
cell.theTextField.text = "\(findMe.edgePoints[indexPath.row].distance)"
cell.theTextField.delegate = self
cell.theTextField.tag = indexPath.row
return cell
}
} else {
return UITableViewCell()
}
}
func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath) {
if let theCell = cell as? DistanceConfigurationTableViewCell {
theCell.theMarker.initWith(edgePin:findMe.edgePoints[indexPath.row])
}
}

Cell doesn't show up properly in table view

I'm using TableView to implement it on ViewController. The problem that I'm facing is the number of cells. Currently the cells supposed to return 2 rows but it only show one row.
What I want to achieve
Storyboard - You can ignore the rest of the components except the tableview
import UIKit
class ViewController: UIViewController {
#IBOutlet var locationTableView: UITableView!
let locationArray = ["Current Location", "Where to"]
let picArray = ["currentPic.png", "whereTo.png"]
override func viewDidLoad() {
super.viewDidLoad()
locationTableView.delegate = self
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return locationArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "GetLocation", for: indexPath)
let location = locationArray[indexPath.row]
let pic = picArray[indexPath.row]
print(location)
if let locationCell = cell as? GetLocationTableViewCell {
locationCell.locationTitle.text = location
locationCell.iconImage.image = pic
}
return cell
}
}
GetLocationTableViewCell.swift
import UIKit
class GetLocationTableViewCell: UITableViewCell {
#IBOutlet var iconImage: UIImageView!
#IBOutlet var locationTitle: UILabel!
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
The outcome is really weird
On Simulator
On my iphone
The number of rows differ on both platforms. What did I do wrong? Is it because of constraints?
Here is problem locationArray[indexPath.section] , picArray[indexPath.section] your section is return 0 so you get two times display "Current Location" you need to use indexPath.row
Try this
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "GetLocation", for: indexPath)
let location = locationArray[indexPath.row]
let pic = picArray[indexPath.row]
print(location)
if let locationCell = cell as? GetLocationTableViewCell {
locationCell.locationTitle.text = location
locationCell.iconImage.image = pic
}
return cell
}
Change your table delegate method like this:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "GetLocation", for: indexPath)
let location = locationArray[indexPath.section]
let pic = picArray[indexPath.row]//replace this line
print(location)
if let locationCell = cell as? GetLocationTableViewCell {
locationCell.locationTitle.text = location
locationCell.iconImage.image = pic
}
return cell
}
You can try like Bellow. You can write array like
let locationArray = [
["textName":"Current Location", "imageName":"currentPic"],
["textName":"Where to", "imageName":"whereTo"]
]
Table view protocol method look like
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 {
return locationArray.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath) CustomCell
cell.textLabel?.text = locationArray[indexPath.row]["textName"]
cell.imageView?.image = UIImage(named: locationArray[indexPath.row]["imageName"]!)
return cell
}
Replace method Following thing in cellRowAtPath
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "GetLocation", for: indexPath)
let location = locationArray[indexPath.row]
let pic = picArray[indexPath.row]
print(location)
if let locationCell = cell as? GetLocationTableViewCell {
locationCell.locationTitle.text = location
locationCell.iconImage.image = pic
}
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 102 //Give cell height
}
As Per your problem i suggest you to manage constraints that your are applying to tableview and Cell. Here i have provided instruction to follow to get solution. Please Manage to follow same instruction on your project Hope this will solve your problem.
1. Manage tableview constraints
a. Pin your tableview to superview from top,left right
b. Set height constraints of tableview.
c. Make outlet of height constraints for tableview so that we can alter value on runtime.
2. Manage Cell constraints
a. Pin your cell contents to superview from top,left, right,bottom
3. manage tableview constraints on runtime
a. set height constraints of tableview view to content size of table view from cell for tow at index path.
self.tableHeight.constant = self.locationTableView.contentSize.height
Full controller Code.
// Controller.swift
// Copyright © 2017 dip. All rights reserved.
//
import UIKit
class ViewController1: UIViewController {
//1:
//Outlet of tableview Height constraints
#IBOutlet weak var tableHeight: NSLayoutConstraint!
#IBOutlet var locationTableView: UITableView!
let locationArray = ["Current Location", "Where to"]
let picArray = ["currentPic.png", "whereTo.png"]
override func viewDidLoad() {
super.viewDidLoad()
locationTableView.delegate = self
}
}
extension ViewController1: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of rows
return locationArray.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "GetLocation", for: indexPath)
let location = locationArray[indexPath.row]
let pic = picArray[indexPath.row]
print(location)
if let locationCell = cell as? GetLocationTableViewCell {
locationCell.locationTitle.text = location
locationCell.iconImage.image = pic
}
//2. set tableivew view height to content Height
self.tableHeight.constant = self.locationTableView.contentSize.height
return cell
}
}
Out Put

How to pass data between UITableViews in NavigationController?

In my first tableViewController has navigationViewController.push(myNextController, animated: true) and I want to segue to another TableViewController. What I am trying to figure out for hours is that when I select a row in my first tableViewController, I want to move to the next tableview. Right now, when I select a row, my next tableVIew has the same data. I want each cell to have differently saved cells
Second table view controller
The title is the navigation title and the myArray is an array:
// globally declared
var dataArray = [String]()
var myArray = [String]()
// this function is in my second table view controller, viewDidLoad()
func data(){
myArray = UserDefaults.standard.stringArray(forKey: "Key")!
dataArray = myArray
}
The dataArray is:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as UITableViewCell
if let getData = UserDefaults.standard.stringArray(forKey:"key") {
cell.textLabel?.text = getData[indexPath.row]
}
tableView.reloadData()
return cell
}
first table view controller
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as UITableViewCell
cell.backgroundColor = UIColorUtil.rgb(rgbValue: 0xFFFFF9)
let getData = UserDefaults.standard.stringArray(forKey: "category")!
let nextViewController = TableView()
nextViewController._titile = getData[indexPath.row]
// so I access myArray from second table view controller because I want to
//get data of each selected cell. But this is a problem.
nextViewController.myArray = getData
self.navigationController?.pushViewController(nextViewController, animated:true)
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as UITableViewCell
if let getData = UserDefaults.standard.stringArray(forKey:"category") {
cell.textLabel?.text = getData[indexPath.row]
}
return cell
}
Why do they have the same cells? How am I able to accomplish this without using a storyboard? I want to programmatically write code. By the way, I am using UITabBar as well. Thanks!

Resources