Custom UIImageView in UITableViewCell being cut off in subsequent cells - Swift - swift

UITableViewCell Custom UIImageView
Image:
Custom TableViewCell UIImageView
If you click on the link above, you'll see that after the first row, the custom UIImageView is being cut off horizontally and then vertically in subsequent rows. Any ideas on how to fix this?
In viewDidLoad I changes row heights as follows:
// Set cell row height
self.tableView.rowHeight = 60
Here's the code for the TableView:
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
var count = Int()
if self.names.count != 0 {
count = self.names.count
} else if self.names.count == 0 {
count = 1
}
return count
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell : UITableViewCell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath) as UITableViewCell
for view in cell.contentView.subviews {
// Clear subviews
view.removeFromSuperview()
}
// Customize separator width
tableView.separatorInset = UIEdgeInsetsZero
cell.separatorInset = UIEdgeInsetsZero
cell.layoutMargins = UIEdgeInsetsZero
cell.preservesSuperviewLayoutMargins = false
// Create imageView
let imageView = UIImageView(frame: CGRectMake(10, 5, 50, 50))
imageView.contentMode = UIViewContentMode.ScaleAspectFit
imageView.layer.cornerRadius = 25
imageView.clipsToBounds = true
cell.contentView.addSubview(imageView)
// Create textLabel
let textLabel = UILabel(frame: CGRectMake(70, 10, self.view.frame.width, 20))
textLabel.font = UIFont(name: "Arial", size: 15.0)
textLabel.textAlignment = .Left
cell.contentView.addSubview(textLabel)
// Create lastMessageLabel
let lastMessageLabel = UILabel(frame: CGRectMake(70, 30, self.view.frame.width, 20))
lastMessageLabel.font = UIFont(name: "Arial", size: 12)
lastMessageLabel.textAlignment = .Left
lastMessageLabel.textColor = UIColor.grayColor()
cell.contentView.addSubview(lastMessageLabel)
if self.names.count != 0 {
// Add contact cell
imageView.image = self.images[indexPath.row]
textLabel.text = self.names[indexPath.row] as? String
lastMessageLabel.text = self.lastMessage[indexPath.row] as? String
}
if self.names.count == 0 {
// Add warning
imageView.image = UIImage(named: "user-placeholder.png")
textLabel.text = "No users saved :("
lastMessageLabel.text = "Tap the search tab to find users."
}
return cell
}
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if self.names.count != 0 {
print(self.names.count)
print(self.names[indexPath.row])
print(self.ids[indexPath.row])
self.selectedUserName = self.names[indexPath.row] as! String
self.selectedUserId = self.ids[indexPath.row] as! String
self.selectedUserImage = self.images[indexPath.row]
self.performSegueWithIdentifier("chat", sender: self)
}
}
override func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == UITableViewCellEditingStyle.Delete && self.userRef.savedUsers.count != 0 {
startActivityIndicator()
let savedUsers = NSMutableArray()
for user in self.userRef.savedUsers {
if user as! String != self.userRef.savedUsers[indexPath.row] as! String {
savedUsers.addObject(user as! String)
}
}
self.rootRef.child("users").child((FIRAuth.auth()?.currentUser?.uid)!).child("savedUsers").setValue(savedUsers, withCompletionBlock: { (error: NSError?, FIRDatabaseReference: FIRDatabaseReference) -> Void in
if error == nil {
print("deleted: \(self.userRef.savedUsers[indexPath.row])")
// Remove user
self.userRef.savedUsers.removeObject(self.userRef.savedUsers[indexPath.row])
self.names.removeObjectAtIndex(indexPath.row)
self.images.removeAtIndex(indexPath.row)
self.lastMessage.removeObjectAtIndex(indexPath.row)
self.stopActivityIndicator()
self.loadUsers()
self.displayAlert("Contact Deleted", message: "The user has been removed from your contacts.")
} else {
self.stopActivityIndicator()
self.displayAlert("Delete Failed", message: "Please try again later.")
}
})
}
}
EDIT:
The problem was imageView.contentMode = UIViewContentMode.ScaleAspectFit which needed to be .ScaleAspectFill

Related

having issues with cached table viewcells

