Cant get a cell subview? - ios

When user choose a cell , I would like to get one of its specific UIViews and change its color.
So,
func collectionView(collectionView: UICollectionView, didSelectItemAtIndexPath indexPath: NSIndexPath) {
for cell in collectionView.visibleCells() as [UICollectionViewCell]
{
if(cell.tag==indexPath.row)
{
for view in [cell.contentView.subviews] {
view.backgroundColor=UIColor.redColor()
//here what ever I try I can't get it to see view as a UIView and change its properties, instead I get error that [UIView] has no member..

There's an easier way to do this. Simply get the cell you're interested in, and manipulate it directly. Using tags is a fragile method. Also, when you iterate through the subviews of another view, you're already dealing with an array, there's no need to wrap it in []s
if let cell = tableView.cellForRowAtIndexPath(indexPath) {
for view in cell.contentView.subviews {
view.backgroundColor = UIColor.redColor()
}
}

This worked for me:
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath)
{
var selectedCell:UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
selectedCell.contentView.backgroundColor = UIColor.redColor()
}
If tableView is set in attribute inspector with selection to multiple Selection it should work. Just set it back in deselect:
override func tableView(tableView: UITableView, didDeselectRowAtIndexPath indexPath: NSIndexPath)
{
var cellToDeSelect:UITableViewCell = tableView.cellForRowAtIndexPath(indexPath)!
cellToDeSelect.contentView.backgroundColor = colorForCellUnselected
}

Your cell.contentView.subViews is in a array so view will turn out to be an array.
Loose the surrounding [] like this:
for view in cell.contentView.subviews {
view.backgroundColor=UIColor.redColor()
}

Related

Swift TableView pass selected Cell

I have two TablewViewControllers: ListTableViewController which holds my list of items and a SortTableViewController where I store sort options for the ListTableView. I need to find a way to highlight the active (if user clicked a sort option) sort option (Cell) when the SortTableViewController loads.Any ideas how to do this?
Screenshot
If you need the sort selection to persist, you can try this.
Use NSUserDefaults to store the selected row index (this assumes your sort options list is fixed)
class SortTableViewController : UITableViewController {
let selectedRowIdx = NSUserDefaults.standardUserDefaults().integerForKey("PLACE_YOUR_KEY_HERE")
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = // your implementation here
if indexPath.row == selectedRowIdx {
cell.textLabel?.textColor = UIColor.redColor()
}
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
NSUserDefaults.standardUserDefaults().setInteger(indexPath.row, forKey: "PLACE_YOUR_KEY_HERE")
}
}
You ca try this
class SortTableViewController: UITableViewController {
var highlightedIndexPath: NSIndexPath? //TODO: populate this
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = //TODO: populate this
cell.textLabel?.textColor = indexPath == highlightedIndexPath ? .redColor() : .blackColor()
return cell
}
}

Change UITableViewCell selection color based on which cell was pressed

My table view has some elements sorted by some types: TypeA, TypeB and TypeC.
I want that when I click on a cell with TypeA to change the selection color to Red, when I type on TypeB to change color to Blue and when pressing on TypeC to change color to Yellow.
Right now I came up with this code:
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
}
func tableView(tableView: UITableView, willDisplayCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
guard let mode = dataSource.selectedObject else {
fatalError("willDisplayCell, but no selected row?")
}
let type = ModeType(rawValue: mode.type)!
let selectionColor = UIView() as UIView
selectionColor.backgroundColor = type.color()
cell.selectedBackgroundView = selectionColor
}
My issue with this is that willDisplayCell is called when I start my app and my data source is empty so I get a fatal error.
How can I overcome this ? Maybe using a flag to do this only when didSelectRowAtIndexPath was called.
Or is there another way to achieve what I am after ?
I assume you have created custom UITableviewCell. Create a cell type enum.
enum CellType {
case RedCell
case Yellowcell
case OrangeCell
}
//Create enum property
class CustomCell : UITableViewCell {
var cellType:CellType = CellType.RedCell //Default is RedCell
}
Now you have to assign the cell type in your ViewController tableview datasource.
override func tableView(tableView: UITableView!, cellForRowAtIndexPath indexPath: NSIndexPath!) -> UITableViewCell! {
var cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("Cell") as! CustomCell
cell.cellType = .RedCell //your choice
return cell
}
override func tableView(tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return true
}
override func tableView(tableView: UITableView, didHighlightRowAtIndexPath indexPath: NSIndexPath) {
var cell = tableView.cellForRowAtIndexPath(indexPath)
switch(cell.cellType) {
//Handle Switch case
case .RedCell:
cell?.contentView.backgroundColor = UIColor.redColor()
cell?.backgroundColor = UIColor.redColor()
}
}
override func tableView(tableView: UITableView, didUnhighlightRowAtIndexPath indexPath: NSIndexPath) {
var cell = tableView.cellForRowAtIndexPath(indexPath)
// Set unhighlighted color
cell?.contentView.backgroundColor = UIColor.blackColor()
cell?.backgroundColor = UIColor.blackColor()
}
EDIT:
If you have created 3 different types of cell class check tableview cell class type and change the color in didHighlightRowAtIndexPath method.
My issue with this is that willDisplayCell is called when I start my
app and my data source is empty so I get a fatal error.
tableView(_:willDisplayCell:forRowAtIndexPath:) will only be called if your data source tells the table view that there are rows to display. So the problem more likely is that your tableView(_:numberOfRowsInSection:) method is returning a number larger than zero when your data source is empty.
Also, your code looks like it expects tableView(_:willDisplayCell:forRowAtIndexPath:) to get called only for selected rows. It gets called for all displayed rows. But this method isn't necessary to affect the background color. In fact, it's rarely used in most apps. There are only a few edge cases where you need to mess with the cell just before it's displayed.
The proper way to set the selection background color is to create and assign a UIView to the cell's selectedBackgroundView property. You can do that either from the cell's subclass (preferred for complex cells) or from the tableView:cellForRowAtIndexPath: data source method:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("MyCell")
cell!.textLabel?.text = "Kilroy was here."
cell!.selectedBackgroundView = UIView(frame: cell!.bounds)
cell!.selectedBackgroundView!.backgroundColor = .greenColor()
return cell!
}

