Add Subview To Custom UI Button Class - ios

Objective:
When the user clicks the custom button, a blank UIView should appear covering the button.
I've added my code to a new Swift project which looks like this
import UIKit
class DownloadUIButton: UIButton {
var isDownloading: Bool? = false
func addView() {
let view = UIView(frame: self.frame)
view.backgroundColor = UIColor.white
self.addSubview(view)
}
}
class ViewController : UIViewController, UITableViewDelegate, UITableViewDataSource {
fileprivate let tableView: UITableView = UITableView(frame: CGRect.init(x: 0, y: 0, width: 300, height: 300), style: UITableViewStyle.plain)
override func viewDidLoad() {
self.setupTableView()
}
fileprivate func setupTableView() {
self.tableView.dataSource = self
self.tableView.delegate = self
tableView.backgroundColor = UIColor.white
tableView.isOpaque = true
view.addSubview(self.tableView)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: "CellIdentifier")
let buttonSize = 30
let btn = DownloadUIButton(frame: CGRect(x: 10, y: 10, width: buttonSize, height: buttonSize))
btn.backgroundColor = UIColor.red
btn.addTarget(self, action:#selector(handleDownload(_:)), for: .touchUpInside)
cell.addSubview(btn)
return cell
}
#objc func handleDownload(_ btn: DownloadUIButton) {
btn.addView()
}
}
However, the project gives this error:
2017-10-28 12:55:41.558522+0100 TestProject[21392:1779236] *** Terminating app due to uncaught exception 'CALayerInvalid', reason: 'layer is a part of cycle in its layer tree'

To make a view appear in front of your button, I'd just make them sibling views with the same frame. Have the custom view's isHidden set to true at launch time, and when the button's clicked, set the button's isHidden to true and the custom view's isHidden to false. Alternately, if you actually want the button to be visible behind transparent parts of the custom view, you can use sendSubview(toBack:) to make the button appear behind the custom view.

Related

Having some UITableViews and some UICollectionViews in a single screen