I have the following code
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
let cell = tableView.dequeueReusableCell(withIdentifier: "book", for: indexPath) as! BookTableViewCell
cell.cellIndex = indexPath
cell.dataSource = self
cell.delegate = self
cell.backgroundColor = UIColor.white
var books = [Book]();
let count = self.enterpriseBooks.count;
if count > 0 && indexPath.section < self.enterpriseBooks_2.count {
books = self.enterpriseBooks_2[indexPath.section]!;
}
if (indexPath.section == (count)) {
books = nytbooks;
} else if (indexPath.section == (count + 1)) {
books = trendingbooks;
} else if (indexPath.section == (count + 2)) {
books = newbooks
}
if (books.count > 0) {
if (cell.collectionView === nil) {
cell.addCollectionView();
cell.collectionView.tag = 124;
cell.collectionView.reloadData()
}
}
return cell
}
// BookTableViewCell
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "collectionCell", for: indexPath as IndexPath) as! BookCollectionViewCell
self.dataSource?.getData(cell: self)
let books = self.books
let book = books?[indexPath.row]
if book != nil {
cell.label.text = book?.title
cell.imageView.sd_setImage(with: URL(string: book?.image as! String), placeholderImage: nil)
}
return cell
}
func addCollectionView () {
let flowLayout = UICollectionViewFlowLayout()
flowLayout.scrollDirection = .horizontal
flowLayout.itemSize = CGSize(width: 100, height: self.frame.height)
//You can also provide estimated Height and Width
flowLayout.estimatedItemSize = CGSize(width: 100, height: self.frame.height)
//For Setting the Spacing between cells
flowLayout.minimumInteritemSpacing = 25
flowLayout.minimumLineSpacing = 20
let cellReuseIdentifier = "collectionCell"
self.collectionView = UICollectionView(frame: CGRect(x: 10,
y: 0,
width: self.frame.width,
height: self.frame.height),
collectionViewLayout: flowLayout)
self.collectionView.showsHorizontalScrollIndicator = false
self.collectionView.translatesAutoresizingMaskIntoConstraints = false
self.collectionView.backgroundColor = .clear
self.collectionView.delegate = self
self.collectionView.dataSource = self
self.collectionView.register(BookCollectionViewCell.self, forCellWithReuseIdentifier: cellReuseIdentifier)
self.backgroundColor = UIColor.white
self.addSubview(collectionView)
}
The issue is I'm running into caching issues where content in a table view cell or collection view cell are overlapping with each other. Can anyone please help?
The above content shows images horizontally aligned into three rows using collection views for each.

How to Set data to second tableview in same Class in swift