cell.contentView.viewWithTag not working in static tableView

I want to get access to a UIImageViewfrom my cell in a static tableView, I use a UITableViewControllerwithin a ContainerViewwitch is embedded in my ViewController, here is my code :
override func tableView(tableView: UITableView, cellForRowAtIndexPath
indexPath: NSIndexPath) -> UITableViewCell {
let cell = super.tableView(tableView, cellForRowAtIndexPath: indexPath)
// Configure the cell...
println(cell.contentView.viewWithTag(10))
if indexPath.row == self.selectedCellInIndex {
cell.contentView.viewWithTag(10)?.hidden = false
}
else {
cell.contentView.viewWithTag(10)?.hidden = true
}
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
self.selectedCellInIndex = indexPath.row
tableView.reloadData()
}
but always cell.contentView.viewWithTag(10)is returning nil and when I do : println("cell.contentView.subviews.count) I get 0, I tried : cell.viewWithTag(10) and the same problem retain,I searched a lot even in other questions dealing with this issue but I didn't find any solution that works for me, how can I fix it ?
With static cells you can create IBOutlet just by control dragging the item to the view controller source file and avoid the viewWithTag.
I found the solution, it's strange but it fixed the issue:
I unchecked Size classes
clean and build and
recheck Size classes option

UITableView checkmark style remove highlight on select

I am trying to remove the highlight when selecting a table view cell, but want to keep the checkmark that appears.
When I try this in cellForRowAtIndexPath:
cell.backgroundView = UIView()
cell.backgroundView?.backgroundColor = UIColor.clearColor()
It only removes the highlight underneath the checkmark, rather than the whole row (refer to image attached).
When I try this in cellForRowAtIndexPath:
cell.selectionStyle = UITableViewCellSelectionStyle.None
It no longer displays the checkmark.
UPDATE: tried this, does the same thing as cell.selectionStyle where it no longer does checkmark
func tableView(tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: NSIndexPath) -> Bool {
return false
}
What is a good way of doing this? I want it to still function like a checkbox but just don't want the blue highlighting to occur. TableView is dynamically generated:
checkBoxView = UITableView()
checkBoxView.frame = CGRect(x: qView.bounds.midX, y: qView.bounds.midY, width: qView.bounds.width - 100, height: qView.bounds.height/1.5)
checkBoxView.center = CGPointMake(qView.bounds.midX, qView.bounds.midY)
checkBoxView.delegate = self
checkBoxView.dataSource = self
checkBoxView.tag = 100
checkBoxView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
checkBoxView.setEditing(true, animated: true)
self.qView.addSubview(checkBoxView)
Table View Functions:
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.checkBoxContent.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell = checkBoxView.dequeueReusableCellWithIdentifier("cell") as! UITableViewCell
cell.textLabel?.text = self.checkBoxContent[indexPath.row]
cell.backgroundColor = UIColor.clearColor()
cell.tintColor = UIColor.greenColor()
return cell
}
func tableView(tableView: UITableView, editingStyleForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCellEditingStyle {
return UITableViewCellEditingStyle(rawValue: 3)!
}
In order to keep the checkmark, you can't set false to this shouldHighlightRowAtIndexPath method. If you do so, this wouldn't even show the checkmark on the left hand side at all.
What i have done is changing the "selectedBackgroundView" of cell which would keep the left-hand side checkmark and giving me the chance to set the background color. I enclose some code here and hope it would help.
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier(cellID, forIndexPath: indexPath) as! RecordTableViewCell
cell.selectedBackgroundView = UIView(frame: cell.frame)
cell.selectedBackgroundView?.backgroundColor = UIColor.orangeColor()
return cell
}
None of the suggestions above worked for me. In Swift 5, add this line to your cellForRowAtIndexPath function:
cell.selectionStyle = UITableViewCell.SelectionStyle.none
Swift 1.2 use:
tableView.deselectRowAtIndexPath(indexPath, animated: true)
In the didSelectRowAtIndexPath delegate method.
Theres an official way to do this with a UITableView, which is to use this :
optional func tableView(_ tableView: UITableView, shouldHighlightRowAtIndexPath indexPath: NSIndexPath) -> Bool
If you return YES for this method, then the tableview will highlight a cell when it is clicked.
Also note if you dont want to use that, that you need to change the contentView.backgroundColor, rather than just the cell backgroundColor. But the highlighting route is the best one to go down.
Documentation here : https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableViewDelegate_Protocol/index.html#//apple_ref/occ/intfm/UITableViewDelegate/tableView:shouldHighlightRowAtIndexPath:

