How to view remove subview? - swift

let overlayView = UIView()
overlayView.backgroundColor = UIColor(red: 0, green: 0, blue: 0, alpha: 0.35)
overlayView.frame = self.view.bounds
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == 0{ self.view.addSubview(overlayView) {
performSegue(withIdentifier: "language", sender: nil)
}
}

To do what you ask you could have the overlay view as an optional, class level property, and try to remove it when the view appears
class VC1: UIViewController {
var overlayView: UIView?
override func viewDidAppear() {
super.viewDidAppear()
overlayView?.removeFromSuperView()
}
Or you could use a protocol / delegate pattern to inform VC1 that VC2 was bring removed and use that method to remove the overlayView. This is a cleaner solution.
However if you're doing whatever I think you are tyring to do (see my comment) I think there is a better approach - handle it all in the second view controller. Make the main view of second view controller do the masking by setting it's alpha, then add a container view to the centre of that view and add all your content/functionality into that container view. This way when you dismiss the second the blur layer will go with it.

Related

White Space at the bottom of a tableview

I have a viewcontroller with a tableview inside it. At the bottom of the tableview there is some white space that I want to get rid of and be replaced by my background colour.
I have added and customised the tableview programatically so I am looking for a programatic answer, as I did not use storyboard much for this. (I had only used it to setup my TabBarController and link it to navigation and view-controllers.)
Below is the some of the code I used to configure the tableview.
private let tableView: UITableView = {
let tableView = UITableView(frame: .zero, style: .plain)
tableView.register(ProfileTableViewCell.self, forCellReuseIdentifier: ProfileTableViewCell.identifier)
tableView.backgroundColor = Constants.backgroundColor
return tableView
}()
override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
tableView.frame = view.bounds
}
Im sure the answer is probably just a single line of code, but I couldn't find one that worked. Thanks in advance!
***EDIT
I have found a solution, but I still think there is a better way to solve this problem. The code below sets a UIView as the background of the tableview, then changes the colour of the UIView.
private let tableView: UITableView = {
let tableView = UITableView(frame: .zero, style: .plain)
tableView.register(ProfileTableViewCell.self, forCellReuseIdentifier: ProfileTableViewCell.identifier)
let backgroundView = UIView(frame: CGRect(x: 0,
y: 0,
width: tableView.bounds.size.width,
height: tableView.bounds.size.height))
backgroundView.backgroundColor = Constants.backgroundColor
tableView.backgroundView = backgroundView
return tableView
}()
The default color of the containing view controller is showing, since the table is short. Try setting the view controller's view's background color in viewDidLoad:
override func viewDidLoad() {
super.viewDidLoad();
view.backgroundColor = Constants.backgroundColor
}

Navigation and View Controller help in iOS 15 and Xcode 13

