How to add a space between the subtitle and a comma between some of the words? - swift

How would I add a space between the subtitle and a comma between some of the words? I'm using swift 3.
override
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")!
let selectedItem = matchingItems[indexPath.row].placemark
cell.textLabel?.text = selectedItem.name
cell.detailTextLabel?.text = selectedItem.subThoroughfare! + selectedItem.thoroughfare!
+ selectedItem.locality! + selectedItem.administrativeArea! + selectedItem.postalCode!
return cell
}

The reason you are getting crash is because you are force wrapping the optional property of CLPlacemark, also if you want to join address try something like this. Make array of String? with all optional property that you are currently trying to make address without ! after that flatMap array to ignore the nil and then simply joined the array with separator ,.
override public tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "cell")!
let selectedItem = matchingItems[indexPath.row].placemark
cell.textLabel?.text = selectedItem.name
let addressArray = [selectedItem.subThoroughfare, selectedItem.thoroughfare, selectedItem.locality, selectedItem.administrativeArea, selectedItem.postalCode].flatMap({$0})
if addressArray.isEmpty {
cell.detailTextLabel?.text = "N/A" //Set any default value
}
else {
cell.detailTextLabel?.text = addressArray.joined(separator: ", ")
}
return cell
}

You are using forced unwrap on values and there is a possibility that one of the value is nil due to which you are getting the crash when code is trying to concatenate string to nil values.

Related

Fatal error: Index out of range when filling cells

I am getting the this error: Index out of range when trying to fill cells out of a table, any idea why this happens?
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: VCInstanciasCell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! VCInstanciasCell
cell.siteLabel.text = String?([arrayItinerario[indexPath.section]][indexPath.row].ubicacion!) ?? ""
cell.txtLabel.text = String?([arrayItinerario[indexPath.section]][indexPath.row].maquinaTipo!) ?? ""
cell.orderLabel.text = String?([arrayItinerario[indexPath.section]][indexPath.row].fma!) ?? ""
cell.codeLabel.text = String?([arrayItinerario[indexPath.section]][indexPath.row].iso!) ?? ""
cell.newLabel.text = String?([arrayItinerario[indexPath.section]][indexPath.row].instanciaID!) ?? ""
cell.setLeftUtilityButtons(self.leftButtons(), withButtonWidth: 50.0)
return cell
}
the error is at cell.siteLabel.text = String?([arrayItinerario[indexPath.section]][indexPath.row].ubicacion!) ?? "" in indexPath.Row
It is quite hard to answer this question without seeing how arrayItinerario is defined, and what triggers the cellForRow (when is the timing you're calling reloadData)
But first of all, I'd try to simplify your code, it will make it easier to understand where the crash comes from, as you're using force unwrapped and also cannot know in which of the row/section you get the index out of range.
I added some checks + guards + prints, it will explain my answer + make your testing easier:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: VCInstanciasCell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! VCInstanciasCell
if let value = value(for: indexPath) {
cell.siteLabel.text = ""
if let ubicacion = value.ubicacion {
cell.siteLabel.text = String(ubicacion)
}
// and so on
} else {
print("couldn't get value for indexPath:\(indexPath)")
}
return cell
}
func value(for indexPath: IndexPath) -> SomeObject? {
let section = indexPath.section
let row = indexPath.row
guard section < arrayItinerario.count else {
print("section \(section) is out of range for list with count: \(arrayItinerario.count)")
return nil
}
let list = arrayItinerario[section]
guard row < list.count else {
print("row \(row) is out of range for list with count: \(list.count)")
return nil
}
return list[row]
}

how to get the value of a label placed on table view cell

I have a number of cells in my tableview each containing different label values
when i tap on the cell I want that value of label in next view controller. how do I get that?
public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as!
MeetingsListTableViewCell
if self.meeting.count > 0{
let eachMeeting = self.meeting[indexPath.row]
cell.meetingTimeLabel?.text = (eachMeeting["time"] as? String) ?? "No Time"
cell.meetingDateLabel?.text = (eachMeeting["date"] as? String) ?? "No Date"
cell.idLabel?.text = (eachMeeting["id"] as? String) ?? "NO ID"
}
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let vc = UIStoryboard.init(name: "Main4", bundle:Bundle.main).instantiateViewController(withIdentifier: "MeetingDetailVC") as? MeetingDetailVC
self.navigationController?.pushViewController(vc!, animated: true)
}
i want that idLabel value to send in the next viewcontroller
Get the data always from the data source array meeting, never from the cell, for example
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let aMeeting = self.meeting[indexPath.row]
let identifier = aMeeting["id"] as! String
guard let vc = UIStoryboard.init(name: "Main4", bundle:Bundle.main).instantiateViewController(withIdentifier: "MeetingDetailVC") as? MeetingDetailVC else { return }
vc.identifier = identifier
self.navigationController?.pushViewController(vc, animated: true)
}
The code assumes that there is a property identifier in MeetingDetailVC
Notes:
For better readability you should name arrays in plural form (meetings).
The check self.meeting.count > 0 is pointless, cellForRowAt is not being called if the data source array is empty.
It's highly recommended to use a custom struct as data source rather than an array of dictionaries. You will get rid of all those annoying type casts.
Tapped cell can be accessed in didSelectRowAt function of tableVeiw. Extract tableView cell and cast int into your custom cell, after casting you can directly access value of lableId, add an optional property in MeetingDetailVC and pass value to it.