Scrolling in UICollectionView selects wrongs cells - Swift

I have the following UICollectionView which is populated by an Array with NSManagedObject of type Categories
The problem is that when a Cell is selected scrolling does not function correctly. When scrolling through the UICollectionView other cells get selected, and deselected. Strange behaviour. I think this is because of the indexPath that is set incorrectly after scrolling? Anyway, I have been struggling with this for a couple of hours, and cannot seem to grasp it. Hopefully someone can point me in the right direction!
The fetchedCategory gets compared to the category to check if it is already selected and if they are the same the colors are inverted.
func collectionView(collectionView: UICollectionView, cellForItemAtIndexPath indexPath: NSIndexPath) -> UICollectionViewCell {
var cell = collectionView.dequeueReusableCellWithReuseIdentifier("CategorySelectionCollectionCell", forIndexPath: indexPath) as CategoryCollectionViewCell
if fetchedCategories[indexPath.row] == category {
cell.categoryLabel?.text = fetchedCategories[indexPath.row].name
cell.categoryLabel?.textColor = UIColor.whiteColor()
cell.backgroundColor = fetchedCategories[indexPath.row].iconColor as? UIColor
collectionView.selectItemAtIndexPath(indexPath, animated: true, scrollPosition: UICollectionViewScrollPosition.None)
} else {
cell.categoryLabel?.text = fetchedCategories[indexPath.row].name
cell.categoryLabel?.textColor = fetchedCategories[indexPath.row].iconColor as UIColor
collectionView.deselectItemAtIndexPath(indexPath, animated: true)
}
return cell
}
func collectionView(collectionView: UICollectionView!, didSelectItemAtIndexPath indexPath: NSIndexPath!) {
var cell = collectionView.cellForItemAtIndexPath(indexPath) as CategoryCollectionViewCell
cell.categoryLabel?.textColor = UIColor.whiteColor()
cell.backgroundColor = fetchedCategories[indexPath.row].iconColor as? UIColor
category = fetchedCategories[indexPath.row]
}
func collectionView(collectionView: UICollectionView!, didDeselectItemAtIndexPath indexPath: NSIndexPath!) {
if var cell = collectionView.cellForItemAtIndexPath(indexPath) as? CategoryCollectionViewCell {
cell.categoryLabel?.text = fetchedCategories[indexPath.row].name
cell.categoryLabel?.textColor = fetchedCategories[indexPath.row].iconColor as UIColor
cell.backgroundColor = UIColor.whiteColor()
}
}
You don't want to call cellForItemAtIndexPath and configure the cells in the didSelectItemAtIndexPath or didDeselectItemAtIndexPath delegate methods.
Also, you shouldn't be calling selectItemAtIndexPath and deselectItemAtIndexPath from within the cellForItemAtIndexPath method.
Instead, just keep track and toggle the state of the selected category in your select/deselect callbacks, and then don't do anything other the set up up the look of your cells in cellForItemAtIndexPath.
As the commenter pointed out, the cells are re-used, so stick to the simple way the delegate callbacks are designed to be used, and you should have much better luck.
If you need to refresh the look of the cells, do it by relying on cellForItemAtIndexPath being called while scrolling and using the reloadData and reloadItemsAtIndexPaths collection view methods if you need to force an update.

Resources