How to Set data to second tableview in same Class in swift.I am using two tables in the the same controller one for dropdown and another for listing. I am unable to set data to second table(listing) in class
as else part is not called in cellForRowAtIndexPath. Thanks in Advance
import UIKit
class PunchClockVC: UIViewController , UITableViewDataSource, UITableViewDelegate{
var appdel = UIApplication.sharedApplication().delegate as! AppDelegate
#IBOutlet weak var dropdownTable: UITableView!
#IBOutlet weak var mainTable: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
self.mainTable.registerClass(PunchClockCustomCell.self, forCellReuseIdentifier: "PunchClockCustomCell")
self.dropdownTable.registerClass(UITableViewCell.self, forCellReuseIdentifier: "dropdowncell")
self.dropdownTable.hidden = true
}
#IBAction func textFieldTapped(sender: AnyObject) {
if self.dropdownTable.hidden == true {
self.dropdownTable.hidden = false
}
else{
self.dropdownTable.hidden = false
}
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == dropdownTable {
return jobArrayID.count
}
return 8
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if tableView == self.dropdownTable {
let cell = tableView.dequeueReusableCellWithIdentifier("dropdowncell", forIndexPath: indexPath) as UITableViewCell
cell.textLabel?.text = (jobArrayID[indexPath.row] as! String) + "-" + (jobArrayName[indexPath.row] as! String)
return cell
}
else {
let cell1 = tableView.dequeueReusableCellWithIdentifier("PunchClockCustomCell", forIndexPath: indexPath) as! PunchClockCustomCell
if indexPath.row == 0
{
cell1.jobcell?.font = UIFont(name: "MuseoSlab-500", size: 25.0)
cell1.locationcell?.font = UIFont(name: "MuseoSlab-500", size: 25.0)
cell1.timecell?.font = UIFont(name: "MuseoSlab-500", size: 25.0)
cell1.typecell?.font = UIFont(name: "MuseoSlab-500", size: 25.0)
cell1.jobcell?.textColor = UIColor.blackColor()
cell1.locationcell?.textColor = UIColor.blackColor()
cell1.timecell?.textColor = UIColor.blackColor()
cell1.typecell?.textColor = UIColor.blackColor()
cell1.jobcell?.text = "Job"
cell1.locationcell?.text = "Location"
cell1.timecell?.text = "Time"
cell1.typecell?.text = "Type"
// return cell1
}
else {
cell1.jobcell?.text = "Jobdata"
cell1.locationcell?.text = "Locationdata"
cell1.timecell?.text = "Timedata"
cell1.typecell?.text = "OUT"
// return cell1
}
return cell1
}
}
It's quite simple You need to set it only with cellForRowAtIndexPath method but the main thing to do is you need to code like below
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
if tableView == firstTbaleView
//outlet given to first tableView
{
let cell = tableView.dequeueReusableCellWithReuseIdentifier("cell1", forIndexPath: indexPath) as! cust1TableViewCell
cell.imgView.image = images[indexPath.row]
cell.filtLabel.text = self.filtersCount[indexPath.row]
return cell
}}else {
let cell2 = tableView.dequeueReusableCellWithReuseIdentifier("cell2", forIndexPath: indexPath) as! cust2TableViewCell
cell2.imgview.image = UIImage(named: colPhotos[indexPath.row])
cell2.labl.text = colNames[indexPath.row]
// cell2.layer.borderColor = UIColor.blueColor().CGColor
// cell2.layer.borderWidth = 2.0
return cell2
}
and that's it you can ask me for any help..
Lets make this a little safer:
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == self.dropdownTable {
return jobArray.count
}
else if tableView == self.mainTable {
return = 5
}
//Default return 0. This way if references are broken or change, you won't crash
return 0
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if tableView == self.dropdownTable {
let cell = tableView.dequeueReusableCellWithIdentifier("dropdowncell", forIndexPath: indexPath) as! UITableViewCell
//configure your cell
return cell
}
else if tableView == self.mainTable {
let cell = tableView.dequeueReusableCellWithIdentifier("PunchClockCustomCell", forIndexPath: indexPath) as! PunchClockCustomCell
//configure your cell
return cell
}
//Shouln't ever reach here, but again, if we refactor somewhere then we'll see an error show up before here.
return UITableViewCell()
}

Expandable cell with dynamic data (swift)

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("idcell", forIndexPath: indexPath) as UITableViewCell
let lblTitle : UILabel = cell.contentView.viewWithTag(101) as! UILabel
lblTitle.text = (deptId[indexPath.row] as? String)! + " " + (deptDesc[indexPath.row] as? String)!
var height:CGFloat = 0
cell.backgroundColor = UIColor.whiteColor()
cell.accessoryType = UITableViewCellAccessoryType.DisclosureIndicator
if(indexPath == selectedIndexPath){
cell.backgroundColor = UIColor.grayColor()
for i in 0...deptProfile.count-1{
let deptmentProfile = UIButton(frame: CGRectMake(0,44+height,400,41))
deptmentProfile.addTarget(self, action: "buttonAction:", forControlEvents: UIControlEvents.TouchUpInside)
height = height+41
deptmentProfile.setTitle(deptProfile[i] as! String, forState: UIControlState.Normal)
deptmentProfile.setTitleColor(UIColor.blackColor(), forState: .Normal)
deptmentProfile.contentHorizontalAlignment = UIControlContentHorizontalAlignment.Left
deptmentProfile.backgroundColor = UIColor.whiteColor()
deptmentProfile.titleEdgeInsets = UIEdgeInsetsMake(0, 40, 0, 0); //margin to the left
cell.addSubview(deptmentProfile)
}
cell.accessoryType = UITableViewCellAccessoryType.None
}
return cell
}
Question: since my expanded data is dynamic,(In coding)deptProfrile is dynamic. How can i clear the cell content? it seems the subview will remain to the cell every time.
You should notice that the cell is reused, so, you have not coded for the else case for that if: if(indexPath == selectedIndexPath). You should provide the code for UI for that else.
You can give the estimated cell height for the tableview, so it will expand the cell for you.
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
if(indexPath == selectedIndexPath){
var cellHeight = 100 // Assume this is the height when deptProfile.count = 0
cellHeight = cellHeight + 44 * deptProfile.count
return cellHeight
}
return super.tableView(tableView, heightForRowAtIndexPath: indexPath)
}

