The count of chosenPlanArray.count is 5 here, and that is how many cells my collection view ends up having.
However, when i try an append values from the collection view to arrays, my collection view is iterating over itself an extra amount of times - in this example it gets to 9 iterations. Even though 'return chosenPlayArray.count' is 5. This is very random and ive been playing with my code all day trying to fix it. Has this ever happened to anybody ?
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return chosenPlanArray.count
}
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "customCell", for: indexPath) as! CustomPlanItCollectionViewCell
cell.planImage.downloadedFrom(link: chosenPlanArray[indexPath.item].imageForPlan!)
cell.planLbl.text = chosenPlanArray[indexPath.item].nameOfEvent
cell.dateTimeLbl.text = chosenPlanArray[indexPath.item].eventStartsAt
if cell.dateTimeLbl.text == nil {
datesForFirebase = [""]
} else {
datesForFirebase.append(cell.dateTimeLbl.text!)
}
individualPlanNames.append(cell.planLbl.text!)
imagesOfPlan.append(chosenPlanArray[indexPath.row].imageForPlan!)
print(chosenPlanArray.count)
print(imagesOfPlan.count)
print(nameOfEventPlan.count)
print(individualPlanNames.count)
return cell
}
Here is my output for those print statements at the bottom. Notice how the first print statment is correct - the actual size of the collection view is 5, as you can tell by the numberOfitems in sec.. I find it weird how the other print statements start at 1, and then loop past the size of 'chosenPlanArray.count' - Is the issue the way i may be appending the values to my arrays? This is causing me to get the wrong number of values uploaded to my firebase. So i need to figure this tricky situation out. Thanks
5 // first print statement print(chosenPlanArray.count)
1 // second print statement print(imagesOfPlan.count)
1 // fourth print(nameOfEventPlan.count)
1 // third print(individualPlanNames.count)
5
2
2
2
5
3
3
3
5
4
4
4
5
5
5
5
5
6
6
6
5
7
7
7
5
8
8
8
5
9
9
9
You have to know that there is cell reusing , which means every scroll a call to cellForItemAt happens which means these lines run again
individualPlanNames.append(cell.planLbl.text!)
imagesOfPlan.append(chosenPlanArray[indexPath.row].imageForPlan!)
and the size of their content increases
Related
I have created a TableView with a Prototype Cell with a lot of content in it, multiple labels, 2 pictures and a view which is colored if the row is selected.
What I want to do now, is I want to add a number for each of the rows created so the user can see how many rows there are. I can't use the ID I get from the Database since it is a random mix of characters.
I added an Int variable 'participantID' which starts from one and increments by one with every cell created and writes the value in a label within the prototype cell.
This does exactly what I want, with just one issue: Every time i scroll in the table the ID is incremented. I know that's because of the reuse of the cells however I couldn't find a way to fix this issue.
This is how it looks (particID):
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "tbcCourseParticipant", for: indexPath) as! participantCell
let partic = participants[indexPath.row]
cell.lblId?.text = String(particID)
cell.lblName?.text = partic.name
cell.lblFirstName?.text = partic.firstName
cell.lblBirthDate?.text = partic.birthDate
cell.lblPhoneNr?.text = partic.phoneNr
cell.lblPrice?.text = String(partic.payed) + "€"
particID += 1
return(cell)
}
The total number of rows is participants.count. The number of this row is indexPath.row+1 (I add 1 because the user will not expect to start counting at zero the way a programmer would do).
So I would say:
cell.lblId?.text = String(indexPath.row+1)
Or maybe:
cell.lblId?.text = String(indexPath.row+1) + " of " + String(participants.count)
I got data in a form of array from server at viewDidLoad
want to show it into collectionView according to its indexPath .
I have a collectionView but its cells are full length of collectionView frame so that cells work as a scrolling pages. at button click, next cell will show with its data array index values.
Lets assume data array are 3. First time its shows correct data array but after button click event in place of caliing cellForRowAt method single time , it call 2 times but at willDisplayCell method it run only one time. due to which the values of willDisplay and cellForRawAt are diffrent.
It occur when collectionView scroll
i except the flow of collectionView as
cellForItemAt Optional(“value of array index 1 ”) willDisplay
Optional(“value of array index 1 ”) UIDisplay of 1 array index
cellForItemAt Optional(“value of array index 2 ”) willDisplay
Optional(“value of array index 2 ”) UIDisplay of 3 array index
cellForItemAt Optional(“value of array index 3 ”) willDisplay
Optional(“value of array index 3 ”) UIDisplay of 3 array index
but i get
cellForItemAt Optional(“value of array index 1 ”) willDisplay
Optional(“value of array index 1 ”) UIDisplay of 1 array index
cellForItemAt Optional(“value of array index 2 ”) willDisplay
Optional(“value of array index 2 ”)
cellForItemAt Optional(“value of array index 3 ”) UIDisplay of 3 array
index
Can we avoid duplicate entries of the column in REALM database?
Eg. I have entries like 4 4 4 4 4 4 3 3 3 3 4 5 5 5 2 2 2 2 4 3 3 3 3 2 2 6 6 6
I want to show 2 3 4 5 6 only.
As #Ahmad F said, specify if you want to do it after or before storing them.
In case you want to filter them AFTER storing you can go with something like this:
return realm.objects(YourObject.self).value(forKeyPath: "#distinctUnionOfObjects.entryKey")
if using realm version 3.10 you can using
Results..distinct(by: )
if using Old version - before Realm 3.10 try this
func uniq<S : Sequence, T : Hashable>(source: S) -> [T] where S.Iterator.Element == T {
var buffer = [T]()
var added = Set<T>()
for elem in source {
if !added.contains(elem) {
buffer.append(elem)
added.insert(elem)
}
}
return buffer
}
using func
uniq(source: realm.objects(Object.self))
Hmm, I think you should add the primary key in your class definition.
And it will help you to avoid duplicate items.
This question already has answers here:
Can I use the range operator with if statement in Swift?
(6 answers)
Closed 5 years ago.
if indexPath.row == 0 ... 11 {
}
That isn't working, it says Binary operator '==' cannot be applied to the operands of type 'Int' and 'CountableClosedRange.
(Purpose of this is to disable rows 0-12.)
What is the proper way to do this? Basic question but I don't know what to search Google for. Thanks in advance!
If I had to guess it would be:
for numero in 0 ... 11 {
if indexPath.row == numero {
}
}
For check between value
Use "~=" range operator.
And use as below
Ex.
if 0 ... 11 ~= indexPath.row {
print("IndexPath in between 0 to 11")
}
let indexPath = IndexPath(row: 4, section: 0)
if (0...10).contains(indexPath.row) {
print(indexPath.row) // 4
}
This checks whether the row of your indexPath is within the range of 0 - 10
You are comparing a range of integers against a single integer which does not work.
You need to check if the range contains the value
if (0...11).contains(indexPath.row) { ...
But in your case you can also simply check
if indexPath.row < 12
since the row will never be negative.
Question 1: How can i have section index in tableview without section?
Question 2: Could i have those section index for specific rows in a table? For example: i want the section index to be implemented whenever indexpath.row > 4.
Table views in UIKit always have sections and rows. By saying you don't want a section, you are really saying that you simply want only one section (at section index 0) that holds all rows (with indexes relative to section index 0).
Note: You can easily have a section without a section header in which case the user will never know that all rows are actually contained in a section.
When you implement your table view data source, you will want to implement numberOfSections and numberOfRowsInSection in order to let the table view know how many sections and rows you want.
See UITableView.
I think you mean with only one single section (you can't have no sections). Here's how I do this:
Create index titles that are just string versions of the array indexes. If there are too many to fit on the screen, iOS will skip some and replace them with bullets to make it clear that there are some indexes not being displayed. You will be guaranteed that the index range is the same as your row range. (Unless you have zero rows).
Instead of returning the section index, return -1. This will do nothing. Programatically scroll to the ROW of the passed in index.
override func sectionIndexTitles(for tableView: UITableView) -> [String]? {
if myDataSourceArray.count > 0 {
return Array(1...myDataSourceArray.count).map({String($0)}).map({ String($0) })
}
return []
}
override func tableView(_ tableView: UITableView, sectionForSectionIndexTitle title: String, at index: Int) -> Int {
tableView.scrollToRow(at: IndexPath(row: index, section: 0), at: .middle, animated: true)
return -1
}
(I actually set my minimum count to 20, rather than zero, as there's not much point in having an index when all items in the table are on the screen. But you do need to check for at least greater than zero, otherwise it will try to create an index of "1" for a table with no rows, and this will cause a crash.)
You may want different index titles other than just numbers, but hopefully this gives you some idea on how it can be done. Once you have a different number of indexes to what you have rows, you would have to come up with some other more complicated way of relating index numbers or index titles to row numbers.
Question1:To have section index in tableview without section, you can make height of section to 0.
Question2: If indexPath.row>4, get section index as: yourArray[indexPath.section]