HI i have searched everywhere for a solution to my problem and cannot figure it out or found any other posts with the same problem.
I recently updated my Xcode project to Xcode 13 and my iPhone to iOS 15 and Apple made some significant changes to the navigation and tab bar structure which completely destroyed my app.
Need assistance on the correct structure on how to resolve this problem and am sure this will help lots of people who come across this same issue.
I have a ViewControllerA inside of a navigation controller which is nested inside of tab bar controller. User taps a button and segues to another ViewControllerB which is a modal VC that goes over full screen. User can then swipe down with a panGestureRecognizer.
As user swipes down there is a strange flicker effect which looks awful. The only solution I found is in storyboards to completely remove navigation bar and apply constraints to top of the view(I know this is possible but not scalable as I do not want to determine device size). But then view is covered by top bar.
I have attached video showing problem.
Please help as I do not know where to go from here.
THANK YOU
var initialTouchPoint: CGPoint = CGPoint(x: 0,y: 0)
#IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
tableView.dataSource = self
tableView.delegate = self
tableView.estimatedRowHeight = 636
tableView.rowHeight = UITableView.automaticDimension
}
#IBAction func panGestureRecognizerHandler(_ sender: UIPanGestureRecognizer) {
let touchPoint = sender.location(in: self.view?.window)
if sender.state == UIGestureRecognizer.State.began {
initialTouchPoint = touchPoint
} else if sender.state == UIGestureRecognizer.State.changed {
if touchPoint.y - initialTouchPoint.y > 0 {
self.view.frame = CGRect(x: 0, y: touchPoint.y - initialTouchPoint.y, width: self.view.frame.size.width, height: self.view.frame.size.height)
}
} else if sender.state == UIGestureRecognizer.State.ended || sender.state == UIGestureRecognizer.State.cancelled {
if touchPoint.y - initialTouchPoint.y > 100 {
self.dismiss(animated: true)
} else {
UIView.animate(withDuration: 0.3, animations: {
self.view.frame = CGRect(x: 0, y: 0, width: self.view.frame.size.width, height: self.view.frame.size.height)
})
}
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "SwipeDownCell", for: indexPath) as! SwipeDownTableViewCell
cell.postImageView.image = UIImage(named: "food")
cell.postImageView.contentMode = .scaleAspectFill
return cell
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
https://streamable.com/924xoo
I have the same issue. It is caused by a combination of safeArea and the modalPresentationStyle of the parent view controller. In my case it is UIModalPresentationOverCurrentContext.
If you use other presentation styles, e.g. UIModalPresentationPopover, the flickering disappear.
As this is not appropriate in my case, I found an easy workaround.
You need to set the top constraint of your first item in the child view to refer the superview, not the safe area!
To better support devices without the notch, you can use following helper method implemented in AppDelegate.
- (UIEdgeInsets)getSafeAreaInsets {
if (#available(iOS 11.0, *)) {
UIEdgeInsets insets = self.window.safeAreaInsets;
return insets;
} else {
return UIEdgeInsetsZero;
}
Call this in the viewDidLoad of the child view and check if the bottom edge is 0.
//classic devices without notch
if ([(AppDelegate*)[[UIApplication sharedApplication] delegate] getSafeAreaInsets].bottom == 0) {
self.labelHeaderContraint.constant = 32;
}

Does iOS 14 have some breaking changes that disable vertical scroll for Collection View? [duplicate]

I have a search form that uses a tableview. After updating Xcode 12 today the UISwitch, UITextField, UISlider no longer work when nested inside a UITableViewCell. Is there a property that has changed that I need to set to make this work again?
To be sure it wasn't just my project, I created a new project and nestled a UITextField inside of it and it doesn't work either.
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
let textField = UITextField(frame: CGRect(x: 5, y: 5, width: 400.0, height: 25.0))
textField.delegate = self
textField.backgroundColor = .blue
cell.addSubview(textField)
return cell
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("this will get called even when selecting the UITextField")
}
func textFieldDidBeginEditing(_ textField: UITextField) {
print("this is never called")
}
Your code was always wrong:
cell.addSubview(textField)
You must never add a subview to a cell. Add the subview to the cell's contentView.
The same happened to me since I upgraded to iOS 14.
This has worked for me when I add the subViews directly to the cell,
cell.contentView.isUserInteractionEnabled = true
Had similar issue, and been going on around for it... what was issue with my code is that under UITableViewCell I was doing this:
didSet {
if contentView.backgroundColor == backgroundColor { return }
contentView.backgroundColor = backgroundColor
for v in otherView.subview { v.backgroundColor = backgroundColor }
}
Removing this line here contentView.backgroundColor = backgroundColor did the trick. Cell is now visible and there is no duplicated contentView
Maybe this will help someone, since I found only answers regarding adding subviews directly to cell instead to cell.contentView
EDIT 1:
Okay, just wanted to update you on situation, issue was that my subviews where of type UIStackView and I had used subview where I actually should have used arrangedSubviews
Hope this will help someone

Is there a callback for ViewCell fully laid out in swift?

