Get the cell in a row and column (Cocoa) - swift

I need to get the cell contained in a column at a specified row without using the tableview functions. For example:
for a in 0...tableview!.numberOfRows {
let column = tableview.tableColumns[2]
let cell = cell in column at the row a
}
Do you have any solutions?
EDIT: in Cocoa

I solved with this (to retrieve the values of an item in each cell), thanks Willeke
for a in 0...tableview!.numberOfRows-1 {
let cell = tableview.view(atColumn: 2, row: a, makeIfNecessary: false) as? cella
print(cell?.tipo.title)
}

Related

NSTableView Tab Between Columns and move to next row

Use Case:
This is a data entry scenario where the user needs to modify the data in three columns of a view based NSTableView; qty, item number and price. The objective is to keep the users hands on the keyboard and diminish the need for mouse'ing around the table to perform edits.
Detailed UI:
When tabbing within a row, the next column should become selected and editable which is (can be) the default behavior of a NSTableView. However, when in the last column (price) is being edited and tabbing out, it should wrap to the next available row, column 0 (qty) and allow the user to continue editing.
Likewise, backtab should be supported within a row, and when in the first column (qty) and backtabbing it should wrap up the the prior row, last column (price). If they are on row 0, column 0, it should wrap down to the last row, last column.
So essentially the user should be able to navigate and edit any row, column with tab or backtab presses.
While there are several solutions, using keyDown, keyUp, notifications etc a lot of it is older ObjC Code and not very Swifty.
Typically questions should include some kind of code but since I have a solution that works, I am including it as an answer so hopefully it will help a future reader.
Question:
Can you suggest a simpler solution of how to navigate a view based tableview based on the above parameters.
First is to subClass a view based NSTableView set set it up like this
class ItemTableView: NSTableView, NSTableViewDataSource, NSTableViewDelegate, NSTextFieldDelegate {
I have a tableView dataSource called transactionArray which holds the items to be displayed within the tableView. I also include the delegate methods
func numberOfRows(in tableView: NSTableView) -> Int
and
func tableView(_ tableView: NSTableView, viewFor tableColumn: NSTableColumn?, row: Int) -> NSView?
within the class so it's self contained.
Here's the function to handle tab navigation
// handle tab and backtab in an editable view based tableView subclass
// will also scroll the edited cell into view when tabbing into view that are outside the viewable area
//ref https://developer.apple.com/documentation/appkit/nscontroltexteditingdelegate/1428898-control
func control(_ control: NSControl, textView: NSTextView, doCommandBy commandSelector: Selector) -> Bool {
print(#function)
//let whichControl = control //this is the tableView textField where the event
// happened. In this case it will only be the
// NSTableCellView located within this tableView
let whichSelector = commandSelector //this is the event; return, tab etc
//these are the keypresses we are interested in, tab, backtab, return/enter.
let tabSelector = #selector( insertTab(_:) )
//let returnSelector = #selector( insertNewline(_:) ) //use this if you need
//custom return/enter handling
let backtabSelector = #selector( insertBacktab(_:) )
//if the user hits tab, need to determine where they are. If it's in the last
// column, need to see if there is another row and if so, move to next
// row, col 0 and go into edit. If it's a backtab in the first column, need
// to wrap back to the last row, last col and edit
if whichSelector == tabSelector {
let row = self.row(for: textView)
let col = self.column(for: textView)
let lastCol = self.tableColumns.count - 1
if col == lastCol { //we tabbed forward in the last column
let lastRow = self.transactionArray.count - 1
var rowToEdit: Int!
if row < lastRow { //if we are above the last row, go to the next row
rowToEdit = row + 1
} else { //if we are at the last row, last col, tab around to the first row, first col
rowToEdit = 0
}
self.editColumn(0, row: rowToEdit, with: nil, select: true)
self.scrollRowToVisible(rowToEdit)
return true //tell the OS we handled the key binding
} else {
self.scrollColumnToVisible(col + 1)
}
} else if whichSelector == backtabSelector {
let row = self.row(for: textView)
let col = self.column(for: textView)
if col == 0 { //we tabbed backward in the first column
let lastCol = self.tableColumns.count - 1
var rowToEdit: Int!
if row > 0 { //and we are after row zero, back up a row and edit the last col
rowToEdit = row - 1
} else { // we are in row 0, col 0 so wrap forward to the last col, last row
rowToEdit = self.transactionArray.count - 1
}
self.editColumn(lastCol, row: rowToEdit, with: nil, select: true)
self.scrollRowToVisible(rowToEdit)
self.scrollColumnToVisible(lastCol)
return true
} else {
self.scrollColumnToVisible(col - 1)
}
}
return false //let the OS handle the key binding
}

Multiple UICollectionView Data Sources in One UIViewController

I have a question about the implementation.
My users will be able to select from a dropdown what they want to see in the collection view. Depending on the choice, the dataset and potentially section/cell types will change.
Should I have one UICollectionView with all of the cells registered and based on the users choice modify my cellForItemAt?
Or should I have a UICollectionView per choice and then swap them depending on the choice?
What is the best and more professional implementation?
If the cells being displayed are similar in nature (they have the same structure of data aka picture, text, description, name, etc) then you should use one re-useable cell.
Having one cell makes your code much cleaner. You can also then set an observable property inside your cell that you set with the data. Pass the data to cell and then inside the cell class, it will be responsible for laying out the code.
let cell = someDequeuedCell
cell.data = somedata
return cell
Then inside the cell class,
var data: SomeData? {
didSet {
//Determine data and layout cell
if data == 'apple' {
//Layout apple cell
} else if data == 'orange' {
//Layout orange cell
} else {
//Layout other cell
}
}
}
This approach is very commonly used, however if each cell varies more than just data being changed. You should register multiple different cells for each datatype.
Inside the collectionView
if dataType == "apple" {
let cell = appleCell
cell.data = someData
return cell
} else if dataType == "orange" {
let cell = orangeCell
cell.data = someData
return cell
} else {
let cell = otherCell
cell.data = someData
return cell
}

Swift TableView cell doesn't fit into 1 row

I'm working on a swift project. I have a tableview that loads the data correctly. However, I have many cells for each row and it doesn't fit into the iphone screen, and got cut off the screen. I would like to have some cells go on to the next line instead of not showing on the screen. How to do that? Thanks.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! ResultTableViewCell
//cell.textLabel?.numberOfLines = 0
//cell.textLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping
let category: Category = categories[indexPath.row]
cell.lblName.text = category.name
cell.lblQty.text = category.qty
cell.lblSub.text = category.sub
cell.lblSub2.text = category.sub2
cell.lblCountry.text = category.country
cell.lblState.text = category.state
cell.lblCity.text = category.city
return cell
}
On my screen, it can only fit 5 columns, and the rest gets cut off. I want to show each row in 2 lines. The first line will display the name, qty, sub, sub2 and the next line will display country, state and city.
It doesn't tell us much without seeing the layout of your cells and some example screens presenting the issue. But it's possible that you would want to look at autoresizing cells and UITableViewAutomaticDimension.

Swift - read above cell value in tableview

Basically I am trying to get a value from a custom table view cell, as I have made 5 prototype cells - each with a different tableViewCell class. However, what I am trying to do is to read the data from the cell above. I have called my classes: TableViewCell1, TableViewCell2 etc... So on the cellForRowAtIndexPath, I have the code like this:
if indexPath.row == 1 {
let cell2 = tableView.dequeueReusableCellWithIdentifier("secondCell", forIndexPath: indexPath) as! TierCell2
return cell2
}
This works, but I have also tried to do it like this, to be able to access the value above (with no luck) - which only results in an optional value error.
let cell1:TableViewCell1 = TableViewCell1()
cell2.PriceText.text = cell1.PriceText.text
Any ideas on how I might accomplish this?
I suggest you then try creating one custom table view cell with the 5 price tier labels that you want to display. Then in the cellForRowAtIndexPath you just deque a cell as the custom class and fill in all the tier information that you already have in your dictionary and return that cell.

Swift - TableView, change font of even rows to bold

I have a tableview and i want to change the font of even rows, Here is my code:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cellIdentifier = "ProductListTableViewCell"
let cell = tableView.dequeueReusableCellWithIdentifier(cellIdentifier, forIndexPath: indexPath) as! ProductListTableViewCell
let product = productList[indexPath.row]
cell.productName.text = product.name
cell.productPrice.text = "\(product.price) manat"
if(indexPath.row % 2 == 0) {
cell.productName.font = UIFont.boldSystemFontOfSize(13.0)
cell.productPrice.font = UIFont.boldSystemFontOfSize(13.0)
}
return cell
}
when i run my code, at the beginning everything works correctly, when i scroll my table view, all new rows appeared on screen becomes bold, both even and old rows. What am i doing wrong?
Remember that a table view reuses cells. That's why you get them from a method named dequeueReusableCellWithIdentifier(_:forIndexPath:).
You set the font to bold when it's an even-numbered row, but you don't set it back to normal when it's an odd-numbered row. If the cell was previously used for an even-numbered row, and is now being used for an odd-numbered row, it still has a bold font.
let weight = (indexPath.row % 2 == 0) ? UIFontWeightBold : UIFontWeightRegular
let font = UIFont.systemFontOfSize(13, weight: weight)
cell.productName.font = font
cell.productPrice.font = font
Your reusable cells are all being set to bold. Add an else to the if row % 2 == 0 to set the cell back to normal font when it is used in an odd row.