I am currently working on a particular problem where I have to add a UITableView and a couple of UICollectionViews along with a couple of labels in a single screen.
Here is the mockup:-
Right now, This is how my view looks (I am just working on the UI for now):-
The UICollectionViews below 'Live now' and 'Related Stories' are horizontally scrollable and in the middle of those UICollectionViews is a UITableView
Rather than having to compress these subviews inside the UIViewController class that I have built, I wish to remake it in such a way that the whole view is scrollable while keeping the same scrolling experience of the subviews currently set in the view.
I considered using another UITableview that encompasses all the views(the collection views and the table view), but then, the scrolling of that particular table view would cause a bad scrolling experience with the table view that I have to add.
The above could be said for using a UIScrollView (UICollectionViews that would be added would have no problem since they are being scrolled horizontally).
Would it be best to use a UICollectionView?
Any Suggestion that could help is welcome. Do let me know if there is anything from my side
Here is my source code:
import UIKit
import SnapKit
import EasyPeasy
class ArticleViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate, UITableViewDelegate, UITableViewDataSource {
var liveLabel = UILabel()
var engageLabel = UILabel()
var storyLabel = UILabel()
var livelayout = UICollectionViewFlowLayout.init()
var storylayout = UICollectionViewFlowLayout.init()
var liveCollectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: UICollectionViewFlowLayout.init())
var storyCollectionView = UICollectionView(frame: CGRect.zero, collectionViewLayout: UICollectionViewFlowLayout.init())
var liveRows = [
"https://images.sportsflashes.com/australia-win-first-t20i-after-nail-biting-finish-at-vizag1551028137.jpg",
"https://images.sportsflashes.com/australia-win-first-t20i-after-nail-biting-finish-at-vizag1551028137.jpg",
"https://images.sportsflashes.com/australia-win-first-t20i-after-nail-biting-finish-at-vizag1551028137.jpg",
"https://images.sportsflashes.com/australia-win-first-t20i-after-nail-biting-finish-at-vizag1551028137.jpg",
"https://images.sportsflashes.com/australia-win-first-t20i-after-nail-biting-finish-at-vizag1551028137.jpg",
"https://images.sportsflashes.com/australia-win-first-t20i-after-nail-biting-finish-at-vizag1551028137.jpg",
"https://images.sportsflashes.com/australia-win-first-t20i-after-nail-biting-finish-at-vizag1551028137.jpg"
]
var articleRows = [
"https://c.ndtvimg.com/2019-03/6dkbrsrg_varun-dhawan_625x300_14_March_19.jpg",
"https://c.ndtvimg.com/2019-03/6dkbrsrg_varun-dhawan_625x300_14_March_19.jpg",
"https://c.ndtvimg.com/2019-03/6dkbrsrg_varun-dhawan_625x300_14_March_19.jpg",
"https://c.ndtvimg.com/2019-03/6dkbrsrg_varun-dhawan_625x300_14_March_19.jpg",
"https://c.ndtvimg.com/2019-03/6dkbrsrg_varun-dhawan_625x300_14_March_19.jpg",
"https://c.ndtvimg.com/2019-03/6dkbrsrg_varun-dhawan_625x300_14_March_19.jpg",
"https://c.ndtvimg.com/2019-03/6dkbrsrg_varun-dhawan_625x300_14_March_19.jpg",
"https://c.ndtvimg.com/2019-03/6dkbrsrg_varun-dhawan_625x300_14_March_19.jpg",
"https://c.ndtvimg.com/2019-03/6dkbrsrg_varun-dhawan_625x300_14_March_19.jpg"
]
var storyRows = [
"https://www.anime-planet.com/images/characters/takuma-mamizuka-83947.jpg",
"https://www.anime-planet.com/images/characters/takuma-mamizuka-83947.jpg",
"https://www.anime-planet.com/images/characters/takuma-mamizuka-83947.jpg",
"https://www.anime-planet.com/images/characters/takuma-mamizuka-83947.jpg",
"https://www.anime-planet.com/images/characters/takuma-mamizuka-83947.jpg",
"https://www.anime-planet.com/images/characters/takuma-mamizuka-83947.jpg",
"https://www.anime-planet.com/images/characters/takuma-mamizuka-83947.jpg",
"https://www.anime-planet.com/images/characters/takuma-mamizuka-83947.jpg",
"https://www.anime-planet.com/images/characters/takuma-mamizuka-83947.jpg"
]
let table = UITableView()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.view.backgroundColor = UIColor.white
if self.navigationController == nil {
return
}
self.navigationController?.isNavigationBarHidden = false
self.navigationItem.leftBarButtonItem = UIBarButtonItem(image:(UIImage(named: "back_arrow")?.withRenderingMode(.alwaysOriginal)), style:.plain, target:self, action:#selector(backPress))
var dateBarButtonItem = UIBarButtonItem(title: "Mar 2019", style: .plain, target: self, action: nil)
dateBarButtonItem.tintColor = UIColor.black
self.navigationItem.rightBarButtonItem = dateBarButtonItem
// Create a navView to add to the navigation bar
let navView = UIView()
// Create the label
let nameLabel = UILabel()
nameLabel.text = "Pavan Vasan"
nameLabel.sizeToFit()
nameLabel.center = navView.center
nameLabel.textAlignment = NSTextAlignment.center
// Create the image view
let image = UIImageView()
image.image = UIImage(named: "twitter")
// To maintain the image's aspect ratio:
let imageAspect = image.image!.size.width/image.image!.size.height
// Setting the image frame so that it's immediately before the text:
image.frame = CGRect(x: nameLabel.frame.origin.x-nameLabel.frame.size.height*imageAspect, y: nameLabel.frame.origin.y, width: nameLabel.frame.size.height*imageAspect, height: nameLabel.frame.size.height)
image.contentMode = UIView.ContentMode.scaleAspectFit
// Add both the label and image view to the navView
navView.addSubview(nameLabel)
navView.addSubview(image)
// Set the navigation bar's navigation item's titleView to the navView
self.navigationItem.titleView = navView
// Set the navView's frame to fit within the titleView
navView.sizeToFit()
}
override func viewDidLoad() {
super.viewDidLoad()
setupLiveCollectionView()
setupTable()
setupStoryCollectionView()
}
func setupLiveCollectionView() {
self.view.addSubview(self.liveLabel)
self.liveLabel.text = "Live now"
self.liveLabel.font = UIFont.boldSystemFont(ofSize: 17.5)
self.liveLabel.textColor = UIColor.black
self.liveLabel.textAlignment = .center
self.liveLabel.easy.layout(
Left(10).to(self.view),
Top(75).to(self.view)
)
livelayout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
livelayout.itemSize = CGSize(width: 75, height: 75)
livelayout.scrollDirection = .horizontal
liveCollectionView = UICollectionView(frame: CGRect(x: 0, y: 100, width: self.view.frame.width, height: 95), collectionViewLayout: livelayout)
liveCollectionView.dataSource = self
liveCollectionView.delegate = self
liveCollectionView.register(LiveViewCell.self, forCellWithReuseIdentifier: "MyCell")
liveCollectionView.backgroundColor = UIColor.white
liveCollectionView.showsHorizontalScrollIndicator = false
self.view.addSubview(liveCollectionView)
}
func setupStoryCollectionView() {
self.view.addSubview(self.storyLabel)
self.storyLabel.text = "Related Stories"
self.storyLabel.font = UIFont.boldSystemFont(ofSize: 17.5)
self.storyLabel.textColor = UIColor.black
self.storyLabel.textAlignment = .center
self.storyLabel.easy.layout(
Left(10).to(self.view),
Top(15).to(self.table)
)
storylayout.sectionInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
storylayout.itemSize = CGSize(width: 120, height: 120)
storylayout.scrollDirection = .horizontal
storyCollectionView = UICollectionView(frame: CGRect(x: 0, y: 250 + self.view.bounds.height*0.40, width: self.view.frame.width, height: 130), collectionViewLayout: storylayout)
storyCollectionView.dataSource = self
storyCollectionView.delegate = self
storyCollectionView.register(StoryViewCell.self, forCellWithReuseIdentifier: "StoryCell")
storyCollectionView.backgroundColor = UIColor.white
storyCollectionView.showsHorizontalScrollIndicator = false
self.view.addSubview(storyCollectionView)
}
func setupTable() {
table.delegate = self
table.dataSource = self
table.register(ArticleTableViewCell.self, forCellReuseIdentifier: "ArticleCell")
table.separatorStyle = .none
self.view.addSubview(table)
self.table.easy.layout(
Top(15).to(self.liveCollectionView),
Left(0).to(self.view),
Width(self.view.bounds.width),
Height(self.view.bounds.height*0.4)
)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if collectionView == self.liveCollectionView {
return self.liveRows.count
} else if collectionView == self.storyCollectionView {
return self.storyRows.count
}
return 0
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if collectionView == self.liveCollectionView {
let myCell = collectionView.dequeueReusableCell(withReuseIdentifier: "MyCell", for: indexPath as IndexPath) as! LiveViewCell
myCell.configure(self.liveRows[indexPath.row])
return myCell
} else if collectionView == self.storyCollectionView {
let myCell = collectionView.dequeueReusableCell(withReuseIdentifier: "StoryCell", for: indexPath as IndexPath) as! StoryViewCell
myCell.configure(self.storyRows[indexPath.row])
myCell.layer.borderColor = UIColor.black.cgColor
myCell.layer.cornerRadius = 15
myCell.layer.borderWidth = 0.5
myCell.layer.masksToBounds = true
return myCell
}
return UICollectionViewCell()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.articleRows.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ArticleCell", for: indexPath) as! ArticleTableViewCell
cell.configure(self.articleRows[indexPath.row])
return cell
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 325
}
#objc func backPress(sender:UIButton!) {
self.navigationController?.popViewController(animated: true)
}
}
It would be preferable in complex screens to use only one main list view type(UITableView or UICollectionView).
In it u can add UIStackView or more UITableViews or UICollectionView.
In your case i would have used a UICollectionView and change the size of the cell according to your needs
You can use a single tableview for full screen and create custom cell by adding UICollectionView inside that.
Having nested scroll views could be against the HIG guidelines, which advocates not to place a scroll view inside of another scroll view.
In fact, similar to our use case, Apple has given the example of their Stocks app, where stock quotes scroll vertically above company-specific information that scrolls horizontally.
For more details, please refer to the HIG documentation at https://developer.apple.com/design/human-interface-guidelines/ios/views/scroll-views/
You can do it without any major changes in your code just below updates.
First, need to set constraint outlet of Tableview Height. e.g consTblHeight
Add Tableview size change observer.
func setupTable() {
table.addObserver(self, forKeyPath: "contentSize", options: NSKeyValueObservingOptions.new, context: nil)
}
Observer Method
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
self.consTblHeight.constant = self.table.contentSize.height
self.view.layoutIfNeeded()
}

