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
Related
I'm working with a UIScrollView where I want to show images, but the problem is that I need those images to be shown horizontally and now they are only shown vertically, how can I change the direction of my UIScrollView, from vertical to horizontal
This is my class where you implemented the UIScrollView:
//
// fastoClass.swift
// AutoLayout(
// Created by Barbatos on 5/14/18.
// Copyright © 2018 Seccion 15. All rights reserved.
//
import UIKit
class fastoClass: UIViewController {
#IBOutlet weak var scrollHorizont: UIScrollView!
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewDidAppear(_ animated: Bool) {
var constraints = [NSLayoutConstraint]()
var i = 0
var previousLeft: UIView? = nil
var previousRight: UIView? = nil
let scrollWidth: CGFloat = self.scrollHorizont.frame.size.width / 2.0
let imageColors = [UIColor.green, UIColor.lightGray, UIColor.blue, UIColor.red]
for color in imageColors{
let newImage = UIImageView()
newImage.backgroundColor = color
newImage.translatesAutoresizingMaskIntoConstraints = false
var toView : UIView? = nil
var toAttribute : NSLayoutAttribute?
let isLeft = (i % 2) == 0
if isLeft {
toView = self.scrollHorizont
toAttribute = NSLayoutAttribute.leading
} else {
toView = previousLeft
toAttribute = NSLayoutAttribute.trailing
}
var topView : UIView? = nil
var topAttribute : NSLayoutAttribute?
if i < 2 {
topView = self.scrollHorizont
topAttribute = NSLayoutAttribute.top
} else {
if isLeft {
topView = previousLeft
} else {
topView = previousRight
}
topAttribute = NSLayoutAttribute.bottom
}
let top = NSLayoutConstraint(item: newImage,
attribute: NSLayoutAttribute.top,
relatedBy: NSLayoutRelation.equal,
toItem: topView,
attribute: topAttribute!,
multiplier: 1.0,
constant: 0)
let leading = NSLayoutConstraint(item: newImage,
attribute: NSLayoutAttribute.leading,
relatedBy: NSLayoutRelation.equal,
toItem: toView,
attribute: toAttribute!,
multiplier: 1.0,
constant: 0)
let width = NSLayoutConstraint(item: newImage,
attribute: NSLayoutAttribute.width,
relatedBy: NSLayoutRelation.equal,
toItem: self.scrollHorizont,
attribute: NSLayoutAttribute.width,
multiplier: 0.5,
constant: 0)
let height = NSLayoutConstraint(item: newImage,
attribute: NSLayoutAttribute.height,
relatedBy: NSLayoutRelation.equal,
toItem: nil,
attribute: NSLayoutAttribute.notAnAttribute,
multiplier: 1.0,
constant: scrollWidth)
constraints.append(top)
constraints.append(leading)
constraints.append(width)
constraints.append(height)
self.scrollHorizont.addSubview(newImage)
i += 1
if isLeft {
previousLeft = newImage
} else {
previousRight = newImage
}
}
self.scrollHorizont.addConstraints(constraints)
self.scrollHorizont.layoutSubviews()
let contentHeight : CGFloat = scrollWidth * (CGFloat(i) / 2.0)
self.scrollHorizont.contentSize = CGSize(width: self.scrollHorizont.frame.size.width, height: contentHeight)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
}
You can try this
override func viewDidAppear(_ animated: Bool) {
var constraints = [NSLayoutConstraint]()
var i = 0
var previousLeft: UIView? = nil
let imageColors = [UIColor.green, UIColor.lightGray, UIColor.blue, UIColor.red]
for color in imageColors{
let newImage = UIImageView()
newImage.backgroundColor = color
newImage.translatesAutoresizingMaskIntoConstraints = false
if previousLeft == nil {
previousLeft = scrollHorizont
}
var con:NSLayoutAttribute? = nil
if previousLeft == self.scrollHorizont {
con = NSLayoutAttribute.leading
}
else {
con = NSLayoutAttribute.trailing
}
self.scrollHorizont.addSubview(newImage)
let top = NSLayoutConstraint(item: newImage,
attribute: NSLayoutAttribute.top,
relatedBy: NSLayoutRelation.equal,
toItem: previousLeft,
attribute: NSLayoutAttribute.top,
multiplier: 1.0,
constant: 0)
let leading = NSLayoutConstraint(item: newImage,
attribute: NSLayoutAttribute.leading,
relatedBy: NSLayoutRelation.equal,
toItem: previousLeft,
attribute: con!,
multiplier: 1.0,
constant: 0)
let width = NSLayoutConstraint(item: newImage,
attribute: NSLayoutAttribute.width,
relatedBy: NSLayoutRelation.equal,
toItem: self.scrollHorizont,
attribute: NSLayoutAttribute.width,
multiplier: 1,
constant: 0)
let height = NSLayoutConstraint(item: newImage,
attribute: NSLayoutAttribute.height,
relatedBy: NSLayoutRelation.equal,
toItem: self.scrollHorizont,
attribute: NSLayoutAttribute.height,
multiplier: 1.0,
constant: 0)
if i == imageColors.count - 1 {
let tra = NSLayoutConstraint(item: newImage,
attribute: NSLayoutAttribute.trailing,
relatedBy: NSLayoutRelation.equal,
toItem: self.scrollHorizont,
attribute: NSLayoutAttribute.trailing,
multiplier: 1.0,
constant: 0)
constraints.append(tra)
}
constraints.append(top)
constraints.append(leading)
constraints.append(width)
constraints.append(height)
previousLeft = newImage
i += 1
}
self.scrollHorizont.addConstraints(constraints)
}
I'm trying to add customView into headerView of my collectionView. Here's my code:
I registed the headerView class in viewDidLoad:
collectionView.register(SearchReuseView.self, forSupplementaryViewOfKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "reuseCell")
Then I setup the collectionView:
func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
var reuseView: UICollectionReusableView?
if indexPath.section == 0 || banners.count == 0 {
let view = UICollectionReusableView(frame: CGRect.zero)
reuseView = view
} else {
if kind == UICollectionElementKindSectionHeader {
let view = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "reuseCell", for: indexPath) as! SearchReuseView
view.backgroundColor = .black
view.delegate = self
view.frame = CGRect(x: 0, y: 0, width: collectionView.frame.width, height: 100)
view.item = banners[indexPath.section % banners.count]
return view
}
}
return reuseView!
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
if section == 0 {
return CGSize.zero
}
return CGSize(width: collectionView.frame.width, height: 100)
}
But when I run on Simulator, the collectionView shows the header but nothing inside.
Here is code of SearchReuseView :
class SearchReuseView: UICollectionReusableView {
weak var delegate: SearchReuseDelegate?
let adImageView: UIImageView = {
let img = UIImageView()
img.translatesAutoresizingMaskIntoConstraints = false
img.contentMode = .scaleAspectFit
return img
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.setupViews()
}
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)!
self.setupViews()
}
func setupViews() {
backgroundColor = .black
adImageView.isUserInteractionEnabled = true
adImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap)))
self.addConstraint(NSLayoutConstraint(item: self, attribute: .bottom, relatedBy: .equal, toItem: self.adImageView, attribute: .bottom, multiplier: 1, constant: 0))
self.addConstraint(NSLayoutConstraint(item: self, attribute: .right, relatedBy: .equal, toItem: self.adImageView, attribute: .right, multiplier: 1, constant: 0))
self.addConstraint(NSLayoutConstraint(item: self, attribute: .top, relatedBy: .equal, toItem: self.adImageView, attribute: .top, multiplier: 1, constant: 0))
self.addConstraint(NSLayoutConstraint(item: self, attribute: .left, relatedBy: .equal, toItem: self.adImageView, attribute: .left, multiplier: 1, constant: 0))
addSubview(adImageView)
}
var item: Banner! {
didSet {
guard let img = item.img else {return}
let url = URL(string: "\(img)")
self.adImageView.kf.setImage(with: url, placeholder: nil, options: [.transition(ImageTransition.fade(1))], progressBlock: { (receivedSize, totalSize) in
}) { (image, error, cacheType, imageURL) in
if error != nil {}
}
}
}
#objc func handleTap(){
guard let link = item.link else {
return
}
delegate?.didTapAds(link: link)
}
}
I wonder why your app is not crashing you should add subview first then add constraints to it
Replace your code with following code
func setupViews() {
backgroundColor = .black
addSubview(adImageView)
addSubview.translatesAutoresizingMaskIntoConstraints = false
adImageView.isUserInteractionEnabled = true
adImageView.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap)))
self.addConstraint(NSLayoutConstraint(item: self, attribute: .bottom, relatedBy: .equal, toItem: self.adImageView, attribute: .bottom, multiplier: 1, constant: 0))
self.addConstraint(NSLayoutConstraint(item: self, attribute: .right, relatedBy: .equal, toItem: self.adImageView, attribute: .right, multiplier: 1, constant: 0))
self.addConstraint(NSLayoutConstraint(item: self, attribute: .top, relatedBy: .equal, toItem: self.adImageView, attribute: .top, multiplier: 1, constant: 0))
self.addConstraint(NSLayoutConstraint(item: self, attribute: .left, relatedBy: .equal, toItem: self.adImageView, attribute: .left, multiplier: 1, constant: 0))
}
Hope it is helpful
if kind == UICollectionElementKindSectionHeader {
let view = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionElementKindSectionHeader, withReuseIdentifier: "reuseCell", for: indexPath) as! SearchReuseView
view.backgroundColor = .black
view.delegate = self
view.frame = CGRect(x: 0, y: 0, width: collectionView.frame.width, height: 100) //delete this line
view.item = banners[indexPath.section % banners.count]
return view
}
I delete the line set frame for header view and it's works
I'm trying to use inputAccessoryViewController in my app, but faced a problem with changing height of accessory view. I tried to change frame/bounds of the view, I also tried to handle height of the accessory view using constraints. But nothing worked well.
InputViewController code:
import UIKit
import RxSwift
import RxCocoa
class InputViewController: UIInputViewController {
private var separatorView: UIView?
private var answerTextView: ConstrainedTextView?
private var closeButton: UIButton?
private var tipLabel: UILabel?
// private var generalHeightConstraint: NSLayoutConstraint?
private var separatorHeightConstraint: NSLayoutConstraint?
private var answerTextViewBottomConstraint: NSLayoutConstraint?
private let junk = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
configureView()
}
private func configureView() {
// view.autoresizingMask = .flexibleHeight
view.backgroundColor = UIColor.white
view.frame = CGRect(x: 0, y: 0, width: view.superview?.bounds.width ?? 100, height: 70)
// view.translatesAutoresizingMaskIntoConstraints = false
// generalHeightConstraint = AutoLayoutSetAttribute(view, .height, 70)
// Separator
separatorView = UIView()
separatorView?.backgroundColor = UIColor.gray
separatorView?.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(separatorView!)
AutoLayoutEqualizeSuper(separatorView, .left, 0)
AutoLayoutEqualizeSuper(separatorView, .right, 0)
AutoLayoutEqualizeSuper(separatorView, .top, 0)
separatorHeightConstraint = AutoLayoutSetAttribute(separatorView, .height, 1)
// Close Button
closeButton = UIButton(type: .system)
closeButton?.setTitle("Hide", for: .normal)
closeButton?.titleLabel?.font = UIFont.systemFont(ofSize: 17)
closeButton?.translatesAutoresizingMaskIntoConstraints = false
closeButton?.addTarget(self, action: #selector(dismissKeyboard), for: .touchUpInside)
view.addSubview(closeButton!)
AutoLayoutSetAttribute(closeButton, .width, 70)
AutoLayoutEqualizeSuper(closeButton, .right, -5)
view.addConstraint(NSLayoutConstraint(item: closeButton!, attribute: .top, relatedBy: .equal, toItem: separatorView, attribute: .bottom, multiplier: 1, constant: 0))
// Tip Label
tipLabel = UILabel()
tipLabel?.textColor = UIColor.darkGray
tipLabel?.text = "Input answer:"
tipLabel?.font = UIFont.systemFont(ofSize: 17)
tipLabel?.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(tipLabel!)
AutoLayoutEqualizeSuper(tipLabel, .left, 5)
AutoLayoutEqualize(tipLabel, separatorView, .top, 0)
view.addConstraint(NSLayoutConstraint(item: tipLabel!, attribute: .right, relatedBy: .equal, toItem: closeButton, attribute: .left, multiplier: 1, constant: 0))
// Text View
answerTextView = ConstrainedTextView()
answerTextView?.backgroundColor = UIColor.white
answerTextView?.delegate = self
answerTextView?.scrollsToTop = false
answerTextView?.showsVerticalScrollIndicator = false
answerTextView?.font = REG_FONT(15)
answerTextView?.maxLines = 5
answerTextView?.translatesAutoresizingMaskIntoConstraints = false
answerTextView?.layer.masksToBounds = true
answerTextView?.layer.cornerRadius = 7
answerTextView?.layer.borderColor = UIColor.lightGray.withAlphaComponent(0.7).cgColor
answerTextView?.layer.borderWidth = 1
view.addSubview(answerTextView!)
AutoLayoutEqualizeSuper(answerTextView, .left, 5)
AutoLayoutEqualizeSuper(answerTextView, .right, -5)
answerTextViewBottomConstraint = AutoLayoutEqualizeSuper(answerTextView, .bottom, -5)
view.addConstraint(NSLayoutConstraint(item: answerTextView!, attribute: .top, relatedBy: .equal, toItem: tipLabel, attribute: .bottom, multiplier: 1, constant: 0))
view.addConstraint(NSLayoutConstraint(item: answerTextView!, attribute: .top, relatedBy: .equal, toItem: closeButton, attribute: .bottom, multiplier: 1, constant: 0))
answerTextView?
.rx
.observe(CGRect.self, "bounds")
.distinctUntilChanged {
$0?.size.height == $1?.size.height
}
.subscribe { [unowned self] newBounds in
if var newHeight = newBounds.element??.size.height,
let separatorHeight = self.separatorHeightConstraint?.constant,
let buttonHeight = self.closeButton?.intrinsicContentSize.height,
let bottomSpace = self.answerTextViewBottomConstraint?.constant {
newHeight = newHeight == 0 ? 30 : newHeight
let generalHeight = newHeight + separatorHeight + buttonHeight + abs(bottomSpace)
self.view.frame = CGRect(x: 0, y: 0, width: self.view.superview?.bounds.width ?? 100, height: generalHeight)
// self.generalHeightConstraint?.constant = generalHeight
// UIView.animate(withDuration: 0.2) {
// self.view.setNeedsLayout()
// self.view.layoutIfNeeded()
// }
}
}
.addDisposableTo(junk)
}
}
// MARK: - UITextViewDelegate Protocol Conformance
extension InputViewController: UITextViewDelegate {
func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
textView.inputAccessoryView = view
return true
}
func textViewShouldEndEditing(_ textView: UITextView) -> Bool {
textView.inputAccessoryView = nil
return true
}
}
View Controller where input accessory VC is used:
import UIKit
class TestViewController: UIViewController {
override var inputAccessoryViewController: UIInputViewController? {
return SDAnswerInputViewController()
}
override var canBecomeFirstResponder: Bool {
return true
}
override func viewDidLoad() {
super.viewDidLoad()
}
}
Can you explain how shall I correctly modify height of input accessory view overriding inputAccessoryViewController?
The problem was in these two lines:
view.addConstraint(NSLayoutConstraint(item: answerTextView!, attribute: .top, relatedBy: .equal, toItem: tipLabel, attribute: .bottom, multiplier: 1, constant: 0))
view.addConstraint(NSLayoutConstraint(item: answerTextView!, attribute: .top, relatedBy: .equal, toItem: closeButton, attribute: .bottom, multiplier: 1, constant: 0))
The answerTextView couldn't modify it's height because of constraints at the bottom and the top.
I have this situation :
This pink view in the scrollview and I want is:
when I tap on 'add' button, I want that to create another pink view object (this is no problem) and set it below the first pink view object setting auto layout for it(vertical space between it and previous pink view object, trailing space .....) but I don't be able to do this part.
Can you help me?
I am not sure where you have problem adding view to scrollview. Here is example for adding button into scrollview at runtime. You can use same code for adding your pink view.
import UIKit
class ViewController: UIViewController, UIPickerViewDataSource, UIPickerViewDelegate
{
var pickerviewObj : UIPickerView!=UIPickerView()
var scrlview: UIScrollView = UIScrollView();
var cotentView : UIView = UIView();
var arrdata :NSMutableArray=["1","2","3","4","5","6","7","8","9","10"]
var dctButtons : NSMutableDictionary!=NSMutableDictionary()
var ContentViewconstraintheight : NSLayoutConstraint = NSLayoutConstraint()
var xPos,ypos: NSInteger!
var SelctedTag : NSInteger!
var width: Double!
// var colors = ["Red","Yellow","Green","Blue"]
func getCalculatedHeightForScren(height : CGFloat) -> CGFloat {
return (height * self.view.frame.size.height/568 );
}
func disableAutoResizingMasks() {
self.pickerviewObj.translatesAutoresizingMaskIntoConstraints = false
self.scrlview.translatesAutoresizingMaskIntoConstraints = false
self.cotentView.translatesAutoresizingMaskIntoConstraints = false;
}
override func viewDidLoad()
{
super.viewDidLoad()
let pickerHeight = getCalculatedHeightForScren(height: 50)
self.pickerviewObj = UIPickerView(frame: CGRect(x: 0, y: self.view.frame.size.height-pickerHeight, width: self.view.frame.size.width, height: pickerHeight) )
self.view.addSubview(self.pickerviewObj);
pickerviewObj.backgroundColor = UIColor.white;
pickerviewObj.showsSelectionIndicator = true;
let toolBar = UIToolbar()
toolBar.barStyle = UIBarStyle.default;
toolBar.isTranslucent = true
toolBar.tintColor = UIColor(red: 76/255, green: 217/255, blue: 100/255, alpha: 1)
toolBar.sizeToFit()
self.view.addSubview(self.scrlview)
self.scrlview.addSubview(self.cotentView);
let spaceButton = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.flexibleSpace, target: nil, action: nil)
let doneButton = UIBarButtonItem(title: "Done", style: UIBarButtonItemStyle.plain, target: self, action: #selector(ViewController.DonePicker))
toolBar.setItems([ spaceButton, doneButton], animated: false)
toolBar.isUserInteractionEnabled = true
toolBar.frame = CGRect(x: 0, y: self.view.frame.size.height-pickerHeight-44, width: self.view.frame.size.width, height: 44);
self.view.addSubview(toolBar);
pickerviewObj.dataSource = self;
pickerviewObj.delegate = self;
//add constraints to PickerView
let constraintCenterX = NSLayoutConstraint(item: pickerviewObj, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: self.view , attribute: NSLayoutAttribute.centerX, multiplier: 1, constant:0);
let constraintBottom = NSLayoutConstraint(item: pickerviewObj, attribute: NSLayoutAttribute.bottom , relatedBy: NSLayoutRelation.equal, toItem: self.view , attribute: NSLayoutAttribute.bottom, multiplier: 1, constant:0);
let constraintWidth = NSLayoutConstraint(item: pickerviewObj, attribute: NSLayoutAttribute.width , relatedBy: NSLayoutRelation.equal, toItem: self.view , attribute: NSLayoutAttribute.width, multiplier: 1, constant:0);
let constraintHeight = NSLayoutConstraint(item: pickerviewObj, attribute: NSLayoutAttribute.height , relatedBy: NSLayoutRelation.equal, toItem: self.view , attribute: NSLayoutAttribute.height, multiplier: (200/568), constant:0);
//add constraints to ScrollView
let scrollconstraintCenterX = NSLayoutConstraint(item: self.scrlview, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: self.view , attribute: NSLayoutAttribute.centerX, multiplier: 1, constant:0);
let scrollconstraintBottom = NSLayoutConstraint(item: self.scrlview, attribute: NSLayoutAttribute.bottom , relatedBy: NSLayoutRelation.equal, toItem: toolBar , attribute: NSLayoutAttribute.top, multiplier: 1, constant:0);
let scrollconstraintWidth = NSLayoutConstraint(item: self.scrlview, attribute: NSLayoutAttribute.width , relatedBy: NSLayoutRelation.equal, toItem: self.view , attribute: NSLayoutAttribute.width, multiplier: 1, constant:0);
let scrollconstraintTop = NSLayoutConstraint(item: self.scrlview, attribute: NSLayoutAttribute.top , relatedBy: NSLayoutRelation.equal, toItem: self.view , attribute: NSLayoutAttribute.top, multiplier:1, constant:0);
//add constraints to ScrollView's contentView
let ContentViewconstrainttop = NSLayoutConstraint(item: self.cotentView, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.equal, toItem: self.scrlview , attribute: NSLayoutAttribute.topMargin, multiplier: 1, constant:0);
let ContentViewconstraintBottom = NSLayoutConstraint(item: self.cotentView, attribute: NSLayoutAttribute.bottom , relatedBy: NSLayoutRelation.equal, toItem: self.scrlview , attribute: NSLayoutAttribute.bottomMargin, multiplier: 1, constant:0);
let ContentViewconstraintleft = NSLayoutConstraint(item: self.cotentView, attribute: NSLayoutAttribute.trailing , relatedBy: NSLayoutRelation.equal, toItem: self.scrlview , attribute: NSLayoutAttribute.trailing, multiplier: 1, constant:0);
let ContentViewconstraintright = NSLayoutConstraint(item: self.cotentView, attribute: NSLayoutAttribute.leading , relatedBy: NSLayoutRelation.equal, toItem: self.scrlview , attribute: NSLayoutAttribute.leading, multiplier: (200/568), constant:0);
let ContentViewconstraintWidth = NSLayoutConstraint(item: self.cotentView, attribute: NSLayoutAttribute.width, relatedBy: NSLayoutRelation.equal, toItem: self.scrlview , attribute: NSLayoutAttribute.width, multiplier: 1, constant:0);
self.ContentViewconstraintheight = NSLayoutConstraint(item: self.cotentView, attribute: NSLayoutAttribute.height, relatedBy: NSLayoutRelation.equal, toItem: nil , attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant:100);
//add constraints to toolBar
let toolconstraintCenterX = NSLayoutConstraint(item: toolBar, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: self.view , attribute: NSLayoutAttribute.centerX, multiplier: 1, constant:0);
let toolconstraintBottom = NSLayoutConstraint(item: toolBar, attribute: NSLayoutAttribute.bottom , relatedBy: NSLayoutRelation.equal, toItem: self.pickerviewObj , attribute: NSLayoutAttribute.top, multiplier: 1, constant:0);
let toolconstraintWidth = NSLayoutConstraint(item: toolBar, attribute: NSLayoutAttribute.width , relatedBy: NSLayoutRelation.equal, toItem: self.view , attribute: NSLayoutAttribute.width, multiplier: 1, constant:0);
//activare all constraints
NSLayoutConstraint.activate([constraintWidth,constraintHeight,constraintCenterX,constraintBottom,toolconstraintWidth,toolconstraintBottom,toolconstraintCenterX,scrollconstraintTop,scrollconstraintWidth,scrollconstraintCenterX,scrollconstraintBottom,ContentViewconstrainttop,ContentViewconstraintBottom,ContentViewconstraintleft,ContentViewconstraintright,ContentViewconstraintWidth,self.ContentViewconstraintheight]);
self.view.layoutSubviews()
self.disableAutoResizingMasks();
toolBar.translatesAutoresizingMaskIntoConstraints = false
}
override func didReceiveMemoryWarning()
{
super.didReceiveMemoryWarning()
}
func getSorted(s1 : Any , s2 : Any) -> Bool{
let str1 : String = s1 as! String
let str2 : String = s2 as! String
return Int(str1)! < Int(str2)!;
}
//custom Logics to Update UI
func addConstarintsToButton(btn : UIButton , yPos : CGFloat)
{
NSLayoutConstraint.deactivate(btn.constraints);
btn.removeConstraints(btn.constraints);
let width = ((self.view.frame.size.width-20)/2) - 30;
let height = self.getCalculatedHeightForScren(height: 40);
let constraintCenterX = NSLayoutConstraint(item: btn, attribute: NSLayoutAttribute.centerX, relatedBy: NSLayoutRelation.equal, toItem: self.scrlview , attribute: NSLayoutAttribute.centerX, multiplier: 1, constant:0);
let constrainttop = NSLayoutConstraint(item: btn, attribute: NSLayoutAttribute.top , relatedBy: NSLayoutRelation.equal, toItem: self.cotentView , attribute: NSLayoutAttribute.top, multiplier: 1, constant:yPos);
let constraintWidth = NSLayoutConstraint(item: btn, attribute: NSLayoutAttribute.width , relatedBy: NSLayoutRelation.equal, toItem: nil , attribute: NSLayoutAttribute.notAnAttribute, multiplier: 1, constant: width);
let constraintHeight = NSLayoutConstraint(item: btn, attribute: NSLayoutAttribute.height , relatedBy: NSLayoutRelation.equal, toItem: nil , attribute: NSLayoutAttribute.notAnAttribute, multiplier: height, constant:height);
NSLayoutConstraint.activate([constraintCenterX, constrainttop,constraintWidth,constraintHeight])
btn.translatesAutoresizingMaskIntoConstraints = false
}
func updateUIElements(tag : Int)
{
let arrKeys : NSMutableArray = NSMutableArray(array: dctButtons.allKeys, copyItems: true)
let SortedKeys = arrKeys.sorted(by: getSorted)
var xPos :CGFloat = 10.0;
var yPos :CGFloat = 50.0;
let width = ((self.view.frame.size.width-20)/2) - 30;
let height = self.getCalculatedHeightForScren(height: 40);
xPos = (self.view.frame.size.width - width)/2;
UIView.animate(withDuration: 0.5, animations: {
if(tag > 0)
{
let vw = self.cotentView.viewWithTag(tag)
vw?.removeFromSuperview()
let vw1 = self.cotentView.viewWithTag(tag + 100)
vw1?.removeFromSuperview()
}
for key in SortedKeys {
let btn1 = self.dctButtons.object(forKey: key) as! UIButton
btn1.frame = CGRect( x:xPos, y:yPos,width:width,height:height);
if let testBtn = self.cotentView.viewWithTag(btn1.tag+100) as? UIButton
{
let btnCross = testBtn ;
btnCross.frame = CGRect(x: xPos + btn1.frame.size.width + 5, y: yPos, width: 20, height: height);
}
self.ContentViewconstraintheight.constant = btn1.frame.size.height + 100;
if let vw = self.cotentView.viewWithTag(btn1.tag) as? UIButton
{
vw.removeFromSuperview();
self.cotentView.addSubview(btn1);
self.addConstarintsToButton(btn: btn1, yPos: yPos);
}
else{
self.cotentView.addSubview(btn1);
self.addConstarintsToButton(btn: btn1, yPos: yPos);
}
yPos += height + 10
}
self.view.layoutSubviews()
self.ContentViewconstraintheight.constant = yPos ;
})
}
// Control event Methods....
func btnClick(sender: UIButton!)
{
SelctedTag=sender.tag;
print(SelctedTag)
if sender.isSelected
{
return;
}
sender.isSelected = true;
let ButtonClose = UIButton(frame: CGRect(x: sender.frame.origin.x + sender.frame.size.width + 5, y: sender.frame.origin.y, width: 20, height: sender.frame.size.height) )
ButtonClose.tag = sender.tag + 100;
ButtonClose.setTitle("X", for: UIControlState.normal)
ButtonClose.backgroundColor = UIColor.gray
ButtonClose.setTitleColor(UIColor.red, for: UIControlState.normal);
ButtonClose.isUserInteractionEnabled = true;
ButtonClose.addTarget(self, action: #selector(ViewController.btnClose(sender:)), for: UIControlEvents.touchUpInside);
self.cotentView.addSubview(ButtonClose);
let strVal = String(sender.tag)
self.arrdata.remove(strVal)
self.pickerviewObj.reloadComponent(0);
}
func DonePicker()
{
let selectedIndex = self.pickerviewObj.selectedRow(inComponent: 0);
if (arrdata.count == 0 || selectedIndex < 0 || selectedIndex > arrdata.count )
{
return;
}
let x : String = arrdata[selectedIndex] as! String
let tag = Int(x)!
if let vw = self.cotentView.viewWithTag(tag) as? UIButton
{
return;
}
let btn = UIButton(type: UIButtonType.system);
btn.isSelected = false;
btn.tag = tag
btn.backgroundColor = UIColor.black;
btn.setTitleColor(UIColor.white, for: UIControlState.normal)
btn.addTarget(self, action:#selector(ViewController.btnClick(sender:)), for: UIControlEvents.touchUpInside)
btn.setTitle("Field " + String(x), for: UIControlState.normal)
btn.setTitleColor(UIColor.white, for: UIControlState.normal)
btn.isUserInteractionEnabled = true;
btn.center = self.pickerviewObj.center;
dctButtons.setObject(btn, forKey: String(x) as NSCopying)
self.pickerviewObj.reloadComponent(0);
self.updateUIElements(tag: 0);
}
func btnClose(sender: UIButton!)
{
print((SelctedTag))
let key = String(sender.tag - 100);
dctButtons.removeObject(forKey: key);
arrdata.add( key)
let tmpArray = arrdata.sorted(by: getSorted)
arrdata.removeAllObjects();
arrdata.addObjects(from: tmpArray)
self.pickerviewObj.reloadComponent(0);
self.updateUIElements(tag: sender.tag - 100);
}
// Picker view Methods....
func numberOfComponents(in pickerView: UIPickerView) -> Int
{
return 1
}
func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int
{
return arrdata.count
}
func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String?
{
let x : String = arrdata[row] as! String
return "Field " + x
}
func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int)
{
// let x : Int = arrdata[row] as! Int
// arrButton.add(x)
// print(arrButton)
// self .numberOfButton(number: arrdata[row] as! Int)
// arrdata.removeObject(at: row)
// pickerView.reloadAllComponents()
}
}
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.
}
}