Swift: How to reload row height in UITableViewCell without reloading data

I have a case in which I have to reload only height of a UITableViewCell.
but if I call the function
tableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: webView.tag, inSection: 0)], withRowAnimation: .Automatic)
it reloads the height as well as the data of the cell.
How can i just control the height of cell in Swift?
This is my cellForRow block :
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if indexPath.row == 0 {
let cell = tableView.dequeueReusableCellWithIdentifier("cell1", forIndexPath: indexPath) as! CustomTableViewCell1
cell.heading.text = headerText
return cell
}
else if indexPath.row == 1 {
let cell = tableView.dequeueReusableCellWithIdentifier("cell2", forIndexPath: indexPath) as! CustomTableViewCell2
ImageLoader.sharedLoader.imageForUrl(self.headerImage , completionHandler:{(image: UIImage?, url: String) in
cell.mainImage.image = image
})
return cell
}
else if indexPath.row == 2 {
let cell = tableView.dequeueReusableCellWithIdentifier("cell3", forIndexPath: indexPath) as! CustomTableViewCell3
//cell.aurthorImage.image = UIImage(named : "obama")
ImageLoader.sharedLoader.imageForUrl(self.headerImage , completionHandler:{(image: UIImage?, url: String) in
cell.aurthorImage.image = image
})
cell.aurthorImage.tag = aurthorID
cell.aurthorImage.layer.cornerRadius = cell.aurthorImage.frame.height/2
cell.aurthorImage.clipsToBounds = true
cell.aurthorImage.userInteractionEnabled = true
cell.aurthorImage.addGestureRecognizer(aurthorImageTapRecignizer)
cell.aurthorName.text = self.authorName
cell.time.text = self.time
self.followButton = cell.followButton
return cell
}
else if indexPath.row == 3 {
let cell = tableView.dequeueReusableCellWithIdentifier("cell4", forIndexPath: indexPath) as! CustomTableViewCell4
let htmlHeight = contentHeights[indexPath.row]
cell.webElement.tag = indexPath.row
cell.webElement.delegate = self
cell.webElement.loadHTMLString(HTMLContent, baseURL: nil)
cell.webElement.frame = CGRectMake(0, 0, cell.frame.size.width, htmlHeight)
return cell
}
else if indexPath.row == 4 {
let cell = tableView.dequeueReusableCellWithIdentifier("cell1", forIndexPath: indexPath) as! CustomTableViewCell1
cell.heading.text = "Related Posts"
return cell
}
else if indexPath.row == 5{
let cell = tableView.dequeueReusableCellWithIdentifier("cell6", forIndexPath: indexPath) as! CustomTableViewCell6
return cell
}
else if indexPath.row == 6 {
let cell = tableView.dequeueReusableCellWithIdentifier("cell1", forIndexPath: indexPath) as! CustomTableViewCell1
cell.heading.text = "Comments"
return cell
}
else if indexPath.row == 7 {
let cell = tableView.dequeueReusableCellWithIdentifier("cell5", forIndexPath: indexPath) as! CustomTableViewCell5
let htmlHeight = contentHeights[indexPath.row]
self.commentSection = cell.commentsView
self.commentSection.tag = indexPath.row
self.commentSection.delegate = self
let url = NSURL(string: commentsURL)
let requestObj = NSURLRequest(URL: url! )
self.commentSection.loadRequest(requestObj)
self.commentSection.frame = CGRectMake(0, 0, cell.frame.size.width, htmlHeight)
commentSectionDidNotLoad = false
return cell
}
else {
let cell = tableView.dequeueReusableCellWithIdentifier("cell1", forIndexPath: indexPath) as! CustomTableViewCell1
cell.heading.text = headerText
return cell
}
You can use this code to update the cell's height without reloading their data:
tableView.beginUpdates()
tableView.endUpdates()
You can also use this method followed by the endUpdates method to animate the change in the row heights without reloading the cell.
UITableView Class Reference
start an update of the tableview and then end it without changing anything.
tableView.beginUpdates()
tableView.endUpdates()
This should make the tableview set the new height
You can regulate the height by either implementing the (a)heightForRowAtIndexPath with logic setting the heights or (b)with auto layout and automatic tableview row height
A.
override func tableView(tableView: UITableView!, heightForRowAtIndexPath indexPath: NSIndexPath!) -> CGFloat {
if [your condition, row == 5 in your comment] {
return 100
} else {
return 40
}
}
Whenever you want to change the height you would just call these two rows
tableView.beginUpdates()
tableView.endUpdates()
B.
in viewDidLoad
tableView.estimatedRowHeight = 40.0
tableView.rowHeight = UITableViewAutomaticDimension
and then you can just expose the layout constraint that set's the cells height and access it to set the height when you want
cell.heightConstraint.constant = 100
tableView.beginUpdates()
tableView.endUpdates()
About your question for example, to give a specific height dimension :
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if indexPath.row == 3 {
return 50.0
}
return 72.0
}
But I think you have a webView inside a cell so, generally, to calculate the dynamic height of a UITableViewCell with a UIWebView:
(this example have two webViews)
class MyTableViewController: UITableViewController, UIWebViewDelegate
{
var content : [String] = ["<!DOCTYPE html><html><head><title>Page Title</title></head><body><h1>My First Heading</h1><p>My first paragraph</p></body></html>", "<HTML><HEAD><TITLE>Coca-Cola</TITLE></HEAD><BODY>In Chinese, Coca-Cola means Bite the Wax Tadpole</BODY></HTML>"]
var contentHeights : [CGFloat] = [0.0, 0.0]
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier("myCustomCell", forIndexPath: indexPath) as! MyCustomCell
let htmlString = content[indexPath.row]
let htmlHeight = contentHeights[indexPath.row]
cell.webView.tag = indexPath.row
cell.webView.delegate = self
cell.webView.loadHTMLString(htmlString, baseURL: nil)
cell.webView.frame = CGRectMake(0, 0, cell.frame.size.width, htmlHeight)
return cell
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat
{
return contentHeights[indexPath.row]
}
func webViewDidFinishLoad(webView: UIWebView)
{
if (contentHeights[webView.tag] != 0.0)
{
// height knowed, no need to reload cell
return
}
contentHeights[webView.tag] = webView.scrollView.contentSize.height
tableView.reloadRowsAtIndexPaths([NSIndexPath(forRow: webView.tag, inSection: 0)], withRowAnimation: .Automatic)
}
}
You can use the view height constraint in the cell, by updating the view in cell height you can update the specific cell height.
let height = cell.Height_constraint.constant
cell.Height_constraint.constant = height + 200 //200 you can use any number
Height_constraint: is the height constraint of subView in my cell.

