Related
I am trying to programmatically draw my CollectionView from within a custom class that subclasses UIView. The app loads up with no errors and the CollectionView is being drawn correctly as I can see the cell items, but the CollectionView does not respond to touch. When I try to scroll nothing happens.
I inspected the ViewController using the Debug View Hierarchy button in Xcode to see if there was possibly a view on top. There was not and I could see the cells clearly drawn separately.
Class:
class DrawUI_mainCollectionView : UIView, UICollectionViewDelegate, UICollectionViewDataSource {
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
var collectionView : UICollectionView?
private func setup() {
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.itemSize = CGSize(width: CGFloat(kScreenWidth),height: 137)
let offset = 120.0
let collectionViewFrame = CGRect(x: 0, y: offset, width: Double(kScreenWidth), height: Double(kScreenHeight))
self.collectionView = UICollectionView(frame: collectionViewFrame, collectionViewLayout: layout)
self.collectionView!.alwaysBounceVertical = true
self.collectionView!.delegate = self
self.collectionView!.dataSource = self
self.collectionView!.register(UINib(nibName: "MealCategoryCell", bundle:Bundle.main), forCellWithReuseIdentifier: "cell")
self.addSubview(self.collectionView!)
}
func numberOfSections(in collectionView: UICollectionView) -> Int {
return 1
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 20
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! MealCategoryCell
cell.label.text = "test"
cell.textDescription.text = "textDescription"
return cell
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: kScreenWidth, height: 137)
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
print("cell \(indexPath.row)")
}
required init?(coder aDecoder: NSCoder) {
fatalError("no storyboard...")
}
}
How I am implementing it on my ViewController
let collectionView = DrawUI_mainCollectionView()
self.view.addSubview(collectionView)
What am I doing wrong? Thanks in advance.
I think your main issue is not using auto layout, if you will add auto layout for the items:
view that contains the collectionView in viewController
collectionView in the view
It should work, the implementation:
In ViewController:
let collectionView = DrawUI_mainCollectionView()
collectionView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(collectionView)
NSLayoutConstraint(item: collectionView , attribute: .leading, relatedBy: .equal, toItem: self.view, attribute: .leadingMargin, multiplier: 1.0, constant: 0.0).isActive = true
NSLayoutConstraint(item: collectionView , attribute: .trailing, relatedBy: .equal, toItem: self.view, attribute: .trailingMargin, multiplier: 1.0, constant: 0.0).isActive = true
NSLayoutConstraint(item: collectionView , attribute: .top, relatedBy: .equal, toItem: self.view, attribute: .topMargin, multiplier: 1.0, constant: 0.0).isActive = true
NSLayoutConstraint(item: collectionView , attribute: .bottom, relatedBy: .equal, toItem: self.view, attribute: .bottomMargin, multiplier: 1.0, constant: 0.0).isActive = true
Inside the view:
private func setup() {
let layout: UICollectionViewFlowLayout = UICollectionViewFlowLayout()
layout.scrollDirection = .vertical
layout.itemSize = CGSize(width: CGFloat(kScreenWidth),height: 137)
let offset = 120.0
let collectionViewFrame = CGRect(x: 0, y: offset, width: Double(kScreenWidth), height: Double(kScreenHeight))
self.collectionView = UICollectionView(frame: collectionViewFrame, collectionViewLayout: layout)
self.collectionView!.alwaysBounceVertical = true
self.collectionView!.delegate = self
self.collectionView!.dataSource = self
self.collectionView!.register(UINib(nibName: "MealCategoryCell", bundle:Bundle.main), forCellWithReuseIdentifier: "cell")
self.collectionView!.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(self.collectionView!)
NSLayoutConstraint(item: collectionView , attribute: .leading, relatedBy: .equal, toItem: self, attribute: .leadingMargin, multiplier: 1.0, constant: 0.0).isActive = true
NSLayoutConstraint(item: collectionView , attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailingMargin, multiplier: 1.0, constant: 0.0).isActive = true
NSLayoutConstraint(item: collectionView , attribute: .top, relatedBy: .equal, toItem: self, attribute: .topMargin, multiplier: 1.0, constant: 0.0).isActive = true
NSLayoutConstraint(item: collectionView , attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottomMargin, multiplier: 1.0, constant: 0.0).isActive = true
}
I am having UIView() class where I am adding a label programatically and also given constraints to automatically adjust height of view based on content. I have used this class as HeaderView for a UItableView section. But the problem here is the height of this view is not adjusting accordingly to its content.
Here he is my code of that custom View.
class DynamicHeaderView: UIView {
override func draw(_ rect: CGRect) {
let headerLabel = UILabel()
headerLabel.numberOfLines = 0
headerLabel.sizeToFit()
headerLabel.text = "This is header view. It is dynamicaaly growing text and will automaticaly get adjusted to it"
self.backgroundColor = .green
headerLabel.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(headerLabel)
self.addConstraint(NSLayoutConstraint(item: headerLabel, attribute: .leading, relatedBy: .equal, toItem: self, attribute: .leading, multiplier: 1, constant: 16))
self.addConstraint(NSLayoutConstraint(item: headerLabel, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailing, multiplier: 1, constant: -16))
self.addConstraint(NSLayoutConstraint(item: headerLabel, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1, constant: 10))
self.addConstraint(NSLayoutConstraint(item: headerLabel, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1, constant: -10))
} }
Code that I have written in my viewController,
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
self.countriesTable.sectionHeaderHeight = UITableView.automaticDimension;
self.countriesTable.estimatedSectionHeaderHeight = 25 }
func tableView(_ tableView: UITableView,
viewForHeaderInSection section: Int) -> UIView? {
let headerView = DynamicHeaderView()
return headerView
}
The height is always stick to the estimated header height as 25 which i have given in viewDidLoad() function.
You need to subclass UITableViewHeaderFooterView , then register the tableView with it , finally implement viewForHeaderInSection
class DynamicHeaderView: UITableViewHeaderFooterView {
let headerLabel = UILabel()
override init(reuseIdentifier: String?) {
super.init(reuseIdentifier: reuseIdentifier)
headerLabel.numberOfLines = 0
// headerLabel.sizeToFit()
headerLabel.text = "This is header view. It is dynamicaaly growing text and will automaticaly get adjusted to it"
self.backgroundColor = .green
headerLabel.translatesAutoresizingMaskIntoConstraints = false
self.addSubview(headerLabel)
headerLabel.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 1000), for: .vertical)
self.addConstraint(NSLayoutConstraint(item: headerLabel, attribute: .leading, relatedBy: .equal, toItem: self, attribute: .leading, multiplier: 1, constant: 16))
self.addConstraint(NSLayoutConstraint(item: headerLabel, attribute: .trailing, relatedBy: .equal, toItem: self, attribute: .trailing, multiplier: 1, constant: -16))
self.addConstraint(NSLayoutConstraint(item: headerLabel, attribute: .top, relatedBy: .equal, toItem: self, attribute: .top, multiplier: 1, constant: 10))
self.addConstraint(NSLayoutConstraint(item: headerLabel, attribute: .bottom, relatedBy: .equal, toItem: self, attribute: .bottom, multiplier: 1, constant: 10))
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
//
In viewDidLoad
tableView.register(DynamicHeaderView.self, forHeaderFooterViewReuseIdentifier: "celld")
tableView.estimatedSectionHeaderHeight = 50
tableView.sectionHeaderHeight = UITableView.automaticDimension
//
func tableView(_ tableView: UITableView,
viewForHeaderInSection section: Int) -> UIView? {
let headerView = tableView.dequeueReusableHeaderFooterView(withIdentifier: "celld") as! DynamicHeaderView
headerView.headerLabel.text = "heightForHeaderInSectionheightForHeaderInSectionheightForHeaderInSectionheightForHeaderInSectionheightForHeaderInSectionheightForHeaderInSection"
return headerView
}
To make uiview on top of all tabs of uitabbar controller .
I planned to make one baseviewcontroller named "uiView.swift" .In "uiView.swift" i added my uiview. After that i want to inherit each tab ViewController (say "resturent.swift") from that uiView.swift. So, in each tab of UITabBarController you will get that "uiView.swift" view resued.uiView.swift is connected to ViewController in Storyboard that has button that show the view on button click .Here is my "uiView.swift"
class uiView: UIViewController {
var menuView: UIView?
override func viewDidLoad() {
super.viewDidLoad()
menuView = UIView(frame: CGRect(x: 0, y: -200, width: 420, height: 200))
menuView?.backgroundColor = UIColor.green
view.addSubview(menuView!)
}
#objc func MyBag(){
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func collectionmenuone(_ sender: Any) {
menuView=UIView(frame: CGRect(x: 0, y: 0, width: 420, height: 200))
menuView?.backgroundColor=UIColor.lightGray
self.view.addSubview(menuView!)
var btnbag = UIButton(type: .roundedRect)
btnbag.addTarget(self, action: #selector(self.MyBag), for: .touchUpInside)
btnbag.frame = CGRect(x: 104, y:130 , width: 150, height: 60)
btnbag.setTitle("Done", for: .normal)
btnbag.backgroundColor=UIColor.green
menuView?.addSubview(btnbag)
}
}
how i can make possible reuse of view from "uiView.swift" in each tab of tabbar controller (i.e "resturent.swif")
class resturent:UICollectionViewController,UICollectionViewDelegateFlowLayout {
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title="Seafood"
collectionView?.backgroundColor=UIColor.white
// view.backgroundColor=UIColor.redColor
collectionView?.register(VideoCell.self, forCellWithReuseIdentifier: "cellid")
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 5
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell=collectionView.dequeueReusableCell(withReuseIdentifier: "cellid", for: indexPath)
// cell.backgroundColor=UIColor.red
return cell
}
/* override func collectionView(collectionView: UICollectionView, cellForItemAtIndexpath indexPath: NSIndexPath) -> UICollectionViewCell {
let cell=collectionView.dequeueReusableCell(withReuseIdentifier: "cellId", for: indexPath as IndexPath)
return cell
}*/
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let height=(view.frame.width - 16 - 16) * 9/16
return CGSize(width: view.frame.width, height: height + 16 + 68)
}
}
class VideoCell:UICollectionViewCell{
override init(frame: CGRect) {
super.init(frame: frame)
setupView()
}
let thumbnailImageView:UIImageView = {
let imageView=UIImageView()
imageView.backgroundColor=UIColor.blue
imageView.image=UIImage(named: "food24")
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds=true
return imageView
}()
let userProfileImageView:UIImageView={
let imageView=UIImageView()
//imageView.backgroundColor=UIColor.green
return imageView
}()
let separatorView:UIView = {
let view = UIView ()
view.backgroundColor=UIColor(red: 230/255, green: 230/255, blue: 230/255, alpha: 1)
return view
}()
let titleLabel:UILabel={
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints=false
label.text="Resturant name here"
return label
}()
let subtitleTextView:UITextView = {
let textView=UITextView()
textView.translatesAutoresizingMaskIntoConstraints=false
textView.textContainerInset=UIEdgeInsetsMake(0, -4, 0, 0)
textView.textColor=UIColor.lightGray
textView.text = "SeaFood"
return textView
}()
func setupView() {
//backgroundColor=UIColor.blue
addSubview(thumbnailImageView)
addSubview(separatorView)
addSubview(userProfileImageView)
addSubview(titleLabel)
addSubview(subtitleTextView)
addConstraintsWithFormat(format: "H:|-16-[v0]-16-|", view: thumbnailImageView)
addConstraintsWithFormat(format: "H:|-16-[v0(44)]", view: userProfileImageView)
//vertial constratints
addConstraintsWithFormat(format: "V:|-16-[v0]-8-[v1(44)]-16-[v2(1)]|", view: thumbnailImageView,userProfileImageView,separatorView)
addConstraintsWithFormat(format: "H:|[v0]|", view: separatorView)
//top constraints
addConstraint(NSLayoutConstraint(item: titleLabel, attribute: .top, relatedBy: .equal, toItem:thumbnailImageView , attribute: .bottom, multiplier: 1, constant: 8))
//left constaints
addConstraint(NSLayoutConstraint(item: titleLabel, attribute: .left, relatedBy: .equal, toItem: userProfileImageView, attribute: .right, multiplier: 1, constant: 8))
//right constraint
addConstraint(NSLayoutConstraint(item: titleLabel, attribute: .right, relatedBy: .equal, toItem: thumbnailImageView, attribute: .right, multiplier: 8, constant: 0))
//height constraint
addConstraint(NSLayoutConstraint(item: titleLabel, attribute: .height, relatedBy: .equal, toItem: self, attribute: .height, multiplier: 0, constant: 20))
//top constraints
addConstraint(NSLayoutConstraint(item: subtitleTextView, attribute: .top, relatedBy: .equal, toItem:titleLabel , attribute: .bottom, multiplier: 1, constant: 4))
//left constaints
addConstraint(NSLayoutConstraint(item: subtitleTextView, attribute: .left, relatedBy: .equal, toItem: userProfileImageView, attribute: .right, multiplier: 1, constant: 8))
//right constraint
addConstraint(NSLayoutConstraint(item: subtitleTextView, attribute: .right, relatedBy: .equal, toItem: thumbnailImageView, attribute: .right, multiplier: 8, constant: 0))
//height constraint
addConstraint(NSLayoutConstraint(item: subtitleTextView, attribute: .height, relatedBy: .equal, toItem: self, attribute: .height, multiplier: 0, constant: 20))
// addConstraintsWithFormat(format: "V:[v0(20)]", view: titleLabel)
// addConstraintsWithFormat(format: "H:|[v0]|", view: titleLabel)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
extension UIView{
func addConstraintsWithFormat(format:String,view:UIView...){
var viewDictionary=[String:UIView]()
for (index,view) in view.enumerated(){
let key="v\(index)"
view.translatesAutoresizingMaskIntoConstraints=false
viewDictionary[key]=view
}
NSLayoutConstraint.activate(NSLayoutConstraint.constraints(withVisualFormat: format , options: NSLayoutFormatOptions(), metrics: nil, views: viewDictionary))
}
}
uiView.swift is of type UIViewController and resturent.swif is of type UICollectionViewController.You can change the entry point of app from uiView.swift to login View controller(Viewcontroller.swift) to run app.How by inheritance i can reuse the view in uiView.swift ?you can download the project from this link .https://drive.google.com/file/d/1XSwOZcfvglB_7Zt_E8W8W3Dym3i1_lrB/view?usp=sharing
You should not add your menu View on any of your view. Instead of this you can direct add it on your window from AppDelegate.
Adding a view on window will place it above all the views that is been currently visible.
I think I have looked through a lot of questions like mine but nothing seems to work.
I am sending request to the server and in the moment I get all the data, I am starting to fill my ViewController programmatically. And all this happening in main_queue
This is the code of adding table:
if self.attachments.count > 0 {
docTableView = UITableView(frame: CGRect(x: 0.0, y: 0.0, width: self.myView.frame.width, height: 500.0), style: UITableViewStyle.Plain)
docTableView!.translatesAutoresizingMaskIntoConstraints = false
docTableView!.registerNib(UINib(nibName: "MenuCell", bundle: nil), forCellReuseIdentifier: "MenuCell")
self.myView.addSubview(docTableView!)
docTableView!.dataSource = self
docTableView!.delegate = self
self.myView.addConstraint(NSLayoutConstraint(item: docTableView!, attribute: .Top, relatedBy: .Equal, toItem: subviews!.last, attribute: .Bottom, multiplier: 1.0, constant: 5.0))
self.myView.addConstraint(NSLayoutConstraint(item: docTableView!, attribute: .Leading, relatedBy: .Equal, toItem: self.headerStackView, attribute: .Leading, multiplier: 1.0, constant: 0))
self.docTableView?.reloadData()
subviews?.append(docTableView!)
}
Then, I realized that two methods have been called : numberOfRowsInSection, heightForRowAtIndexPath and even the count of elements is greater than 0.
But cellForRowAtIndexPath is not being called and I guess that the reason that I do not see the tableView at all.
So how can I get to it?
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if tableView == self.docTableView {
return attachments.count
}
else {
return self.notificationViewModel!.comments.count
}
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 100.0 // I add this to show that its not zero
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if tableView == self.docTableView {
let object = attachments[indexPath.row]
UIApplication.sharedApplication().openURL(NSURL(string: object.Url!)!)
}
}
So commTableView is the same as docTableView. I need both of them and they have the same problem.
EDIT: I have this hierarchy: View->ScrollView->myView
EDIT2: My ViewController code. I have different types of data to add but all of it needs tables of attachments and comments
class NotificationViewController: UIViewController, MarkChosenDelegate, UITableViewDataSource, UITableViewDelegate {
//IBOutlets FROM STORYBOARD
#IBOutlet weak var myView: UIView!
#IBOutlet weak var headerStackView: UIStackView!
#IBOutlet weak var setMarkButton: UIButton!
#IBOutlet weak var placingWayCodeLabel: UILabel!
#IBOutlet weak var leftDaysLabel: UILabel!
#IBOutlet weak var typeLabel: UILabel!
#IBOutlet weak var regionLabel: UILabel!
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var notificationNameLabel: UILabel!
#IBOutlet weak var markColorButton: UIButton!
var docTableView:UITableView?
var commTableView:UITableView?
var delegate:NewMarkSetProtocol?
var notificationViewModel: NotificationViewModel?
var attachments:[Attachment] = []
//FIELDS FOR SEGUE TO THE CUSTOMER
var customerGuid:String?
var customerName:String?
var inn:String?
var kpp:String?
let marks = DataClass.sharedInstance.marks
var viewUtils:ViewUtils?
var notificationItem: NotificationT? {
didSet {
self.setUpTheHeaderInformation()
}
}
//VIEW CONTROLLER LIFE CYCLES METHODS
override func viewDidLoad() {
super.viewDidLoad()
self.setUpTheHeaderInformation()
viewUtils = ViewUtils()
viewUtils?.showActivityIndicator(self.view)
notificationViewModel = NotificationViewModel()
notificationViewModel?.delegateComments = self
notificationViewModel?.delegateInformation = self
if (notificationItem != nil) {
if UsefulClass.isConnectedToNetwork() == true {
notificationViewModel!.getNotification(notificationItem!)
notificationViewModel!.getComments((notificationItem?.NotificationGuid)!)
} else {
notificationViewModel!.getCoreNotification(notificationItem!)
}
}
print(setMarkButton)
}
func setUpTheHeaderInformation() {
if let notificationT = self.notificationItem {
self.navigationItem.title = notificationT.OrderName
self.notificationItem?.IsRead = true
if let label = self.notificationNameLabel {
label.text = notificationT.OrderName
self.placingWayCodeLabel.text = notificationT.getPlacingWayId()
self.leftDaysLabel.text = notificationT.getLeft()
self.typeLabel.text = notificationT.getType()
if (marks.count != 0) {
var mark:MarkClass?
for i in 0..<marks.count {
if (marks[i].Id == notificationT.MarkId) {
mark = marks[i]
}
}
if let _mark = mark {
self.setMarkButton.setTitle(String(_mark.Name!), forState: .Normal)
self.markColorButton.hidden = false
self.markColorButton.backgroundColor = UsefulClass.colorWithHexString(_mark.Color!)
} else {
self.markColorButton.hidden = true
}
}
if let code = notificationT.RegionCode {
self.regionLabel.text = UsefulClass.regionByRegionCode(code)
}
}
}
}
//TABLE VIEW
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let count:Int = 2
if tableView == self.docTableView {
print(attachments.count)
return attachments.count
}
if tableView == self.commTableView {
return self.notificationViewModel!.comments.count
}
return count
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 100.0
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
if tableView == self.docTableView {
let object = attachments[indexPath.row]
UIApplication.sharedApplication().openURL(NSURL(string: object.Url!)!)
}
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
if tableView == self.docTableView {
let cell = tableView.dequeueReusableCellWithIdentifier("MenuCell", forIndexPath: indexPath) as! MenuCell
let object = attachments[indexPath.row]
let endIndex = object.FileName!.endIndex.advancedBy(-4)
let type:String = (object.FileName?.substringFromIndex(endIndex))!
cell.imageMark.image = notificationViewModel!.getImageForAttachment(type)
cell.name.text = object.FileName
cell.count.text = ""
return cell
} else {
let cell = tableView.dequeueReusableCellWithIdentifier("CommentItemCell", forIndexPath: indexPath) as! CommentTableViewCell
let object = self.notificationViewModel!.comments[indexPath.row]
if let name = object.getCreatorName() {
cell.nameUser.text = name
}
cell.textComment.text = object.Text
//cell.imageUser.image =
cell.timeComment.text = object.getTime()
return cell
}
}
func tableView(tableView: UITableView, canEditRowAtIndexPath indexPath: NSIndexPath) -> Bool {
if tableView == self.commTableView {
return true
} else {
return false
}
}
func tableView(tableView: UITableView, commitEditingStyle editingStyle: UITableViewCellEditingStyle, forRowAtIndexPath indexPath: NSIndexPath) {
if editingStyle == .Delete {
Requests.deleteComment(notificationViewModel!.comments[indexPath.row].Id!, notificationGuid: (self.notificationItem?.NotificationGuid)!)
notificationViewModel?.comments.removeAtIndex(indexPath.row)
self.commTableView!.reloadData()
} else {
}
}
extension String {
func heightWithConstrainedWidth(width: CGFloat, font: UIFont) -> CGFloat {
let constraintRect = CGSize(width: width, height: CGFloat.max)
let boundingBox = self.boundingRectWithSize(constraintRect, options: NSStringDrawingOptions.UsesLineFragmentOrigin, attributes: [NSFontAttributeName: font], context: nil)
return boundingBox.height
}
}
extension NSAttributedString {
func heightWithConstrainedWidth(width: CGFloat) -> CGFloat {
let constraintRect = CGSize(width: width, height: CGFloat.max)
let boundingBox = self.boundingRectWithSize(constraintRect, options: NSStringDrawingOptions.UsesLineFragmentOrigin, context: nil)
return ceil(boundingBox.height)
}
func widthWithConstrainedHeight(height: CGFloat) -> CGFloat {
let constraintRect = CGSize(width: CGFloat.max, height: height)
let boundingBox = self.boundingRectWithSize(constraintRect, options: NSStringDrawingOptions.UsesLineFragmentOrigin, context: nil)
return ceil(boundingBox.width)
}
}
extension NotificationViewController:NotificationInformationUpdate {
func informationUpdate() {
var subviews:[UIView]? = [UIView]()
switch(notificationItem?.Type)! {
case 0:
let notification = notificationViewModel?.notification as! Notification_223
self.attachments = notification.attachments
if let name = notification.TenderPlanOrganisationName {
subviews = addTitleandValue("Заказчик", _value: name, _subviews: subviews!, numberOfLines: 0)
}
if let initialSum = notification.InitialSum {
subviews = addTitleandValue("Цена контракта", _value: initialSum, _subviews: subviews!, numberOfLines: 0)
} else if let maxPrice = notificationItem?.MaxPrice {
subviews = addTitleandValue("Цена контракта", _value: UsefulClass.getMaxPrice(maxPrice), _subviews: subviews!, numberOfLines: 0)
}
break
case 1:
let notification = notificationViewModel?.notification as! Notification_44
self.attachments = notification.attachments!
let customerNameTitle = UILabel()
customerNameTitle.text = "Заказчик:"
customerNameTitle.translatesAutoresizingMaskIntoConstraints = false
customerNameTitle.textColor = UIColor.grayColor()
setSimilarConstraintsToTitlesLabels(customerNameTitle, relatedView: self.headerStackView)
let customerName = UILabel()
customerName.text = notification.TenderPlanOrganisationName
customerName.textColor = UIColor.blueColor()
customerName.userInteractionEnabled = true
let tapGester = UITapGestureRecognizer(target: self, action: #selector(NotificationViewController.customerNameClick(_:)))
customerName.addGestureRecognizer(tapGester)
subviews = setSimilarConstraintsToValuesLabels(customerName, relatedView: customerNameTitle, _subViews: subviews!)
if let maxprice = notificationItem?.MaxPrice {
subviews = addTitleandValue("Цена контракта", _value: UsefulClass.getMaxPrice(maxprice), _subviews: subviews!, numberOfLines: 0)
}
break
case 2:
let notification = notificationViewModel?.notification as! B2BNotification
self.attachments = notification.attachments
subviews = addTitleandValue("Заказчик", _value: notification.TenderPlanOrganisationName!, _subviews: subviews!, numberOfLines: 0)
if let priceTotal = notification.PriceTotal {
var value = UsefulClass.getMaxPrice(priceTotal)
if let pricevat = notification.PriceVAT {
value.appendContentsOf(" (" + pricevat + ")")
}
subviews = addTitleandValue("Начальная цена всего лота", _value: value, _subviews: subviews!, numberOfLines: 0)
} else {
subviews = addTitleandValue("Начальная цена всего лота", _value: "Отсутствует поле", _subviews: subviews!, numberOfLines: 0)
}
if let priceone = notification.PriceOne {
subviews = addTitleandValue("Цена за единицу продукции", _value: UsefulClass.getMaxPrice(priceone), _subviews: subviews!, numberOfLines: 0)
}
break
case 7, 17:
let notification = notificationViewModel?.notification as! TakTorgNotification
self.attachments = notification.attachments
subviews = addTitleandValue("Наименование заказа", _value: notification.Subject!, _subviews: subviews!, numberOfLines: 0)
if let procNumber = notification.ProcedureProcedureNumber {
subviews = addTitleandValue("Номер закупки", _value: procNumber, _subviews: subviews!, numberOfLines: 0)
} else if let procNumber2 = notification.ProcedureProcedureNumber2 {
subviews = addTitleandValue("Номер закупки", _value: procNumber2, _subviews: subviews!, numberOfLines: 0)
}
if let startPrice = notification.StartPrice {
subviews = addTitleandValue("Начальная цена", _value: UsefulClass.getMaxPrice(startPrice), _subviews: subviews!, numberOfLines: 0)
}
if let peretorgPossible = notification.ProcedurePeretorgPossible {
subviews = addTitleandValue("Возможность проведения процедуры переторжки", _value: peretorgPossible, _subviews: subviews!, numberOfLines: 0)
}
if let negotiationPossible = notification.ProcedureNegotiationPossible {
subviews = addTitleandValue("Возможность проведения переговоров", _value: negotiationPossible, _subviews: subviews!, numberOfLines: 0)
}
//….
break
default:
break
}
let documentsTitle = UILabel()
documentsTitle.text = "Документы закупки"
documentsTitle.textColor = UIColor.blackColor()
documentsTitle.translatesAutoresizingMaskIntoConstraints = false
documentsTitle.font = documentsTitle.font.fontWithSize(18)
self.myView.addSubview(documentsTitle)
self.myView.addConstraint(NSLayoutConstraint(item: documentsTitle, attribute: .Top, relatedBy: .Equal, toItem: subviews!.last, attribute: .Bottom, multiplier: 1.0, constant: 12.0))
self.myView.addConstraint(NSLayoutConstraint(item: documentsTitle, attribute: .Leading, relatedBy: .Equal, toItem: self.headerStackView, attribute: .Leading, multiplier: 1.0, constant: 0))
subviews?.append(documentsTitle)
if self.attachments.count > 0 {
docTableView = UITableView()
docTableView!.translatesAutoresizingMaskIntoConstraints = false
docTableView!.registerNib(UINib(nibName: "MenuCell", bundle: nil), forCellReuseIdentifier: "MenuCell")
self.myView.addSubview(docTableView!)
docTableView!.dataSource = self
docTableView!.delegate = self
self.myView.addConstraint(NSLayoutConstraint(item: docTableView!, attribute: .Top, relatedBy: .Equal, toItem: subviews!.last, attribute: .Bottom, multiplier: 1.0, constant: 5.0))
self.myView.addConstraint(NSLayoutConstraint(item: docTableView!, attribute: .Leading, relatedBy: .Equal, toItem: self.headerStackView, attribute: .Leading, multiplier: 1.0, constant: 0))
self.myView.addConstraint(NSLayoutConstraint(item: docTableView!, attribute: .Height, relatedBy: .Equal, toItem: nil, attribute: .NotAnAttribute, multiplier: 1.0, constant: 300.0))
self.docTableView?.reloadData()
subviews?.append(docTableView!)
}
if notificationViewModel?.comments.count > 0 {
commTableView = UITableView()
commTableView?.translatesAutoresizingMaskIntoConstraints = false
commTableView!.registerNib(UINib(nibName: "CommentCell", bundle: nil), forCellReuseIdentifier: "CommentItemCell")
self.myView.addSubview(commTableView!)
self.myView.addConstraint(NSLayoutConstraint(item: commTableView!, attribute: .Top, relatedBy: .Equal, toItem: subviews!.last, attribute: .Bottom, multiplier: 1.0, constant: 5.0))
self.myView.addConstraint(NSLayoutConstraint(item: commTableView!, attribute: .Leading, relatedBy: .Equal, toItem: self.headerStackView, attribute: .Leading, multiplier: 1.0, constant: 0))
subviews?.append(commTableView!)
commTableView?.dataSource = self
commTableView?.delegate = self
}
//TITLE
let addCommentLabel = UILabel()
addCommentLabel.text = "Добавьте свой комментарий"
addCommentLabel.translatesAutoresizingMaskIntoConstraints = false
addCommentLabel.textColor = UIColor.lightGrayColor()
self.myView.addSubview(addCommentLabel)
self.myView.addConstraint(NSLayoutConstraint(item: addCommentLabel, attribute: .Top, relatedBy: .Equal, toItem: subviews!.last, attribute: .Bottom, multiplier: 1.0, constant: 10.0))
self.myView.addConstraint(NSLayoutConstraint(item: addCommentLabel, attribute: .Leading, relatedBy: .Equal, toItem: self.headerStackView, attribute: .Leading, multiplier: 1.0, constant: 0))
subviews?.append(addCommentLabel)
let textField = UITextField()
textField.translatesAutoresizingMaskIntoConstraints = false
textField.borderStyle = .RoundedRect
self.myView.addSubview(textField)
self.myView.addConstraint(NSLayoutConstraint(item: textField, attribute: .Top, relatedBy: .Equal, toItem: subviews!.last, attribute: .Bottom, multiplier: 1.0, constant: 5.0))
self.myView.addConstraint(NSLayoutConstraint(item: textField, attribute: .Leading, relatedBy: .Equal, toItem: self.headerStackView, attribute: .Leading, multiplier: 1.0, constant: 0))
self.myView.addConstraint(NSLayoutConstraint(item: textField, attribute: .Width, relatedBy: .Equal, toItem: self.myView, attribute: .Width, multiplier: 1.0, constant: -15))
subviews?.append(textField)
let sendButton = UIButton()
sendButton.setTitle("Отправить", forState: .Normal)
sendButton.translatesAutoresizingMaskIntoConstraints = false
sendButton.backgroundColor = UIColor.blueColor()
sendButton.setTitleColor(UIColor.whiteColor(), forState: .Normal)
self.myView.addSubview(sendButton)
self.myView.addConstraint(NSLayoutConstraint(item: sendButton, attribute: .Top, relatedBy: .Equal, toItem: subviews!.last, attribute: .Bottom, multiplier: 1.0, constant: 5.0))
self.myView.addConstraint(NSLayoutConstraint(item: textField, attribute: .Trailing, relatedBy: .Equal, toItem: textField, attribute: .Trailing, multiplier: 1.0, constant: 0))
subviews?.append(sendButton)
var height:CGFloat = 0.0
for i in 0..<self.myView.subviews.count {
height = height + myView.subviews[i].bounds.height
}
self.myView.frame = CGRect(x: 0, y: 0, width: self.myView.frame.width, height: self.myView.frame.height + height)
self.view.frame = CGRect(x: 0, y: 0, width: self.myView.frame.width, height: self.view.frame.height + height)
self.scrollView.frame = CGRect(x: 0, y: 0, width: self.myView.frame.width, height: self.scrollView.frame.height + height)
self.scrollView.contentSize = CGSize(width: self.myView.frame.width, height: self.scrollView.frame.height + height)
subviews = nil
self.viewUtils?.hideActivityIndicator(self.view)
}
func addPubDate(_subviews:[UIView], date:String, number:String) -> [UIView] {
var subviews = _subviews
let pubDateLabel = UILabel()
pubDateLabel.text = "Дата публикации: " + UsefulClass.covertDataWithZ(date, withTime: false)
pubDateLabel.translatesAutoresizingMaskIntoConstraints = false
pubDateLabel.textColor = UIColor.blackColor()
pubDateLabel.font = pubDateLabel.font.fontWithSize(11)
self.myView.addSubview(pubDateLabel)
self.myView.addConstraint(NSLayoutConstraint(item: pubDateLabel, attribute: .Top, relatedBy: .Equal, toItem: subviews.last, attribute: .Bottom, multiplier: 1.0, constant: 8.0))
self.myView.addConstraint(NSLayoutConstraint(item: pubDateLabel, attribute: .Leading, relatedBy: .Equal, toItem: self.headerStackView, attribute: .Leading, multiplier: 1.0, constant: 0))
subviews.append(pubDateLabel)
notificationUrlNumber(subviews, relatedView: pubDateLabel, number: number)
return subviews
}
func notificationUrlNumber(subviews:[UIView], relatedView:UILabel, number:String) {
let label = UILabel()
label.text = "Извещение №: " + number
label.textColor = UIColor.blueColor()
setSimilarConstraintsToValuesLabels(label, relatedView: relatedView, _subViews: subviews)
}
//левый заголовок для поля
func addtitle(_title:String, _subviews:[UIView]) -> [UIView] {
var subviews = _subviews
let title = UILabel()
title.text = _title
title.numberOfLines = 0
title.textColor = UIColor.blackColor()
title.translatesAutoresizingMaskIntoConstraints = false
title.font = title.font.fontWithSize(18)
self.myView.addSubview(title)
self.myView.addConstraint(NSLayoutConstraint(item: title, attribute: .Top, relatedBy: .Equal, toItem: subviews.last, attribute: .Bottom, multiplier: 1.0, constant: 12.0))
self.myView.addConstraint(NSLayoutConstraint(item: title, attribute: .Leading, relatedBy: .Equal, toItem: self.headerStackView, attribute: .Leading, multiplier: 1.0, constant: 0))
subviews.append(title)
return subviews
}
//правое значение для информационого поля
func addTitleandValue(_title:String, _value:String, _subviews:[UIView], numberOfLines:Int) -> [UIView] {
var subviews = _subviews
let title = UILabel()
title.text = _title
title.font = title.font.fontWithSize(12)
if subviews.count > 0 {
setSimilarConstraintsToTitlesLabels(title, relatedView: (subviews.last!))
} else {
setSimilarConstraintsToTitlesLabels(title, relatedView: self.headerStackView)
}
let value = UILabel()
value.text = _value
value.numberOfLines = numberOfLines
value.font = value.font.fontWithSize(12)
subviews = setSimilarConstraintsToValuesLabels(value, relatedView: title, _subViews: subviews)
return subviews
}
func addBoolEptrfValues(_title:String, _subviews:[UIView])->[UIView] {
var subviews = _subviews
let title = UILabel()
title.text = _title
title.numberOfLines = 0
setSimilarConstraintsToTitlesLabels(title, relatedView: (subviews.last!))
let value = UILabel()
value.text = notificationViewModel?.convertBoolToString(true)
value.textColor = UIColor.blackColor()
subviews = setSimilarConstraintsToValuesLabels(value, relatedView: title, _subViews: subviews)
return subviews
}
func addDeleteButton(subviews:[UIView], isDeleted:Bool) -> UILabel {
let deleteLabel = UILabel()
if isDeleted == false {
deleteLabel.text = "Удалить"
} else {
deleteLabel.text = "Восстановить"
}
deleteLabel.translatesAutoresizingMaskIntoConstraints = false
deleteLabel.textColor = UIColor.blueColor()
deleteLabel.font = deleteLabel.font.fontWithSize(11)
self.myView.addSubview(deleteLabel)
self.myView.addConstraint(NSLayoutConstraint(item: deleteLabel, attribute: .Top, relatedBy: .Equal, toItem: subviews.last, attribute: .Bottom, multiplier: 1.0, constant: 8.0))
self.myView.addConstraint(NSLayoutConstraint(item: deleteLabel, attribute: .Leading, relatedBy: .Equal, toItem: self.headerStackView, attribute: .Leading, multiplier: 1.0, constant: 0))
return deleteLabel
}
//right values next to the title
func setSimilarConstraintsToValuesLabels(subView:UILabel, relatedView:UILabel, _subViews:[UIView]) -> [UIView] {
var subViews = _subViews
subView.translatesAutoresizingMaskIntoConstraints = false
self.myView.addSubview(subView)
if (relatedView.text?.characters.count < 35 && subView.text?.characters.count < 30) {
self.myView.addConstraint(NSLayoutConstraint(item: subView, attribute: .Right, relatedBy: .Equal, toItem: self.myView, attribute: .Right, multiplier: 1.0, constant: -15))
self.myView.addConstraint(NSLayoutConstraint(item: subView, attribute: .Left, relatedBy: .Equal, toItem: relatedView, attribute: .Right, multiplier: 1.0, constant: 5))
self.myView.addConstraint(NSLayoutConstraint(item: subView, attribute: .FirstBaseline, relatedBy: .Equal, toItem: relatedView, attribute: .LastBaseline, multiplier: 1.0, constant: 0))
} else {
self.myView.addConstraint(NSLayoutConstraint(item: subView, attribute: .Top, relatedBy: .Equal, toItem: relatedView, attribute: .Bottom, multiplier: 1.0, constant: 8.0))
self.myView.addConstraint(NSLayoutConstraint(item: subView, attribute: .Leading, relatedBy: .Equal, toItem: self.headerStackView, attribute: .Leading, multiplier: 1.0, constant: 8.0))
self.myView.addConstraint(NSLayoutConstraint(item: subView, attribute: .Width, relatedBy: .Equal, toItem: self.myView, attribute: .Width, multiplier: 1.0, constant: -15))
self.myView.addConstraint(NSLayoutConstraint(item: relatedView, attribute: .Width, relatedBy: .Equal, toItem: self.myView, attribute: .Width, multiplier: 1.0, constant: -15))
subViews.append(relatedView)
}
subViews.append(subView)
return subViews
}
func setSimilarConstraintsToTitlesLabels(subView:UILabel, relatedView:UIView) {
subView.translatesAutoresizingMaskIntoConstraints = false
subView.textColor = UIColor.grayColor()
subView.numberOfLines = 0
self.myView.addSubview(subView)
self.myView.addConstraint(NSLayoutConstraint(item: subView, attribute: .Top, relatedBy: .Equal, toItem: relatedView, attribute: .Bottom, multiplier: 1.0, constant: 8.0))
self.myView.addConstraint(NSLayoutConstraint(item: subView, attribute: .Leading, relatedBy: .Equal, toItem: self.headerStackView, attribute: .Leading, multiplier: 1.0, constant: 0))
}
}
The method "informationUpdate()" is called when information for showing is parsed.
Your tableView has no height Constraint, so the height is set to 0.
Then no cell are visible => cellForRow never called :)
I think you should try to create more clear code. Do not use "blind" array of subviews; do not append views directly to subviews property, you already added it to view hierarchy; if you use autolayout (translatesAutoresizingMaskIntoConstraints = false) - don't try mix it with frames in single view, go and set up all constraints; use different background colors for different views to debug view hierarchy at runtime; go to Xcode Debug\View Debugging\Capture View Hierarchy for deep explore view hierarchy at runtime
Also, if numberOfRowsInSection did called by UITableView and return value > 0 (check it!), then cellForRowAtIndexPath must be called immediately by this UITableView since dataSource property is set. If you have more than one UITableView objects - check if there is no unexpected replaces.
P.S. if you from Russia I can help on Russian lang
I created own subclass of UITableViewCell. There are a few subviews (2x imageview, 2x UILabel). I did everything programatically also constraints but on some cells autolayout isn't computed properly and I don't know why. And here is screenshot of my tableview with mentioned issue.
Thanks for any advice.
Here is source of my cell
//menu list cell
class TableMenuViewCell: UITableViewCell{
var stripe:UIView?
var separatorTop:UIView?
var separatorBottom:UIView?
var imageBox:UIView?
var img:UIImageView?
var dateBox:UIImageView?
var date:UILabel?
var label:UILabel?
var desc:UILabel?
var foreground:UIView?
var multiplier:CGFloat = 1
var didSetupConstraints:Bool = false
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.backgroundColor = Constants.grayColor
if UIDevice.currentDevice().userInterfaceIdiom == UIUserInterfaceIdiom.Pad {
multiplier = 1.3
}
//stripe
stripe = UIView()
stripe!.backgroundColor = Constants.light2GrayColor
stripe!.translatesAutoresizingMaskIntoConstraints = false
addSubview(stripe!)
//image box
imageBox = UIView()
imageBox!.backgroundColor = UIColor.clearColor()
imageBox!.translatesAutoresizingMaskIntoConstraints = false
addSubview(imageBox!)
//image view
img = UIImageView()
img!.backgroundColor = UIColor.clearColor()
img!.contentMode = UIViewContentMode.ScaleAspectFill
img!.clipsToBounds = true;
img!.translatesAutoresizingMaskIntoConstraints = false
imageBox!.addSubview(img!)
//constraints
imageBox!.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[img]-0-|", options: [], metrics: nil, views: ["img" : img! ]))
imageBox!.addConstraints(NSLayoutConstraint.constraintsWithVisualFormat("V:|-0-[img]-0-|", options: [], metrics: nil, views: ["img" : img! ]))
//label
label = UILabel()
label!.numberOfLines = 0
label!.backgroundColor = UIColor.clearColor()
label!.textColor = UIColor.whiteColor()
label!.textAlignment = NSTextAlignment.Left
label!.font = UIFont(name: Constants.FONT_MEDIUM, size: Constants.MENU_LABEL_FONT_SIZE * multiplier)
label!.translatesAutoresizingMaskIntoConstraints = false
addSubview(label!)
label!.sizeToFit()
//desc
desc = UILabel()
desc!.numberOfLines = 0
desc!.backgroundColor = UIColor.clearColor()
desc!.textColor = Constants.turquoiseColor
desc!.textAlignment = NSTextAlignment.Left
desc!.font = UIFont(name: Constants.FONT_THIN, size: Constants.MENU_DESC_FONT_SIZE * multiplier)
desc!.translatesAutoresizingMaskIntoConstraints = false
addSubview(desc!)
desc!.sizeToFit()
//separator top
separatorTop = UIView()
separatorTop!.backgroundColor = Constants.lightGrayColor
separatorTop!.translatesAutoresizingMaskIntoConstraints = false
addSubview(separatorTop!)
//separator bottom
separatorBottom = UIView()
separatorBottom!.backgroundColor = Constants.lightGrayColor
separatorBottom!.translatesAutoresizingMaskIntoConstraints = false
addSubview(separatorBottom!)
//foreground
foreground = UIView()
foreground!.backgroundColor = Constants.light2GrayHoverColor
foreground!.alpha = 0.5
foreground!.opaque = false
self.selectedBackgroundView = foreground!
}
//set layout
func setLayout(rowIndex : Int){
if didSetupConstraints{
return
}
else{
didSetupConstraints = true
}
let views:[String:AnyObject] = ["stripe" : stripe!, "imageBox" : imageBox!, "label" : label!, "desc" : desc!, "separatorTop" : separatorTop!, "separatorBottom" : separatorBottom!]
let metrics:[String:AnyObject] = ["hMargin" : Constants.HORIZONTAL_MARGIN, "vMargin" : Constants.VERTICAL_MARGIN, "stripeWidth" : Constants.STRIPE_WIDTH, "separatorHeight" : Constants.SEPARATOR_HEIGHT]
var constraintsArr:[NSLayoutConstraint] = []
//horizontal constraints
constraintsArr.appendContentsOf( NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[separatorTop]-0-|", options: [], metrics: metrics, views: views) )
constraintsArr.appendContentsOf( NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[separatorBottom]-0-|", options: [], metrics: metrics, views: views) )
constraintsArr.appendContentsOf( NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[stripe(==stripeWidth)]-(hMargin)-[imageBox]-(hMargin)-[label]-0-|", options: [], metrics: metrics, views: views) )
constraintsArr.appendContentsOf( NSLayoutConstraint.constraintsWithVisualFormat("H:|-0-[stripe(==stripeWidth)]-(hMargin)-[imageBox]-(hMargin)-[desc]-0-|", options: [], metrics: metrics, views: views) )
constraintsArr.append(NSLayoutConstraint(item: imageBox!, attribute: NSLayoutAttribute.Width, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: self.bounds.height - 4*Constants.VERTICAL_MARGIN))
//vertical constraints
constraintsArr.append(NSLayoutConstraint(item: stripe!, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: self.bounds.height))
constraintsArr.append(NSLayoutConstraint(item: stripe!, attribute: NSLayoutAttribute.Top, relatedBy: NSLayoutRelation.Equal, toItem: separatorTop!, attribute: NSLayoutAttribute.Top, multiplier: 1, constant: 0))
constraintsArr.append(NSLayoutConstraint(item: stripe!, attribute: NSLayoutAttribute.Bottom, relatedBy: NSLayoutRelation.Equal, toItem: separatorBottom!, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: 0))
constraintsArr.append(NSLayoutConstraint(item: imageBox!, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0))
constraintsArr.append(NSLayoutConstraint(item: imageBox!, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: self.bounds.height - 4*Constants.VERTICAL_MARGIN))
if desc!.text!.isEmpty {
constraintsArr.append(NSLayoutConstraint(item: label!, attribute: NSLayoutAttribute.CenterY, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.CenterY, multiplier: 1, constant: 0))
}else{
constraintsArr.append(NSLayoutConstraint(item: label!, attribute: NSLayoutAttribute.CenterYWithinMargins, relatedBy: NSLayoutRelation.Equal, toItem: self, attribute: NSLayoutAttribute.CenterYWithinMargins, multiplier: 1, constant: -label!.bounds.height*0.5))
constraintsArr.append(NSLayoutConstraint(item: desc!, attribute: NSLayoutAttribute.TopMargin, relatedBy: NSLayoutRelation.Equal, toItem: label!, attribute: NSLayoutAttribute.Bottom, multiplier: 1, constant: Constants.VERTICAL_MARGIN + Constants.VERTICAL_MARGIN * multiplier ))
}
constraintsArr.append(NSLayoutConstraint(item: separatorTop!, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: rowIndex != 0 ? 0 : Constants.SEPARATOR_HEIGHT))
constraintsArr.append(NSLayoutConstraint(item: separatorBottom!, attribute: NSLayoutAttribute.Height, relatedBy: NSLayoutRelation.Equal, toItem: nil, attribute: NSLayoutAttribute.NotAnAttribute, multiplier: 1, constant: Constants.SEPARATOR_HEIGHT))
self.addConstraints(constraintsArr)
}
override func prepareForReuse() {
super.prepareForReuse()
imageView!.image = nil
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
Source of Table view controller
import UIKit
class MenuViewController: UITableViewController {
var cellHeight:CGFloat = 50
override func viewDidLoad() {
super.viewDidLoad()
initTableView()
}
override func viewDidAppear(animated: Bool) {
super.viewWillAppear(animated)
tableView.reloadData()
}
func initTableView(){
tableView.separatorStyle = UITableViewCellSeparatorStyle.None
tableView.backgroundColor = Constants.grayColor
tableView.delegate = self
tableView.dataSource = self
tableView.estimatedRowHeight = cellHeight
tableView.rowHeight = UITableViewAutomaticDimension
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.registerClass(TableMenuViewCell.self, forCellReuseIdentifier: NSStringFromClass(TableMenuViewCell))
}
override func tableView(tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 0.001
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
if UIDevice.currentDevice().userInterfaceIdiom == UIUserInterfaceIdiom.Pad {
return cellHeight * 1.2
}
return cellHeight
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 16
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier( NSStringFromClass(TableMenuViewCell), forIndexPath: indexPath) as! TableMenuViewCell
//stripe
cell.stripe!.backgroundColor = Constants.turquoiseColor
//image
cell.img!.image = UIImage(named: "placeholder")
cell.img!.sizeToFit()
//image box
cell.imageBox!.sizeToFit()
//label
cell.label!.text = "Main Label"
cell.label!.sizeToFit()
//desc
cell.desc!.text = "Description Text"
cell.desc!.sizeToFit()
cell.setLayout(indexPath.row)
cell.setNeedsLayout()
cell.layoutIfNeeded()
return cell
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}