Posts

Post not yet marked as solved
6 Replies
For every device? In every orientation? Problem would be - if I change the contents, I have to change the height.If I start from a new table view cell, add a new text view, and re-type the text (can't just paste it), then some of the issues improve - This was the only way I found to get rid of the large right hand margin issue.
Post not yet marked as solved
6 Replies
It is a good tutorial, but I have done it previously, and reviewed it for this problem. The problem occurs despite .automaticDimensions in the heightForRowAt function.I often see an error that the constraints suggest a height of zero for table view cell content view. The only solution I found for this is to delete the constraints and reapply them, which sometimes removes the error, but often results in the text view not appearing. If I then add a height constraint, the view appears, but the height is now fixed for a single device.
Post not yet marked as solved
6 Replies
Yes, it is only the last row. I am not sure the difference between the last visible row or the very last row. In this case, the very last row in the intended table grid is visible. In the simple github project, you can just see the problem in the very last row, although it is not as pronounced as it is in some cases - it just looks a little tiny bit to the left of the cell above. This would not be a problem, but in certain situations it can become quite exacerbated (I will try to explain below).With regard to the widths, I have logged their values and the widths of each cell are identical. Here is the log output for the final two rows showing width values for 5 cells in a single row (all rows have these exact identical values)cell width 172.0cell width 132.0cell width 132.0cell width 132.0cell width 132.00000000000003cell width 172.0cell width 132.0cell width 132.0cell width 132.0cell width 132.00000000000003The width values are always equal for cells in the same column, even when the problem is exacerbated. When exacerbated, space is being added between the cells of each row, except in the very last visible row in the grid. Hence, the cells in this row do not exactly sit below the cells above them like a column of cells (particularly the very last cell in the last column).What appears to be happening is that when calculating cellWidth, I am subtracting a constant value to solve rounding issues (see all caps comment in code). Depending on the available width, column numbers and cell content, this constant needs to be adjusted to be between 0.5 and 20 (I just increase the value until I get the right number of columns on as many devices as possible). The spaces added between cells are this constant value shared across the entire row because when I increase the value of this constant, the spaces increase. This would be ok, except the spaces are not added between cells in the very last row! Here are the collection view delegate methods: func willRotateToInterfaceOrientation(toInterfaceOrientation: UIInterfaceOrientation, duration: TimeInterval) { cView.collectionViewLayout.invalidateLayout() cView.reloadData() } func numberOfSections(in collectionView: UICollectionView) -> Int { return 1 } func collectionView( _ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int { return currentContents.count } func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell { let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as! CollectionViewCell let settings = currentContents[indexPath.item] cell.cVLabel.text = settings.text cell.contentView.layer.cornerRadius = 5 cell.contentView.layer.borderWidth = 0.5 cell.contentView.layer.borderColor = UIColor.gray.cgColor cell.contentView.layer.masksToBounds = true return cell } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets { return UIEdgeInsets(top: 0, left: 0, bottom: 10, right: 0) } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat { return 0 } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat { return 0.5 } func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize { var columnPortion = CGFloat() let columnNumber = indexPath.item % 5 switch columnNumber { case 0: columnPortion = portion0 case 1: columnPortion = portion1 case 2: columnPortion = portion2 case 3: columnPortion = portion3 case 4: columnPortion = portion4 default: columnPortion = 1 } // https://stackoverflow.com/questions/54915227/uicollectionview-remove-space-between-cells-with-7-items-per-row var cellWidth = CGFloat() let minimumWidth = floor(availableWidth / numberOfColumns) cellWidth = minimumWidth * columnPortion - 20 // HERE IS CONSTANT TO REMOVE ROUNDING ISSUES, BUT IT ADDS SPACE ISSUES IN ALL ROWS EXCEPT FINAL ROW print("cell width", cellWidth) return CGSize(width: cellWidth, height: rowHeight).xx_rounded() } } extension CGFloat { func xx_rounded(_ rule: FloatingPointRoundingRule = .down, toDecimals decimals: Int = 0) -> CGFloat { let multiplier = CGFloat(10 ^ decimals) return (self * multiplier).rounded(.down) / multiplier } } extension CGSize { func xx_rounded(rule: FloatingPointRoundingRule = .down, toDecimals: Int = 0) -> CGSize { return CGSize(width: width.xx_rounded(rule, toDecimals: toDecimals), height: height.xx_rounded(rule, toDecimals: toDecimals)) } }Thanks for bothering with this - everything I've tried fails because the last row is somehow treated differently - it's quite frustrating.
Post not yet marked as solved
6 Replies
Have you any idea why the cell widths in the last row, including their spacing, is different to the other rows? This makes my grids look less table like.
Post not yet marked as solved
6 Replies
This solves the issue on the iPad Air devices - awesome and thanks! It also appears to work if the portions are of type CGFloat, which is what the sizeForItem needs. Please tell me if I need to use Double for the initial values of the portions or CGFloat is ok.As you may realise, the uneven last row issue is still there. In my humble, it seems most likely to also be a rounding issue in the following line:cellWidth = minimumWidth * columnPortion - 20In the initial code (in the question and code on github), the "constant" ("20") value was "1" - as I understand, to soak up any rounding issues. In a lot of cases, the closer this value comes to zero, the closer the widths in the final row are to the other rows - BUT, sometimes (some devices, some orientations), if the value is too low, the cells from one row spill onto the next row (instead of 5 cells/columns per row, only 4). If I increase this constant value, to say 20 as above, it prevents this problem from occuring, but adds space between cells in all rows except the last row, which is the second issue in the question. I've tried to calculate this remainder value, but this also fills the available width in all rows (except the last row) by adding space between the cells.
Post marked as solved
11 Replies
I see - basically reloading the collection view - with the UIPickerViews inside it - was confusing the pickers. That makes sense to me now. I've found a way, based on your code, to update the existing cells and their labels to avoid this problem. Wonderful - thank you very much!
Post marked as solved
11 Replies
I downloaded the file and the pickers show on a iPhone 7 + device, a simulator iPhone Xr, and every other simulator tested in xcode 10.3. iPad Air is the best to show the below situation. The values in the pickers are "value 1" or "value 2", and can be changed with three fingers in the simulator.| Value 1 | nothing | Value 1 | Value 1 |-- -- -- -- -- -- --- -- -- -- -- --- -- - -- --- - - -- -| Initial text 1 | nothing | Initial text 3 | Initial text 4 |I also see the contraint errors, but there is nothing fatal or overriding the collection view size for item method (pickers are shown - maybe it is not clear that they are pickers because the text is similar to the other labels.As above, if I use the picker in the first column to select value 2, the data in that column updates, but the picker itself reverts to its former value - Value 1 - and the picker in the third column changes its display to Value 2 (no change to the data in that column).| Value 1 | nothing | Value 2 | Value 1 |-- -- -- -- -- -- --- -- -- -- -- --- -- - -- --- - - -- -| Ichanged col 1) | nothing | Initial text 3 | Initial text 4 |
Post marked as solved
11 Replies
Before changing my approach completely to instantiate the pickers programatically, I thought to recreate the issue in a new project - to see if it repeats itself. And it does!It seems a strange enough issue - could you please look at this code and see if it is something I am doing wrong? It is not exactly as described above, but chosing a label updates the correct collection view, but the picker labels behave strangely.UIPickerLabelThing.zip
Post marked as solved
11 Replies
myPickerDidSelectRowInCase could be anything that changes the results only for items in the column. Simplest would be to select actual values for each column based on caseOfPicker. In the code below, which is more complex, i'm setting a column specific delegate that is used to fetch data before ereloading the collection view.protocol EgPickerDelegate { func myPickerDidSelectRowInCase(selectedRowValue: Int?, caseOfPicker: Int?) } extension EgEndingsCVTVCell: UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout, EgPickerDelegate { func myPickerDidSelectRowInCase(selectedRowValue: Int?, caseOfPicker: Int?) { switch caseOfPicker { case 0: col0GenderPredicate = genderPredicator(selectedRowValue: selectedRowValue ?? 0) case 2: col2GenderPredicate = genderPredicator(selectedRowValue: selectedRowValue ?? 0) case 3: col3GenderPredicate = genderPredicator(selectedRowValue: selectedRowValue ?? 0) default: col0GenderPredicate = genderPredicator(selectedRowValue: 0) } loadSavedData() cView.reloadData() }as above - confirm - the collection view cell class confirms to the EgPickerDelegate.I'm not sure if you mean the fetchedResultsControllerDelegate. I'm not sure this is useful.extension EgEndingsCVTVCell: NSFetchedResultsControllerDelegate { func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) { print("THE CONTROLLER CONTENT HAS CHANGED") cView.reloadData() } }The CollectionView is actually inside a TableViewCell. At cell for item at row: else if indexPath.row == 5 { let cell = tableView.dequeueReusableCell(withIdentifier: "EgEndingsCVTVCell") as! EgEndingsCVTVCell return cell }Thanks for looking into this.
Post marked as solved
11 Replies
Thanks Claude for taking a look. This is the grid table with the pickers in the top row. The user should be able to pick a different gender (eg, Masculine, Neutral or Feminine) for each column, and the values below, in that column, should update (of course, the picker should also show the selected value - which is the problem).| Masculine | | Masculine | Masculine |-- -- -- -- -- -- --- -- -- -- -- --- -- - -- --- - - -- -| Der Mann | gibt | dem Hund | den Ball. |additional rows of examplesThe UILabels that behave strangely are the 3 picker labels in the top row.The cases, 4...28, are for the attributed text (put together in a separate method). The rest of the cellForItem, is simply: case 1: cell.label.text = nil case 4...32: cell = cVCellContents(cell: cell, indexPath: indexPath, offset: 0) default: cell.label.attributedText = NSAttributedString(string: "No case") } return cell }To demo what I mean about the picker labels, if I roll the column 1 picker to 'Neutral', the data for the column updates (correct caseOfPicker value passed to delegate) to show neutral words in that column (eg, Das Kind), but the UILabel in column 1 reverts back to 'Masculine' while the label of the picker in the untouched 4th column changes from Masculine to Neutral (the data in this column stays masculine). In the other column (3), the picker label is unchanged.| Masculine | | Masculine | Neutral |-- -- -- -- -- -- --- -- -- -- -- --- -- - -- --- - - -- -| Das Kind | gibt | dem Hund | den Ball. |Continuing from this situation, if I then select Feminine in column 1, the data in this column updates with feminine values (eg Die Frau), the picker label in column 4 changes to Feminine, and the picker label in column 1 now updates to Neutral (i.e. the previously selected value for this column).| Neutral | | Masculine | Feminine |-- -- -- -- -- -- --- -- -- -- -- --- -- - -- --- - - -- -| Die Frau | gibt | dem Hund | den Ball. |This pattern repeats - with the column 4 label showing the UILabel selected in column 1, and column 1 reverting to its previously selected value.Column 3 behaves slightly differently. When I pick another value, the data in column 3 updates correctly, and the picker in this column does NOT revert to its previous value (it correctly shows the selected value). Meanwhile, however, the labels in columns 1 and 4 swap values. In the example, continuing from above, column 3 is changed from Masculine to Neutral - the data updates correctly for the column (dem Pferd); column 3 label is correctly showing the selected Neutral value; but columns 1 and 4 exchange their values with each other (without changing their data).| Feminine | | Neutral | Neutral |-- -- -- -- -- -- --- -- -- -- -- --- -- - -- --- - - -- -| Die Frau | gibt | dem Pferd | den Ball. |Quantum computing?