Custom Checkbox AccessoryView for UITableView

I am using Custom AccessoryView for UITableViewCell. I am using a checkbox. Here, I want multiple selection. The code works fine while selection but while deselecting it I am having issues. I am not sure what I should be writing in cellForRowAtIndexPathMethod. The issue I am facing is, after deselecting the checkbox, I cannot select it again. Here is my code:
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let fourthCell = tableView.dequeueReusableCellWithIdentifier("fourthCell", forIndexPath: indexPath) as! ItemDetailFourthTableViewCell
if indexPath != self.lastIndexPath {
fourthCell.accessoryView = UIImageView(image: UIImage(named: "checkBoxPassive.png"))
fourthCell.accessoryView?.tag = 2
}
if indexPath == self.lastIndexPath {
fourthCell.accessoryView = UIImageView(image: UIImage(named: "checkBoxActive.png"))
}
return fourthCell
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
tableView.deselectRowAtIndexPath(indexPath, animated: true)
self.isSelected = true
self.lastIndexPath == indexPath
if indexPath.section == 1 {
let cell = tableView.cellForRowAtIndexPath(indexPath) as! ItemDetailFourthTableViewCell
print("The cell here is \(cell)")
print("Here the cell accessoryView is \(cell.accessoryView?.tag)")
if cell.accessoryView?.tag == 0 {
print("It is active")
cell.accessoryView = UIImageView(image: UIImage(named: "checkBoxPassive.png"))
} else if cell.accessoryView?.tag == 2 {
print("It is passive")
cell.accessoryView = UIImageView(image: UIImage(named: "checkBoxActive.png"))
}
}
}