I have a UITableView with cells, the relevant part of the layout looks like this:
everything is fine until i try to add shadows to that button(orange) and view ($-), this happens:
The problem is that the view is not fully set in awakeFromNib, and it also not fully set during
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
So when can i add the shadow to those views without having to worry about the size not being set correctly yet?
Aditional Info: if i set it during the cell setup, it does not work at first, but after scrolling it gets fixed for as long as the view is open.
Edit 1: how do i add the shadows? I call a func for the cell that calls the next method passing the view as parameter, i think that #DonMag suggestion should work, subclassing should work, but is there no way to know when all the view is laid out in a TableView?
static func addShadowToView(view: UIView, CornerRadius: CGFloat){
view.layer.cornerRadius = CornerRadius
view.clipsToBounds = true
view.layer.masksToBounds = false
view.layer.shadowColor = UIColor.gray.cgColor
view.layer.shadowOffset = CGSize(width: 0.1, height: 0.1)
view.layer.shadowOpacity = 0.5
let shadowPath = UIBezierPath(roundedRect: view.bounds,
cornerRadius: view.layer.cornerRadius)
view.layer.shadowPath = shadowPath.cgPath
}

Custom UITableViewCell programmatically with SWIFT

Attached you may find a picture of (left) my attempt to create a similar (right) UITableView. they look like buttons but they're only cells that can be clicked on as a tableview cell.
I have tried many different things including adding a container window inside a custom cell, adding a UIImage inside the custom cell but I just can't replicate these cells!
I have tried using a custom cell class, I have tried doing it through IB and I for the crazyiness of me, cannot recreate it.
Would anyone be able to give me a hint on how to create the (inside cell) text-bounding box/square? with the different background colour lighting?
If this can easily be done with IB I'd rather do it this way, but if you have a sample customcell class that I can take a look at that'd be greatly appreciated too!
Thank you for taking the time to look at my question.
I have made a sample for you close to your requirement. Have a look
https://github.com/RajanMaheshwari/CustomTableCell
I would like to do this using a UITableView.
My approach will be taking a custom cell and add a UIView with some constraints from left, right, up and down.
Also I will provide the same background color to UITableView, UIView which is the superview and the cell content view and also make the separator of UITableView as None and Selection of TableCell as None so that the UI looks like
Next after applying every constraint and making a CustomCell and making IBOutlets we will jump to code.
I will do all the shadow and outlining in Custom Cell's awakeFromNib method
This will be my CustomTableViewCell class
class CustomTableViewCell: UITableViewCell {
#IBOutlet weak var labelBackgroundView: UIView!
#IBOutlet weak var cellLabel: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
labelBackgroundView.layer.borderWidth = 0.5
labelBackgroundView.layer.borderColor = UIColor.lightGrayColor().CGColor
labelBackgroundView.layer.shadowColor = UIColor.lightGrayColor().CGColor
labelBackgroundView.layer.shadowOpacity = 0.8
labelBackgroundView.layer.shadowRadius = 5.0
labelBackgroundView.layer.shadowOffset = CGSizeMake(0.0, 2.0)
labelBackgroundView.layer.masksToBounds = false;
}
I have two outlets.
One is the label in which you will be displaying the name.
Other is the outer view which you want to display with some outlining and shadow.
The ViewController code will be:
class ViewController: UIViewController,UITableViewDataSource,UITableViewDelegate {
var array = [String]()
#IBOutlet weak var myTableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
array = ["Wealth","Health","Esteem","Relationship"]
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return array.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CustomTableViewCell") as! CustomTableViewCell
cell.cellLabel.text = array[indexPath.row]
cell.labelBackgroundView.tag = indexPath.row
cell.labelBackgroundView.userInteractionEnabled = true
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(cellViewTapped))
cell.labelBackgroundView.addGestureRecognizer(tapGesture)
return cell
}
func cellViewTapped(sender:UITapGestureRecognizer) {
let view = sender.view
let index = view?.tag
print(index!)
}
}
Here I have not used didSelectIndex of UITableViewDelegate as I only want the tap on the Outlining LabelBackgroundView and not on complete cell.
So the final outcome is like this
I think you are on the right path. I did something similar in a project. I created a subclass of UIView (too add a shadow to the view) and added a view with this type inside the cell.
class ShadowedView: UIView {
override func awakeFromNib() {
layer.shadowColor = UIColor(red: 157.0/255.0, green: 157.0/255.0, blue: 157.0/255.0, alpha: 0.5).CGColor
layer.shadowOpacity = 0.8
layer.shadowRadius = 5.0
layer.shadowOffset = CGSizeMake(0.0, 2.0)
}
}
Don't forget to add some constraints to the view inside the cell.
You can arrange your collection view layout in "Size insepector"
And customise your image in the cell.