Getting list of events from an array - swift

I want to print out a list of events in one day selected on a calendar made using FSCalendar. So far I have written this in my app:
while counter2 < noOfEvents{
print("counter[counter2]: ", counter[counter2])
cell.eventName.text = eventsArray[counter[counter2]].nameOfEvent
cell.eventDescription.text = eventsArray[counter[counter2]].descriptionEvent
cell.countryName.text = eventsArray[counter[counter2]].country
cell.eventDate.text = eventsArray[counter[counter2]].dateEvent
cell.eventTime.text = eventsArray[counter[counter2]].timeEvent
print("eventsArray[counter[counter2]].nameOfEvent: ", eventsArray[counter[counter2]].nameOfEvent)
counter2 += 1
}
My question is how to make the list display both events and not just the latest one. In the logs both are clearly there but in the actual list on the app only the latest one is displayed. Any helpp is appreciated

// MARK: - Table view data source
// Set the number of sections in the table view (assumes 1 if simple list of events)
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
// Set the number of events
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return eventsArray.count
}
// Provide each cell when requested
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "CalendarCell2", for: indexPath) as! CalendarCell2
// Configure the cell...
if let event = eventsArray[indexPath.row] {
// Set the appropriate elements in the cell
}
return cell
}
Note that if the number of events changes you'll want to update the table view by the reloadData() function.

Related

Duplicates in tableview section Swift

I amm trying to put some datas into categories into a tableView. Pizzas into pizza category, burgers into burger etc, but i have every item duplicate ( Look here Picture . What can be the problem ?
Struct :
struct Food {
var photoKeyRestaurant: String
var foodName: String
var foodDescription: String
var restaurantName: String
var priceFood: Int
var typeFood: String
}
Table View
func numberOfSections(in tableView: UITableView) -> Int {
return food.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return food[section].foodName.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "FoodTableViewCell", for: indexPath) as! FoodTableViewCell
// cell.delegate = self
let mancare = food[indexPath.section]
let storageRef = Storage.storage().reference()
let photoRef = storageRef.child(mancare.photoKeyRestaurant)
cell.foodImage.sd_setImage(with: photoRef)
cell.descriptionLabel.text = mancare.foodDescription
cell.foodNameLabel.text = mancare.foodName
cell.priceLabel.text = "\(mancare.priceFood) lei"
cell.foodImage.layer.borderWidth = 1
cell.foodImage.layer.masksToBounds = false
cell.foodImage.layer.borderColor = UIColor.black.cgColor
cell.foodImage.layer.cornerRadius = cell.foodImage.frame.height/2
cell.foodImage.clipsToBounds = true
//Fac ca imaginea sa fie cerc - finish
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 120
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return food[section].typeFood
}
If somone will ask, im retrieving the data from the firestore, but there s no problem there, because the data is retrieved succesfuly.
Anyone know what can be the problem ? Thanks
It is interesting that your code for cellForRowAt never actually mentions the indexPath.row. It refers only to the indexPath.section. How can you get and display data corresponding to this row, which you are supposed to configure in cellForRowAt if you do not in some way refer to the question of what row this is?
Perhaps there is some other mechanism going on that I don't see, but it seems to me that this one fact alone explains why each section just shows the same data over and over rather than different data for each row.
You have 2 big problems with this code.
You have the wrong array of data fo sections.
in the func cellForRowAt you cant return indexPath.section.
With first. You need to use 2-dimensional arrays like:
var foodCategorys: [FoodCategory] = [[categoryName, Food],[categoryName, Food]]
So you need another struct to contain this 2-dimensional array:
struct FoodCategory {
var categoryName: String
var listFood: [Food] = [] // Food is the struct that you currently have
}
So the data will display in tableView is an array FoodCategory. With numberOfSections will return a count of an array FoodCategory. And numberOfRowsInSection will return a count of a listFood into FoodCatogory.
func numberOfSections(in tableView: UITableView) -> Int {
return foodCategorys.count //array of listFood
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return foodCategorys[section].listFood.count
}
And second, in cellForRowAt, when you want to get the index of list data. you need to call foods[indexPath.section].listFood[indexPath.row]. The func need row not section
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "FoodTableViewCell", for: indexPath) as! FoodTableViewCell
//cell.delegate = self
let mancare = foods[indexPath.section].listFood[indexPath.row] //Remeber that, the array food we are using in this line is array of FoodCategory
I think you need to research with key word "section in uitableview swift", or watch this video https://www.youtube.com/watch?v=AHY09z-XS9s
So, that all. I hope you will understand how tableview and section work

index is out of range after filtering an array