How to fix dynamic height for individual cells as UIautodimensions is not working

I am creating a wall page like twitter or Facebook in which user can post on the wall it can include image and just text. So based on the content the cell's heights must change, if the post is of one line the row height must be appropriate.
I tried using UITableViewAutomaticDimensions, but its not working with my code please do help me.
import UIKit
class wallPageViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
var tableOfApps : UITableView?
var appNames: [String]? = []
var apps: [wallPageModel]?
var dynamic_height : CGFloat = 150.0
var addPost : UITextField?
var readMore : UITextView?
func loadTableOfApps(){
//appNames = ["jkbajdba", "abfajfb", "akjbfkjag", "ahbfkajf" ]
let provider = wallPageProvider()
apps = provider.getApps()
let tableHeight = view.frame.size.height
tableOfApps = UITableView(frame: CGRect(x: 10, y: 60, width: 300, height: tableHeight))
tableOfApps!.delegate = self
tableOfApps!.dataSource = self
tableOfApps?.separatorStyle = UITableViewCellSeparatorStyle.none
//self.tableOfApps?.rowHeight = UITableViewAutomaticDimension
//self.tableOfApps?.estimatedRowHeight = UITableViewAutomaticDimension
print("load table of apps")
view.addSubview(tableOfApps!)
}
override func viewDidLoad() {
super.viewDidLoad()
loadTableOfApps()
loadAddPost()
tableOfApps?.estimatedRowHeight = 150.0
tableOfApps?.rowHeight = UITableViewAutomaticDimension
view.backgroundColor = UIColor(red: 232/255, green: 234/255, blue: 246/255, alpha: 1.0)
// Do any additional setup after loading the view.
}
func loadAddPost(){
addPost = UITextField(frame: CGRect(x: 10, y: 20, width: 300, height: 30))
addPost?.placeholder = "Stay safe, post a tip!"
addPost?.isUserInteractionEnabled = true
addPost?.borderStyle = UITextBorderStyle.roundedRect
addPost?.autocapitalizationType = .none
view.addSubview(addPost!)
addPost?.addTarget(self, action: #selector(writeComment), for: UIControlEvents.touchDown)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print("app coun\(apps!.count)")
return apps!.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cell : wallModelTableViewCell?
cell = tableView.dequeueReusableCell(withIdentifier: "cell") as? wallModelTableViewCell
if cell == nil {
cell = wallModelTableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "cell")
}
let app = apps![indexPath.row]//reading the array of data hence provider
//association of provider and view
//this is the processs from where view can read the data from provide
cell!.iconImageLabel!.image = app.icon
cell!.titleLabel!.text = app.title
cell?.backgroundColor = UIColor.white
cell!.commentsLabel?.image = app.comments_Label
cell?.commentsLabel?.center = CGPoint(x: tableView.frame.size.width/2, y: dynamic_height-20)
cell?.likeButtonLabel?.image = app.likeButton
cell?.likeButtonLabel?.center = CGPoint(x: (tableView.frame.size.width/2)-130, y: dynamic_height-20)
/*cell?.likeButtonLabel?.leftAnchor.constraint(equalTo: tableView.leftAnchor, constant: 50)*/
cell!.feedTextLabel!.text = app.feedText
cell?.feedTextLabel?.sizeToFit()//so that it can expand the data more than two lines
cell?.feedTextLabel?.backgroundColor = UIColor.clear
//Limiting UIlabel to 125 characters
if (cell?.feedTextLabel?.text.count)! > 125{
/*
let index = cell?.feedTextLabel?.text.index((cell?.feedTextLabel?.text.startIndex)!, offsetBy: 125)
cell?.feedTextLabel?.text = cell?.feedTextLabel?.text.substring(to: index!)
cell?.feedTextLabel?.text = cell?.feedTextLabel?.text.appending("...")*/
//cell?.feedTextLabel?.attributedText = NSAttributedString(string: "...readmore")
}
cell?.layer.cornerRadius = 6.0
cell?.isUserInteractionEnabled = false
cell?.titleLabel?.isUserInteractionEnabled = true
tableOfApps?.backgroundColor = UIColor.clear
tableOfApps?.backgroundView?.isOpaque = false
tableOfApps!.estimatedRowHeight = 150.0
tableOfApps!.rowHeight = UITableViewAutomaticDimension
print("table view cell for row")
/*let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector( self.labelAction(gesture:)))
cell?.feedTextLabel?.addGestureRecognizer(tap)
cell?.feedTextLabel?.isUserInteractionEnabled = true
tap.delegate = self as! UIGestureRecognizerDelegate*/
return cell!
}
/*#objc func labelAction(gesture: UITapGestureRecognizer){
}*/
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
print("height for row")
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 150.0
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: - Navigation
#objc func writeComment(){
let addComment = addCommentViewController()
navigationController?.pushViewController(addComment, animated: true)
}
/*
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
I want each row must have dynamic height as the content is provided by the user if the content contains 150 characters the height of the cell must be 200+ if content contains less than 125 characters the height must be as adequate to read.

UITableview scrolling is not responding properly?

booktable.frame = CGRect(x: 0, y: booktopview.bounds.height, width: screenWidth, height: screenHeight-booktopview.bounds.height-tabbarView.bounds.height)
booktable.register(UITableViewCell.self, forCellReuseIdentifier: "mycell")
booktable.dataSource = self
booktable.delegate = self
booktable.separatorColor = UIColor.lightGray
booktable.backgroundColor = UIColor.clear
booktable.separatorStyle = .singleLine
bookview.addSubview(booktable)
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if(tableView == booktable)
{
let cell1 = booktable.dequeueReusableCell(withIdentifier: "mycell")
for object in (cell1?.contentView.subviews)!
{
object.removeFromSuperview();
}
let img :UIImageView = UIImageView()
let lbl : UILabel = UILabel()
img.frame = CGRect(x: 15, y: 15, width: 80, height: 130)
img.image = imgarray[indexPath.row]
img.layer.borderWidth = 1.0
img.layer.borderColor = UIColor.lightGray.cgColor
cell1?.contentView.addSubview(img)
imgheight = img.bounds.height
lbl.frame = CGRect(x: img.bounds.width + 40, y: (imgheight+40-80)/2, width: booktable.bounds.width-img.bounds.width + 40 - 100, height: 80)
lbl.text = imgname[indexPath.row]
lbl.numberOfLines = 0
lbl.textAlignment = .left
lbl.font = UIFont(name: "Arial", size: 23)
lbl.textColor = UIColor.black
cell1?.selectionStyle = .none
cell1?.contentView.addSubview(lbl)
return cell1!
}
The code shown above is for book table, which sometimes scrolls like normal and sometimes not scrolling at all. I am doing all the code programatically. I have tested this on both simulators and devices but still the problem exists. Any help is appreciated...
Create Custom UITableViewCell, let's say it is ListTableCell
class ListTableCell: UITableViewCell {
#IBOutlet weak var lblTemp: UILabel!
#IBOutlet weak var imgTemp: UIImage!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
I've created UITableViewCell with xib like this and bind IBOutlets
Let's say we have struct Model and array like this
struct Model {
let image : UIImage
let name: String
}
for i in 0...10 {
let model = Model(image: #imageLiteral(resourceName: "Cat03"), name: "Temp \(i)")
array.append(model)
}
Now on ViewController viewDidLoad() method,
tableView.register(UINib(nibName: "ListTableCell", bundle: nil), forCellReuseIdentifier: "ListTableCell")
Implement UITableViewDataSource methods like this,
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ListTableCell") as! ListTableCell
let model = array[indexPath.row]
cell.lblTemp.text = model.name
cell.imgTemp.image = model.image
return cell
}
FYI
For different tableviews, you can create different custom cell the same way and cellForRowAt indexPath and numberOfRowsInSection method will change appropriately.
Let me know in case of any queries.
UPDATE
Follow this and this to create CustomTableCell programmatically

How To Share Same UIView Between Multiple UITableView Cells

Objective
When the user clicks on any of the 3 blue buttons, all buttons change to the same color.
Note: this is an abstraction of a shared progress view problem, it's therefore important that only one UIView is shared (or mimicked) across my three rows
Here is a compilable Swift project:
import UIKit
class ToggleButton: UIButton {
var connectedView: UIView?
func onPress() {
self.isHidden = true
self.connectedView?.isHidden = false
}
}
class ViewController : UIViewController, UITableViewDelegate, UITableViewDataSource {
var tableView: UITableView = UITableView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
var myView: UIView? = nil
var toggleBtn: ToggleButton? = nil
override func viewDidLoad() {
self.setupTableView()
}
fileprivate func setupTableView() {
self.tableView.dataSource = self
self.tableView.delegate = self
self.tableView.backgroundColor = UIColor.white
self.tableView.isOpaque = true
self.view.addSubview(self.tableView)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 3
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell(style: .default, reuseIdentifier: "CellIdentifier")
let frame = CGRect(x: 10, y: 10, width: 30, height: 30)
if let view = self.myView, let btn = self.toggleBtn {
cell.addSubview(view)
cell.addSubview(btn)
} else {
let myView = UIView(frame: frame)
myView.backgroundColor = UIColor.green
myView.isHidden = true
cell.addSubview(myView)
let toggleBtn = ToggleButton(frame: frame)
toggleBtn.backgroundColor = UIColor.blue
toggleBtn.addTarget(self, action: #selector(onPress), for: .touchUpInside)
toggleBtn.connectedView = myView
cell.addSubview(toggleBtn)
}
return cell
}
#objc func onPress(_ sender: Any) {
if let button = sender as? ToggleButton {
button.onPress()
}
}
}
Any help appreciated.
The concept of UITableViewCell is made to be very independent each other.
So the only thing you can do it having a bool flag in your ViewController, then you init your 3 cells with this flags.
And finally each time the button is pressed you toggle the flag en reload your tableView.

Why does adding UILabel in subView makes it pixelated

I'm making a message that is shown when the tableView is empty and I've added a label in my subView and it appears to be pixelated. But when I add something in my tableView and delete it, then the message shown (UILabel) is perfectly fine. Can't figure out why.
Adding the label in my self.tableView.backgroundView = emptyLabel solves it but I want to add two labels so I add one in subView that makes it pixelated.
Here is my code:
class ReminderTableViewController: UITableViewController
{
#IBOutlet var myTableView: UITableView!
#IBOutlet weak var dateLabel: UIView!
#IBAction func back(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
override func viewDidLoad() {
super.viewDidLoad()
self.tableView.separatorColor = UIColor.clear
tableView.separatorStyle = .none
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
performSegue(withIdentifier: "details", sender: self)
}
public func buttonImageForEmptyStateView() -> UIImage? {
return UIImage.init(named: "Exclamation Mark Filled-100-2")
}
override func viewDidAppear(_ animated: Bool) {
tableView.reloadData()
self.reloadEmptyState(forTableView: self.tableView)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
if list.count==0{
let emptyLabel=UILabel(frame: CGRect(x: 0,y: 0, width: self.view.bounds.width, height: self.view.bounds.height))
let emptyLabel2=UILabel(frame: CGRect(x: 0.0,y: 20.0, width: self.view.bounds.width, height: self.view.bounds.height))
self.view.addSubview(emptyLabel2)
self.view.addSubview(emptyLabel)
let emptyImage = UIImageView(image: UIImage(named: "Quote Right Filled-100 (3)"))
emptyImage.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(emptyImage)
emptyImage.alpha=0.1
NSLayoutConstraint.activate([
emptyImage.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
emptyImage.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
emptyImage.heightAnchor.constraint(equalToConstant: 90),
emptyImage.widthAnchor.constraint(equalToConstant: 90)
])
emptyLabel.text = "no present reminders"
emptyLabel.textColor=UIColor.darkGray
emptyLabel.font=UIFont(name: "HelveticaNeue-Light", size: 18)
emptyLabel.textAlignment = NSTextAlignment.center
emptyLabel2.text = "you add by going back to the homescreen"
emptyLabel2.textColor=UIColor.gray
emptyLabel2.font=UIFont(name: "HelveticaNeue-Light", size: 11)
emptyLabel2.textAlignment = NSTextAlignment.center
self.tableView.separatorStyle = UITableViewCellSeparatorStyle.none
return 0
}
else{
return (list.count)
}
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell=UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "cell")
cell.textLabel?.text=list[indexPath.row]
cell.contentView.backgroundColor = UIColor(red:0.89, green:0.89, blue:0.89, alpha:0.7)
cell.textLabel?.textColor=UIColor.black
cell.textLabel?.font=UIFont(name: "HelveticaNeue-Light", size: 16)
return (cell)
}
override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle==UITableViewCellEditingStyle.delete{
list.remove(at: indexPath.row)
tableView.reloadData()
}
}
}
numberOfRowsInSection is call multiple times, so there is not good place to add subview because every time this function is call another UILabel's instance add to view hierarchy.
Remove adding labels in numberOfRowsInSection. Add class variables:
var emptyLabel: UILabel!
var emptyLabel2: UILabel!
var emptyImage: UIImageView!
then add the function
func createEmptyLabels() {
emptyLabel=UILabel(frame: CGRect(x: 0,y: 0, width: self.view.bounds.width, height: self.view.bounds.height))
emptyLabel2=UILabel(frame: CGRect(x: 0.0,y: 20.0, width: self.view.bounds.width, height: self.view.bounds.height))
self.view.addSubview(emptyLabel2)
self.view.addSubview(emptyLabel)
emptyImage = UIImageView(image: UIImage(named: "Quote Right Filled-100 (3)"))
emptyImage.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(emptyImage)
emptyImage.alpha=0.1
NSLayoutConstraint.activate([
emptyImage.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
emptyImage.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
emptyImage.heightAnchor.constraint(equalToConstant: 90),
emptyImage.widthAnchor.constraint(equalToConstant: 90)
])
emptyLabel.text = "no present reminders"
emptyLabel.textColor=UIColor.darkGray
emptyLabel.font=UIFont(name: "HelveticaNeue-Light", size: 18)
emptyLabel.textAlignment = NSTextAlignment.center
emptyLabel2.text = "you add by going back to the homescreen"
emptyLabel2.textColor=UIColor.gray
emptyLabel2.font=UIFont(name: "HelveticaNeue-Light", size: 11)
emptyLabel2.textAlignment = NSTextAlignment.center
emptyLabel.isHidden = true
emptyLabel2.isHidden = true
emptyImage.isHidden = true
}
call this function in viewDidLoad
and in numberOfRowsInSection:
let hideEmptyViews = (list.count != 0)
emptyLabel.isHidden = hideEmptyViews
emptyLabel2.isHidden = hideEmptyViews
emptyImage.isHidden = hideEmptyViews
You are adding the label in numberOfRowsInSection. The problem is that this method is called many times. So you are adding many copies of the label, piled on top of one another, and this makes the label look funny.

Resources