Getting a indexPath.row with a matching value

So, I have two Json requests from the same API with the difference, that one is from today and the other one from yesterday. I have them displayed in "MyCell" in my TableView and the result is this.
This is the code :
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as! CustomTableViewCell
let today = today[indexPath.row]
let yesterday = yesterday[indexPath.row]
let nameOfThe place = today.local
let salesToday = today.sales
let nameOfThePlaceYesterday = yesterday.local
let salesYesterday = yesterday.sales
}
So far, so good. Thats whats I wanted. The problem start when some places havent open yesterday( for example A and B). I get this:
Whats happening is, since there isnt the same "numberOfRowsInSection" for both days, it just populates cell in order but mismatching places. Question:
How do I get "indexPath.row" with a matching value of the other indexPath.row. In this case it would be a name of the place.
Thank you
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as! CustomTableViewCell
let today = today[indexPath.row]
let nameOfThe place = today.local
let salesToday = today.sales
if let yesterday = yesterday[safe: indexPath.row] {
let nameOfThePlaceYesterday = yesterday.local
let salesYesterday = yesterday.sales
}
}

Thread 1: Fatal error: Index out of range from tableViewCell

I have error says "Thread 1: Fatal error: Index out of range".
on
cell.titleLabel.text = cellDataArrayPoster[indexPath.row].jobTitlePoster as? String
please notice that I'm using two different cells,
as prototypeCells. Moreover, they both have different identifier.
both arrays have getting their data from firebase.
var cellDataArray = [cellData]()
var cellDataArrayPoster = [cellDataPoster]()
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellDataArray.count + cellDataArrayPoster.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let index = indexPath.row
if index == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! infoCell
cell.titleLabel.text = cellDataArray[indexPath.row].jobTitle as? String
cell.companyLabel.text = cellDataArray[indexPath.row].companyName
//cell.timeStampLabel.text = cellDataArray[indexPath.row].createdAt.calenderTimeSinceNow()
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "cellPoster", for: indexPath) as! infoCellPoster
cell.titleLabel.text = cellDataArrayPoster[indexPath.row].jobTitlePoster as? String
//cell.timeStampLabel.text = cellDataArray[indexPath.row].createdAt.calenderTimeSinceNow()
return cell
}
}
You misunderstood the concept of table view delegate methods. It is good to read more from the documentation.
My general rule of thumb is to always use only 1 array as data source for table view to avoid index out of range situations.
In your particular case the error is saying all about it - you are trying to reach index number that is out of range of the array. The easiest workaround will be to combine the two arrays in one, and have some sort of inheritance between the objects so they can fit.

Displaying two reusable cells in tableview - Swift 3

I have two custom reusable table view cells in my table view. The first cell, I would like it to be present at all times. The second cell and beyond, are returning a count that is being passed from mysql database.
// return the amount of cell numbers
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return posts.count
}
// cell config
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.row < 1 {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! InfoCell
//set the data here
return cell
} else {
let Postcell = tableView.dequeueReusableCell(withIdentifier: "PostCell", for: indexPath) as! PostCell
let post = posts[indexPath.row]
let image = images[indexPath.row]
let username = post["user_username"] as? String
let text = post["post_text"] as? String
// assigning shortcuts to ui obj
Postcell.usernameLbl.text = username
Postcell.textLbl.text = text
Postcell.pictureImg.image = image
return Postcell
}
} // end of function
My first cell is there and so are the post.count, but for some reason the posts.count is missing one post and I believe this is because of the first cell. Can anybody help me with this? thanks in advance.
You need to adjust the value returned from numberOfRowsInSection to account for the extra row. And you would need to adjust the index used to access values from your posts array to deal with the extra row.
But a much better solution is to use two sections. The first section should be your extra row and the second section would be your posts.
func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if section == 0 {
return 1
} else {
return posts.count
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath) as! InfoCell
//set the data here
return cell
} else {
let Postcell = tableView.dequeueReusableCell(withIdentifier: "PostCell", for: indexPath) as! PostCell
let post = posts[indexPath.row]
let image = images[indexPath.row]
let username = post["user_username"] as? String
let text = post["post_text"] as? String
// assigning shortcuts to ui obj
Postcell.usernameLbl.text = username
Postcell.textLbl.text = text
Postcell.pictureImg.image = image
return Postcell
}
}