I am trying to filter a song array so it only has songs where the song artistName is the same as ArtistName(Which is always the selected artist). When I run my app it throws an Fatal error: Index out of range even though in my debug console artistSongs has 4 elements. I don't understand how id be getting this crash.
override func viewDidLoad() {
super.viewDidLoad()
retriveData()
//Register nib
topSongTableView.register(TopSongTableViewCell.nib(), forCellReuseIdentifier: TopSongTableViewCell.topSongCell)
ArtistPicture.image = artistCover
ArtistLabel.text = ArtistName
//Assign TableView to self
topSongTableView.delegate = self
topSongTableView.dataSource = self
}
//Define number of rows in topSongsTableView
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 5
}
// songs of artist
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TopSongTableViewCell", for: indexPath) as! TopSongTableViewCell
let artistSongs = songs.filter{ $0.artistName == ArtistName }
print(artistSongs)
cell.TopSongLabel.text = artistSongs[indexPath.row].cleanName //CASH
cell.SongImage.image = UIImage(named: artistSongs[indexPath.row].cover)
return cell
}
Your problem is that your tableView topSongTableView expects to display 5 rows (you hard coded it) but when you're dequeuing your cells, you also filter artistSongs at the same time (it shouldn't be done here) and this produces in your case an array with less than 5 elements (4 in your case).
So here in func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell, you're trying to dequeue more cells than elements in artistSongs.
Let's say let artistSongs = songs.filter{ $0.artistName == ArtistName } produces an array of 3 elements only but your table view expects 5, when you dequeue your cells and try to access the song with artistSongs[indexPath.row], it's gonna work for the first 3 rows and then it will crash (your current crash).
Your solution is to filter the artist songs somewhere else, say in viewDidLoad, and then use this array to populate your table view safely:
// ADD THIS
var filteredSongs: [Song]()
override func viewDidLoad() {
super.viewDidLoad()
[...]
// ADD THIS
self.filteredSongs = songs.filter{ $0.artistName == ArtistName }
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
// CHANGE THIS
return self.filteredSongs.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "TopSongTableViewCell", for: indexPath) as! TopSongTableViewCell
// REMOVE THIS
//let artistSongs = songs.filter{ $0.artistName == ArtistName }
// REMOVE THIS
//print(artistSongs)
cell.TopSongLabel.text = self.filteredSongs[indexPath.row].cleanName
cell.SongImage.image = UIImage(named: self.filteredSongs[indexPath.row].cover)
return cell
}

Enable unique actions for each row in UITableView

I have a small tableview of 7 rows. I would like to enable different actions for a press of each row.
For example, the row at index 0 would display another VC (without passing data). The row at index 0 would open a web URL, the next might be a share function, etc.
My biggest problem is the first case of send the user to another VC. Mostly because I don't know if I should enable a segue. And for all cases, I need to be able to specify a function for each row separately, therefore I would need to specify the proper index (0,1,2,etc).
How can I do this is Swift?
Here is a skeleton of code you need:
class ViewController: UITableViewController {
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 2 }
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = String(describing: indexPath)
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == 0 {
print("Do action for row 0")
} else if indexPath.row == 1 {
print("Do action for row 1")
}
}
}

How to display multiple attributes in a single table view? Swift

I want to display three different entitys from core data on a table view. I can do this with one entity and tried to carry that logic over to displaying three on the same table view. I used the same entity in the code below to test this. I am getting blank sections in my table view. I must have the cellForRowAt method wrong? Here is my code.
var word: [NSManagedObject] = []
let sections = ["Custom Library", "Mastered Words", "Library"]
var array = [
[NSManagedObject](),
[NSManagedObject](),
[NSManagedObject]()
]
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell2")
array = [
word,
word,
word
]}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array[section].count
}
func numberOfSections(in tableView: UITableView) -> Int {
sections.count
}
func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return self.sections[section]
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let customWord = array[indexPath.row][indexPath.section]
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell2", for: indexPath)
cell.textLabel?.text = customWord.value(forKeyPath: "title") as? String
return cell
Based on the code you've shown, your array property is an array of empty arrays as word is an empty array itself. If you're using array to determine the number of rows in each section based on the array at that section index, then you're going to get 0 rows for each section.

Trying to edit a List in realm

I'm trying to make a List with realm:
class TripsList : Object {
let trips = List<Trip>()
}
Then, inside my ViewController class:
var trips : Results<TripsList>?
override func viewDidLoad() {
super.viewDidLoad()
trips = realm.objects(TripsList.self)
}
When someone moves a UITableViewRow, I want to update my realm database.
override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
let movedObject = self.realm.objects(Trip.self)[sourceIndexPath.row]
trips.remove(at: sourceIndexPath.row)
trips.insert(movedObject, at: destinationIndexPath.row)
}
Here are my TableView Datasource methods:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return realm.objects(Trip.self).count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.font = UIFont.systemFont(ofSize: 17)
cell.accessoryType = UITableViewCell.AccessoryType.disclosureIndicator
cell.textLabel?.text = nameData.names[realm.objects(Trip.self)[indexPath.row].tripID]
return cell
}
The problem is there is no option to do trips.remove(at:) or trips.insert(_:at:).
My overall goal is the ability to insert and remove when someone moves a UITableViewRow and update my realm database.
You cannot directly modify a Results instance. Results are auto-updating collections, meaning that they always reflect the current state of the query you used to initialise them. You need to modify the Realm in order to modify the Results instance.
Moreover, a Results instance is only guaranteed to keep its ordering in case you sort it. So you'll need to introduce a property on Trip that you use to sort the objects and modify that property when the user moves a row.
Your TripsList class seems to be unnecessary, since it seems that you simply want to store a number of Trip objects in Realm, then retrieve them without actually doing any grouping. Even if you needed to group them, you could do so using Realm queries. Keeping this in mind, this is how I'd modify your current code to allow the user to sort their Trips and save the sorting to Realm.
class Trip: Object {
// Your existing code for Trip
...
// Sorting property
#objc dynamic var sortingIndex = 0
}
In your table view controller:
var trips : Results<Trip>?
override func viewDidLoad() {
super.viewDidLoad()
trips = realm.objects(Trip.self).sorted(byKeyPath: "sortingIndex")
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return trips?.count ?? 0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.font = UIFont.systemFont(ofSize: 17)
cell.accessoryType = UITableViewCell.AccessoryType.disclosureIndicator
if let tripID = trips?[indexPath.row].tripID {
cell.textLabel?.text = nameData.names[tripID]
}
return cell
}
override func tableView(_ tableView: UITableView, moveRowAt sourceIndexPath: IndexPath, to destinationIndexPath: IndexPath) {
guard let movedObject = trips?.[sourceIndexPath.row] else { return }
// Depending on your exact needs, you might want to update the `sortingIndex` property of your other rows as well, whose position in the table view was affected by the reordering
try! realm.write {
movedObject.sortingIndex = destinationIndexPath.row
}
}