Dynamic layout in a UITableView Cell - ios

I'm an Android developer, recently started to discover iOS using SWIFT 2
I would like to have a dynamic layout in my custom cell, I have an UImageView. and I have two cases :
To show the image.
To hide the image (OR to remove it) the Cell height should change
I've made my cell height dynamic using :
tableView.rowHeight = UITableViewAutomaticDimension
tableView.estimatedRowHeight = 160.0
How Can I achieve that ! here is my code :
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! PostCell
if (posts[indexPath.row].PostImageURL == "None") {
// Remove the Image
} else {
cell.PostImage.load(posts[indexPath.row].PostImageURL!)
}

You could try to set the UIImageView's Outlet to be hidden.
You could try to set the UIImageView to nil
You could try to loop through the sub idea of your Cell and remove the UIImageView from the View Hierarchy.
Hope I could help!

Related

how to get current cell.contentview in uicollectionview. how to add subview in uicollectionview cell

Hi in my application i want to add particular view in cell.contentview now situation is that where i can add this code. reason is if i am puting this code on cellforitematindexpath it will be added in last cell(indxpath.row) reason is in cellforrowatindexpath last cell will be loaded last so view will be added in last cell. while i want it on that cell which was displaying at current time
Here is my code. simply have to add subview
let cell : pdfImageCell = collectionView.dequeueReusableCell(withReuseIdentifier: "pdfImageCell", for: indexPath) as! pdfImageCell
cell.contentView.addSubview(userResizableView1)
Get the visible cell index like below in UICollectionView. You can also get multiple cells visible if they are visible on screen so selected the cell you want.
var visibleCurrentCell: IndexPath? {
for cell in self.collectionView.visibleCells {
let indexPath = self.collectionView.indexPath(for: cell)
return indexPath
}
return nil
}
Then get the cell from your index and add the subview in that cell.
You can add UIView in awakeFromNib() method. It will get the call only once.
class pdfImageCell : UICollectionViewCell {
//you can add here
override func awakeFromNib() {
var userResizableView1 = UIView()
self.contentView.addSubview(userResizableView1)
}
}
- (void)reloadItemsAtIndexPaths:(NSArray *)indexPaths
Here it is a method to reload the specific indexPaths in your collectionView
you can update your datasource on click and your cellForItemAtIndex will know from your data source that it has to have the subview this time
if (datasourcearray[indexpPath.row].isSubViewToBeAdded)
{
self.contentview.addsubview(subViewToBeAdded)
}

Passing indexpath tag to button inside prototype cell in tableview

I have created a tableview prototype cell in storyboard and I have added a button to cell and set its tag to indexpath.row. When I scroll my cells the scrolled cell on the top of tableview always set tag to zero instead of correct tag.
public func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("autoLoadReuseIndentifier", forIndexPath: indexPath)
print("indexpath :\(indexPath.row)")
cell.contentView.viewWithTag(100)?.layer.cornerRadius = 5
tableView.separatorStyle = UITableViewCellSeparatorStyle.None
let tempDict : NSDictionary = savedCardsArray.objectAtIndex(indexPath.row) as! NSDictionary
let bankName = cell.contentView.viewWithTag(102) as! UILabel
deleteButton = cell.contentView.viewWithTag(106) as? UIButton
deleteButton?.tag = indexPath.row
deleteButton?.addTarget(self, action: "deleteCard1:", forControlEvents: UIControlEvents.TouchUpInside)
print("delete button:\(deleteButton)")
// print("indexpath delete tag :\(deleteButton.tag)")
if(self.isSetUpAutoloadSelected){
deleteButton?.hidden = true
}else{
deleteButton?.hidden = false
}
return cell;
}
Whenever I scroll the cells, delete button tag is always set to zero.
If you should go with other way so use follow code and get indexPath.
func deleteCard1(_ sender:deleteCard) {
let buttonPosition:CGPoint = sender.convert(CGPointZero, to:self.tableView)
let indexPath = self.tableView.indexPathForRow(at: buttonPosition)
}
I think you don't need to follow this approach because firstly you set button tag statically in storyboard and again you are change it's tag in cellforrowatindexpath so when you scroll, cell will never find button with tag 106.If you want to follow this approach then you need to create customButton and add Variable of type NSInteger or whatever you want and store indexpath.row into that variable of customButton.
Another Approach is Create CustomTableViewCell Class and create button outlet in this custom Cell class and set indexpath.row into button tag like this
CustomCellClassObject.buttonName.tag = indexPath.row
As Sumit said, it’s better to use a custom cell and create outlet for the buttons and labels, as fetching sub views using tags will be tough to maintain the code in the future.
Additionally, you don’t have to create the variable deleteButton, as I don’t see a valid purpose.
Assign tag to the button and add target in cellForRowAtIndexPath, it should work fine.

Image View in custom Table View Cell resizes unexpectedly after touch or scroll

I have a custom table cell inside a table view, which contains a horizontal stack view of image view and text field... The image view mode is ScaleAspectFit
When the view loads initially, the views are arranged as they should be, but when a cell is touched or the table view is scrolled, the image view resizes unexpectedly
Here are screenshots and my code
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("ImagesTableViewCell", forIndexPath: indexPath) as! ImagesTableViewCell
// Configure the cell...
let pic = self.patient!.images[indexPath.row]
cell.imageViewPic.clipsToBounds = true
cell.imageViewPic.contentMode = .ScaleAspectFit
cell.imageViewPic.image = getImage(pic.imagePath)
cell.labelPic.text = pic.caption
cell.imageViewPic.tag = indexPath.row
cell.labelPic.tag = indexPath.row
return cell
}
I tried all Content Modes with no benefit
Edit2: here is getImage() function code as requested
func getImage(filename: String) -> UIImage {
let path = getDocumentsDirectory().stringByAppendingPathComponent(filename)
let image = UIImage(contentsOfFile: path)
return image!
}
Set the clipsToBounds property of UIImageView to true.
Like
set cell.imageViewPic.clipsToBounds=true
Also check the constraint of the imageview. It should be center vertical align,leading, fixed width and fixed height.
try below steps it may can help you.
render ImageView with fixe width and height
make clipSubviews = YES. in story board OR cell.imageViewPic.clipsToBounds = YES;

Two TableViews One Data Source?

I have setup a segue that will show a view controller with a small TableView. I want a different segue to show a bigger TableView but I want the bigger table to have the same exact info as the smaller table. Got the smaller tableView working perfect on its own, but once I give the bigger table a Data source, reset and try it out.....crashes.
// IndexPath or First Cell in TableView
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell = UITableViewCell()
if self.TaskTableViews.hidden == false {
cell = tableView.dequeueReusableCellWithIdentifier( "FirstTask" , forIndexPath: indexPath) as UITableViewCell!
let list = frc.objectAtIndexPath(indexPath) as! List
cell.textLabel?.text = list.taskName
cell.textLabel?.textColor = UIColor.whiteColor()
TaskTableViews.backgroundColor = UIColor.lightGrayColor().colorWithAlphaComponent(0.55)
TaskTableViews.layer.cornerRadius = 8
TaskTableViews.separatorColor?.colorWithAlphaComponent(2.0) }
if self.TaskTable2.hidden == false {
cell = tableView.dequeueReusableCellWithIdentifier( "Second Task" , forIndexPath: indexPath) as UITableViewCell!
let list = frc.objectAtIndexPath(indexPath) as! List
cell.textLabel?.text = list.taskName
cell.textLabel?.textColor = UIColor.whiteColor()
TaskTable2.backgroundColor = UIColor.lightGrayColor().colorWithAlphaComponent(0.55)
TaskTable2.layer.cornerRadius = 8
TaskTable2.separatorColor?.colorWithAlphaComponent(2.0) }
return cell as UITableViewCell
}
The problem is that the code for your two tables is slamming into each other. To fix this, rejigger your logic. Do not make your logic depend on what is hidden. You can handle only one table at a time; just one table is calling here. That table comes in as the tableView parameter. Make your logic depend on that. Depending what table view that tableView parameter is, configure the cell and return it for that table view.
I think that you should consider changing your approach by just resizing the table view dynamically when you go from one scene to the other instead of having two table views if the information is exactly the same.
If you're still pushing for this approach then don't make the condition be that the table view is hidden and instead implement your own logic or boolean to determine this. But again, I'd rather resize a single table view as needed.
You have many problems in your code
1.
var cell = UITableViewCell()
What's the point of this line?
2.
cell = tableView.dequeueReusableCellWithIdentifier( "FirstTask" , forIndexPath: indexPath) as UITableViewCell!
What's the point of casting? This function returns UITableViewCell (not even optional)
3.
cell.textLabel?.text = list.taskName
Should not compile, cause UITableViewCell doesn't have textLabel
4.
TaskTableViews.backgroundColor = UIColor.lightGrayColor().colorWithAlphaComponent(0.55)
What's the point of doing this every cell request? Move this to viewDidLoad or other appropriate place
Your if { } parts are identical except of reuse identifier
Use tableView argument when needed
Use if { } else
8.
return cell as UITableViewCell
Why cast? Just return
I'm sure I haven't found all of them))

viewWithTag in UICollectionViewCell returns nil in Swift (until cell is reused)

This lengthy title is roughly my problem. I started simple learning example using UICollectionView in Swift project.
I added CollectionView to ViewController created by template, assigned delegate and data source. Custom cell is created in storyboard. Reuse identifier is set.
Everything is fine so far. I have placed one UILabel in custom cell, and gave tag value 100.
Here's code of my ViewController: https://gist.github.com/tomekc/becfdf6601ba64d5fd5d
And interesting exceprt below:
func collectionView(collectionView: UICollectionView!, cellForItemAtIndexPath indexPath: NSIndexPath!) -> UICollectionViewCell! {
let cell = collectionView.dequeueReusableCellWithReuseIdentifier("element", forIndexPath: indexPath) as UICollectionViewCell
cell.backgroundColor = UIColor.yellowColor()
// list subviews
NSLog("--- ROW %d ---", indexPath.row)
printSubviews(cell)
if let labelka = cell.viewWithTag(100) as? UILabel {
labelka.text = String(format: "Row %d", indexPath.row)
NSLog("Found label")
}
return cell
}
func printSubviews(view:UIView) {
if let list = view.subviews as? [UIView] {
for uiv in list {
NSLog("%# tag:%d", uiv, uiv.tag)
printSubviews(uiv)
}
}
}
The problem is that cell.viewWithTag(100) returns nil until cell is reused. When I scroll the view so any of cells goes out of window and reuse is forced, viewWithTag(100) returns the label and I can set its value.
What's interesting, I put together similar example in Objective-C and there is no such problem. Even when built and run with XCode6 beta4.
I wonder if I missed something or this is wrong behavior?
Update: apparently I took too simplistic approach. When I created custom UICollectionViewCell subclass (as I usually do), result is correct.

Resources