Swift - TableViewCell - Layout margin not working - swift

I have a table view which should display comments with their replies. Whenever the replies are shown, there should be a margin on the left side so it is clear that a particular reply belongs to the comment above.
To achieve that, I tried following:
class CommentsTableViewCell: UITableViewCell {
// label containing name of comment writer
private func initSenderLabel() {
senderLabel.translatesAutoresizingMaskIntoConstraints = false
self.contentView.addSubview(senderLabel)
senderLabel.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 18).isActive = true
senderLabel.widthAnchor.constraint(equalToConstant: 150).isActive = true
senderLabel.topAnchor.constraint(equalTo: self.contentView.topAnchor, constant: 6).isActive = true
senderLabel.heightAnchor.constraint(equalToConstant:14).isActive = true
senderLabel.font = .boldSystemFont(ofSize: 14)
senderLabel.adjustsFontSizeToFitWidth = true
senderLabel.textColor = .gray
}
// actual comment
private func initCommentLabel() {
commentLabel.translatesAutoresizingMaskIntoConstraints = false
self.contentView.addSubview(commentLabel)
commentLabel.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 18).isActive = true
commentLabel.widthAnchor.constraint(equalToConstant: 209).isActive = true
commentLabel.topAnchor.constraint(equalTo: self.senderLabel.bottomAnchor, constant: 2).isActive = true
commentLabel.bottomAnchor.constraint(equalTo: self.contentView.bottomAnchor, constant: -29).isActive = true
commentLabel.font = .boldSystemFont(ofSize: 16)
commentLabel.textColor = .black
commentLabel.lineBreakMode = .byWordWrapping
commentLabel.numberOfLines = 0
}
// button to load replies
private func initLoadReplyButton() {
loadReplyButton.translatesAutoresizingMaskIntoConstraints = false
self.contentView.addSubview(loadReplyButton)
loadReplyButton.leadingAnchor.constraint(equalTo: self.contentView.leadingAnchor, constant: 50).isActive = true
loadReplyButton.widthAnchor.constraint(equalToConstant: 150).isActive = true
loadReplyButton.topAnchor.constraint(equalTo: commentLabel.bottomAnchor, constant: 0).isActive = true
loadReplyButton.heightAnchor.constraint(equalToConstant: 24).isActive = true
loadReplyButton.addTarget(self, action: #selector(loadReplyButton_touched), for: .touchDown)
loadReplyButton.setTitle(NSLocalizedString(LOAD_REPLIES_BUTTON_TITLE, comment: ""), for: .normal)
loadReplyButton.backgroundColor = .clear
loadReplyButton.setTitleColor(.darkGray, for: .normal)
}
// Sets up the cell using the comment data
func setup(comment: Comment, sender:String) {
// Assign comment
self.commentObject = comment
// Update UI depending if it is a comment or reply
if comment is CommentReply {
loadReplyButton.isHidden = true
contentView.layoutMargins = UIEdgeInsets(top: 0, left: 150, bottom: 0, right: 0)
}
else {
// Remove insets
loadReplyButton.isHidden = false
UIView.setAnimationsEnabled(false)
updateButtonTitle()
UIView.setAnimationsEnabled(true)
}
if !comment.hasReplies {
loadReplyButton.isHidden = true
}
// Update size layout
self.layoutIfNeeded()
}
However, the code above still shows me the replies as it does for the "normal" comments. How can I modify the position of the replies?

Related

add 2 image views to a uiscrollview func every time it is called

My swift code below goal is to add 2 image views every time. Ass you can in the gif below only one image view is being added. I just need to add 2 image views. The image views are lastImage and lastImage2. you can see only lastImage is being shown. It seems I can only add 1 imageview when func didclickadd is called.
import UIKit
class ViewController: UIViewController {
fileprivate var lastImage:UIImageView?
fileprivate var lastImage2:UIImageView?
fileprivate var mainViewBootom:NSLayoutConstraint?
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
setupVIew()
}
override func viewDidAppear(_ animated: Bool) {
scrollView.contentSize = CGSize(width: view.frame.width, height: mainView.frame.height)
view.layoutIfNeeded()
}
//MARK: Components
let scrollView:UIScrollView = {
let sv = UIScrollView(frame: .zero)
return sv
}()
let mainView:UIView = {
let uv = UIView()
uv.backgroundColor = .white
return uv
}()
let btnAdd:UIButton = {
let btn = UIButton(type: .system)
btn.setTitle("Add", for: .normal)
return btn
}()
let textField:UITextField = {
let jake = UITextField()
return jake
}()
//MARK: Setup UI
func setupVIew() {
view.addSubview(scrollView)
view.addSubview(btnAdd)
view.addSubview(textField)
scrollView.translatesAutoresizingMaskIntoConstraints = false
btnAdd.translatesAutoresizingMaskIntoConstraints = false
textField.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
btnAdd.centerXAnchor.constraint(equalTo: view.centerXAnchor),
btnAdd.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -12),
btnAdd.widthAnchor.constraint(equalToConstant: 100),
btnAdd.heightAnchor.constraint(equalToConstant: 45),
//
textField.centerXAnchor.constraint(equalTo: view.centerXAnchor),
textField.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 25),
textField.widthAnchor.constraint(equalToConstant: 100),
textField.heightAnchor.constraint(equalToConstant: 45),
//
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
scrollView.bottomAnchor.constraint(equalTo: btnAdd.topAnchor , constant: -12),
])
btnAdd.addTarget(self, action: #selector(didClickedAdd), for: .touchUpInside)
scrollView.addSubview(mainView)
mainView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
mainView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
mainView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
mainView.topAnchor.constraint(equalTo: scrollView.topAnchor),
])
let imgView = UIImageView(frame: CGRect(x: 0, y: 0, width: 150, height: 100))
imgView.backgroundColor = .red
mainView.addSubview(imgView)
let samsam = UIImageView(frame: CGRect(x: 0, y: 200, width: 40, height: 100))
samsam.backgroundColor = .blue
mainView.addSubview(samsam)
imgView.translatesAutoresizingMaskIntoConstraints = false
imgView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
imgView.widthAnchor.constraint(equalToConstant: 150).isActive = true
imgView.heightAnchor.constraint(equalToConstant: 100).isActive = true
samsam.translatesAutoresizingMaskIntoConstraints = false
samsam.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
samsam.topAnchor.constraint(equalTo: imgView.bottomAnchor).isActive = true
samsam.widthAnchor.constraint(equalToConstant: 75).isActive = true
samsam.heightAnchor.constraint(equalToConstant: 100).isActive = true
if lastImage != nil {
imgView.topAnchor.constraint(equalTo: lastImage!.bottomAnchor , constant: 20).isActive = true
}else{
imgView.topAnchor.constraint(equalTo: mainView.topAnchor , constant: 12).isActive = true
}
lastImage = samsam
mainViewBootom = mainView.bottomAnchor.constraint(equalTo: lastImage!.bottomAnchor , constant: 12)
mainViewBootom!.isActive = true
}
#objc func didClickedAdd(){
let imgView = UIImageView(frame: CGRect(x: 20, y: 0, width: 30, height: 20))
imgView.backgroundColor = .orange
mainView.addSubview(imgView)
let ss = UIImageView(frame: CGRect(x: 0, y: 0, width: 40, height: 50))
imgView.backgroundColor = .green
mainView.addSubview(ss)
imgView.translatesAutoresizingMaskIntoConstraints = false
imgView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
imgView.widthAnchor.constraint(equalToConstant: 40).isActive = true
imgView.heightAnchor.constraint(equalToConstant: 60).isActive = true
ss.translatesAutoresizingMaskIntoConstraints = false
ss.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = false
ss.widthAnchor.constraint(equalToConstant: 80).isActive = true
ss.heightAnchor.constraint(equalToConstant: 90).isActive = true
if lastImage != nil {
ss.topAnchor.constraint(equalTo: imgView.topAnchor , constant: 20).isActive = true
imgView.topAnchor.constraint(equalTo: lastImage!.bottomAnchor , constant: 50).isActive = true
}else{
imgView.topAnchor.constraint(equalTo: mainView.topAnchor , constant: 10).isActive = true
ss.bottomAnchor.constraint(equalTo: imgView.bottomAnchor , constant: 25).isActive = true
}
lastImage = imgView
lastImage2 = ss
mainView.removeConstraint(mainViewBootom!)
mainViewBootom = mainView.bottomAnchor.constraint(equalTo: lastImage2!.bottomAnchor , constant: 40)
mainViewBootom!.isActive = true
view.layoutIfNeeded()
scrollView.contentSize = CGSize(width: view.frame.width, height: mainView.frame.height)
view.layoutIfNeeded()
}
}
Couple notes...
With proper constraint setup, auto-layout handles the UIScrollView content size all by itself. No need to ever set scrollView.contentSize = ...
You have several instances of adding a subview (image view) to your mainView, which is a subview of your scroll view, but then you add constraints from that subview to your controller's view. Make sure you are constraining elements to the proper other elements.
Here's your code, with commented changes:
class BenViewController: UIViewController {
fileprivate var lastImage:UIImageView?
// 1) don't need this
// fileprivate var lastImage2:UIImageView?
fileprivate var mainViewBootom:NSLayoutConstraint?
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
setupVIew()
}
// 2) don't need this
// override func viewDidAppear(_ animated: Bool) {
// scrollView.contentSize = CGSize(width: view.frame.width, height: mainView.frame.height)
// view.layoutIfNeeded()
// }
//MARK: Components
let scrollView:UIScrollView = {
let sv = UIScrollView(frame: .zero)
return sv
}()
let mainView:UIView = {
let uv = UIView()
uv.backgroundColor = .white
return uv
}()
let btnAdd:UIButton = {
let btn = UIButton(type: .system)
btn.setTitle("Add", for: .normal)
return btn
}()
let textField:UITextField = {
let jake = UITextField()
return jake
}()
//MARK: Setup UI
func setupVIew() {
view.addSubview(scrollView)
view.addSubview(btnAdd)
view.addSubview(textField)
scrollView.translatesAutoresizingMaskIntoConstraints = false
btnAdd.translatesAutoresizingMaskIntoConstraints = false
textField.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
btnAdd.centerXAnchor.constraint(equalTo: view.centerXAnchor),
btnAdd.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -12),
btnAdd.widthAnchor.constraint(equalToConstant: 100),
btnAdd.heightAnchor.constraint(equalToConstant: 45),
//
textField.centerXAnchor.constraint(equalTo: view.centerXAnchor),
textField.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 25),
textField.widthAnchor.constraint(equalToConstant: 100),
textField.heightAnchor.constraint(equalToConstant: 45),
//
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
scrollView.bottomAnchor.constraint(equalTo: btnAdd.topAnchor , constant: -12),
])
btnAdd.addTarget(self, action: #selector(didClickedAdd), for: .touchUpInside)
scrollView.addSubview(mainView)
mainView.translatesAutoresizingMaskIntoConstraints = false
// 3) change this:
// NSLayoutConstraint.activate([
// mainView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
// mainView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
// mainView.topAnchor.constraint(equalTo: scrollView.topAnchor),
// ])
//
// to this
NSLayoutConstraint.activate([
mainView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
mainView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
mainView.topAnchor.constraint(equalTo: scrollView.topAnchor),
mainView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
mainView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
])
// end of change 3)
let imgView = UIImageView(frame: CGRect(x: 0, y: 0, width: 150, height: 100))
imgView.backgroundColor = .red
mainView.addSubview(imgView)
let samsam = UIImageView(frame: CGRect(x: 0, y: 200, width: 40, height: 100))
samsam.backgroundColor = .blue
mainView.addSubview(samsam)
imgView.translatesAutoresizingMaskIntoConstraints = false
// 4) change view.centerXAnchor to mainView.centerXAnchor
// imgView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
imgView.centerXAnchor.constraint(equalTo: mainView.centerXAnchor).isActive = true
imgView.widthAnchor.constraint(equalToConstant: 150).isActive = true
imgView.heightAnchor.constraint(equalToConstant: 100).isActive = true
samsam.translatesAutoresizingMaskIntoConstraints = false
// 5) change view.centerXAnchor to mainView.centerXAnchor
// samsam.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
samsam.centerXAnchor.constraint(equalTo: mainView.centerXAnchor).isActive = true
samsam.topAnchor.constraint(equalTo: imgView.bottomAnchor).isActive = true
samsam.widthAnchor.constraint(equalToConstant: 75).isActive = true
samsam.heightAnchor.constraint(equalToConstant: 100).isActive = true
if lastImage != nil {
imgView.topAnchor.constraint(equalTo: lastImage!.bottomAnchor , constant: 20).isActive = true
}else{
imgView.topAnchor.constraint(equalTo: mainView.topAnchor , constant: 12).isActive = true
}
lastImage = samsam
mainViewBootom = mainView.bottomAnchor.constraint(equalTo: lastImage!.bottomAnchor , constant: 12)
mainViewBootom!.isActive = true
}
#objc func didClickedAdd(){
let imgView = UIImageView(frame: CGRect(x: 20, y: 0, width: 30, height: 20))
imgView.backgroundColor = .orange
mainView.addSubview(imgView)
let ss = UIImageView(frame: CGRect(x: 0, y: 0, width: 40, height: 50))
// 6) typo or copy/paste mistake
// imgView.backgroundColor = .green
ss.backgroundColor = .green
mainView.addSubview(ss)
imgView.translatesAutoresizingMaskIntoConstraints = false
// 7) change view.centerXAnchor to mainView.centerXAnchor
// imgView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
imgView.centerXAnchor.constraint(equalTo: mainView.centerXAnchor).isActive = true
imgView.widthAnchor.constraint(equalToConstant: 40).isActive = true
imgView.heightAnchor.constraint(equalToConstant: 60).isActive = true
ss.translatesAutoresizingMaskIntoConstraints = false
// 8) change view.leadingAnchor to mainView.leadingAnchor
// ss.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = false
ss.leadingAnchor.constraint(equalTo: mainView.leadingAnchor).isActive = false
ss.widthAnchor.constraint(equalToConstant: 80).isActive = true
ss.heightAnchor.constraint(equalToConstant: 90).isActive = true
// 9) always need to do this ... but did you mean imgView.bottomAnchor?
ss.topAnchor.constraint(equalTo: imgView.topAnchor , constant: 20).isActive = true
if lastImage != nil {
// 9a) instead of only here
//ss.topAnchor.constraint(equalTo: imgView.topAnchor , constant: 20).isActive = true
imgView.topAnchor.constraint(equalTo: lastImage!.bottomAnchor , constant: 50).isActive = true
}else{
imgView.topAnchor.constraint(equalTo: mainView.topAnchor , constant: 10).isActive = true
}
// 10) always need to do this
// deactivate bottom constraint
mainViewBootom?.isActive = false
lastImage = ss
mainViewBootom = mainView.bottomAnchor.constraint(equalTo: lastImage!.bottomAnchor, constant: 40)
mainViewBootom?.isActive = true
// 11) don't need any of this
// lastImage = imgView
// lastImage2 = ss
// mainView.removeConstraint(mainViewBootom!)
//
//
// mainViewBootom = mainView.bottomAnchor.constraint(equalTo: lastImage2!.bottomAnchor , constant: 40)
//
//
//
//
// mainViewBootom!.isActive = true
// view.layoutIfNeeded()
//
// scrollView.contentSize = CGSize(width: view.frame.width, height: mainView.frame.height)
// view.layoutIfNeeded()
}
}
Use Xcode’s “view debugger” (the button is circled in red in my screen snapshot below) and you’ll see what’s going on:
Your ss view has no background color. Note, that when you created that view, you accidentally reset the imgView background color a second time rather than setting the ss.backgroundColor.
Fix that and you’ll see your both imgView and ss:
The view debugger is your best friend when trying to diagnose issues like this. Now, obviously, the green view probably isn’t where you intended it, but you should now be able to see it and diagnose that issue very easily.
All of this having been said, a few observations:
You’re making life much harder than you need to. If you just set the constraints for the scroll view and a stack view within that scroll view, you then only need to add an arranged subview. For example:
#objc func didTapButton(_ sender: UIButton) {
stackView.addArrangedSubview(randomView())
stackView.addArrangedSubview(randomView())
}
Note, once the stack view and scroll view have been set up (see below), then you don’t need to mess around with contentSize or constraints for these subviews at all (other than the widthAnchor and heightAnchor). The auto layout engine, combined with the constraints between the stack view and the scroll view, will take care of everything for you.
So, a full working example:
class ViewController: UIViewController {
let scrollView: UIScrollView = {
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
return scrollView
}()
let stackView: UIStackView = {
let stackView = UIStackView()
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.alignment = .center
stackView.spacing = 10
return stackView
}()
let button: UIButton = {
let button = UIButton(type: .system)
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle("Add", for: .normal)
button.addTarget(self, action: #selector(didTapButton(_:)), for: .touchUpInside)
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
configure()
}
}
// MARK: - Actions
extension ViewController {
#objc func didTapButton(_ sender: UIButton) {
stackView.addArrangedSubview(randomView())
stackView.addArrangedSubview(randomView())
}
}
// MARK: - Private utility methods
private extension ViewController {
func configure() {
view.addSubview(scrollView)
view.addSubview(button)
scrollView.addSubview(stackView)
NSLayoutConstraint.activate([
// define frame of `scrollView`
scrollView.topAnchor.constraint(equalTo: view.topAnchor),
scrollView.bottomAnchor.constraint(equalTo: button.topAnchor),
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
// define frame of `button`
button.centerXAnchor.constraint(equalTo: view.centerXAnchor),
button.bottomAnchor.constraint(equalTo: view.bottomAnchor),
// define contentSize of `scrollView` based upon size of `stackView`
stackView.topAnchor.constraint(equalTo: scrollView.contentLayoutGuide.topAnchor),
stackView.bottomAnchor.constraint(equalTo: scrollView.contentLayoutGuide.bottomAnchor),
stackView.leadingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: scrollView.contentLayoutGuide.trailingAnchor),
// but define width of `stackView` relative to the _main view_
stackView.widthAnchor.constraint(equalTo: scrollView.frameLayoutGuide.widthAnchor)
])
button.setContentHuggingPriority(.required, for: .vertical)
}
func randomView() -> UIView {
let widthRange = view.bounds.width * 0.1 ... view.bounds.width * 0.9
let heightRange = view.bounds.width * 0.1 ... view.bounds.width * 0.25
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
view.widthAnchor.constraint(equalToConstant: .random(in: widthRange)),
view.heightAnchor.constraint(equalToConstant: .random(in: heightRange))
])
view.backgroundColor = UIColor(red: .random(in: 0.25...1), green: .random(in: 0.25...1), blue: .random(in: 0.25...1), alpha: 1)
return view
}
}
Even better, I’d personally set up the scroll view, stack view, button, and all the associated constraints in Interface Builder, and then that hairy configure method in my example goes away completely. It’s fun to learn how to create views programmatically, but in real-world projects, it’s rarely the most productive way to do it. Do programmatic views where needed (e.g. adding arranged subviews to the stack view on the click of a button), but otherwise, for those views that should be there when you first run the app, Interface Builder is worth considering.
E.g. It dramatically reduces the amount of code above, leaving us simply with:
class ViewController: UIViewController {
#IBOutlet weak var scrollView: UIScrollView!
#IBOutlet weak var stackView: UIStackView!
#IBAction func didTapButton(_ sender: UIButton) {
stackView.addArrangedSubview(randomView())
stackView.addArrangedSubview(randomView())
}
}
// MARK: - Private utility methods
private extension ViewController {
func randomView() -> UIView { ... }
}
Clearly, it takes a while to get used to designing views and configuring constraints in IB, but it’s worth the effort. It distills our code down the the bare essentials.
In your code, you’re setting frames for these image views and then setting translatesAutoresizingMaskIntoConstraints. There’s absolutely no point in setting the frame in that case, because translatesAutoresizingMaskIntoConstraints says “ignore my frame, use constraints instead.”
I’m assuming you’re doing all of this just to become familiar with scroll views, but it’s worth noting that, especially when adding lots of image views, that the scroll view is an inherently inefficient approach.
For example, let’s say you’ve added 100 image views, but you can see only 8 at a time. Do you really want to hold all 100 image views in memory at the same time? No.
But, UITableView, which is a subclass of UIScrollView, takes care of this. You end up only keeping the currently visible image views in memory. It’s a far better approach.
This is especially true when you start using actual UIImage objects, because they require a lot of memory. We get lulled into a sense of security, looking at reasonably sized PNG/JPG assets, but when they’re loaded into memory, they’re uncompressed and require a disproportionate amount of memory.

Multiple buttons triggered with one function programmaticaly swift

Tried to summarize my code. Problem is i am getting "newCalculator[2861:53607] -[UIButton buttonClicked:]: unrecognized selector sent to instance 0x7fd912651e50" error and trying to understand what i need to do? I researched some solutions changing selector syntax however still this problem persists. What i want is; inside a stackview i add multiple buttons with an order and all buttons should call same function when they are clicked.
o//
// ViewController.swift
// newCalculator
//
// Created by taylank on 17.10.2019.
// Copyright © 2019 TKT. All rights reserved.
//
import UIKit
var stackViews = [UIStackView]()
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//Layer 1
let containerStackView1 = UIStackView()
containerStackView1.translatesAutoresizingMaskIntoConstraints = false
containerStackView1.axis = .vertical
containerStackView1.distribution = .fillEqually
containerStackView1.spacing = 1
//Layer 2
let topHalfView2 = UIView()
topHalfView2.translatesAutoresizingMaskIntoConstraints = false
topHalfView2.backgroundColor = .white
let botHalfView2 = UIView()
botHalfView2.translatesAutoresizingMaskIntoConstraints = false
//Layer 3
let topLabel3 = UILabel()
topLabel3.translatesAutoresizingMaskIntoConstraints = false
topLabel3.text = "0"
topLabel3.font = UIFont.boldSystemFont(ofSize: 40)
let containerStackView3 = UIStackView()
containerStackView3.translatesAutoresizingMaskIntoConstraints = false
containerStackView3.axis = .vertical
containerStackView3.distribution = .fillEqually
containerStackView3.spacing = 1
//Layer 4
stackViews = createStackViews(from: 0, to: 4, align: "h")
let yamaView = UIView()
yamaView.translatesAutoresizingMaskIntoConstraints = false
yamaView.backgroundColor = .black
//ADDING VIEWS TO SCENE .VIEW->Contstckview1->Top-BotHalfView->contstckview2-ResultLabel->horzstackviews
containerStackView1.addArrangedSubview(topHalfView2)
containerStackView1.addArrangedSubview(botHalfView2)
view.addSubview(containerStackView1)
topHalfView2.addSubview(topLabel3)
botHalfView2.addSubview(containerStackView3)
containerStackView3.addArrangedSubview(stackViews[0])
view.addSubview(yamaView)
//stackViews[0].topAnchor.constraint(equalTo: containerStackView3.topAnchor, constant: 0).isActive = true
for a in 1...stackViews.count-1{
containerStackView3.addArrangedSubview(stackViews[a])
// stackViews[a].leadingAnchor.constraint(equalTo: stackViews[0].leadingAnchor, constant: 0).isActive = true
// stackViews[a].trailingAnchor.constraint(equalTo: stackViews[0].trailingAnchor, constant: 0).isActive = true
}
//stackViews[0].leadingAnchor.constraint(equalTo: containerStackView3.leadingAnchor, constant: 0).isActive = true
// stackViews[0].trailingAnchor.constraint(equalTo: containerStackView3.trailingAnchor, constant: 0).isActive = true
//Uiheight--v:?--uibottom--uifillequ
//ConstraintsStackView1
containerStackView1.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
containerStackView1.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
containerStackView1.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
containerStackView1.heightAnchor.constraint(equalToConstant: view.frame.height).isActive = true
//TopHalfView2
topHalfView2.topAnchor.constraint(equalTo: containerStackView1.topAnchor, constant: 0).isActive = true
topHalfView2.leadingAnchor.constraint(equalTo: containerStackView1.leadingAnchor, constant: 0).isActive = true
topHalfView2.trailingAnchor.constraint(equalTo: containerStackView1.trailingAnchor, constant: 0).isActive = true
// topHalfView2.heightAnchor.constraint(equalToConstant: containerStackView1.frame.height/2).isActive = true
//creates problem conflicts with other constraint fill equally?
//BotHalfView2
botHalfView2.bottomAnchor.constraint(equalTo: containerStackView1.bottomAnchor, constant: 0).isActive = true
botHalfView2.leadingAnchor.constraint(equalTo: containerStackView1.leadingAnchor, constant: 0).isActive = true
botHalfView2.trailingAnchor.constraint(equalTo: containerStackView1.trailingAnchor, constant: 0).isActive = true
// botHalfView2.heightAnchor.constraint(equalToConstant: containerStackView1.frame.height/2).isActive = true
//topLabel3
topLabel3.bottomAnchor.constraint(equalTo: topHalfView2.bottomAnchor, constant: 0).isActive = true
topLabel3.trailingAnchor.constraint(equalTo: topHalfView2.trailingAnchor, constant: -5).isActive = true
//ConstraintsStackView3
containerStackView3.leadingAnchor.constraint(equalTo: botHalfView2.leadingAnchor, constant: 0).isActive = true
containerStackView3.trailingAnchor.constraint(equalTo: botHalfView2.trailingAnchor, constant: 0).isActive = true
containerStackView3.topAnchor.constraint(equalTo: botHalfView2.topAnchor, constant: 0).isActive = true
containerStackView3.bottomAnchor.constraint(equalTo: botHalfView2.bottomAnchor, constant: 0).isActive = true
//constraint button
stackViews[4].arrangedSubviews[2].widthAnchor.constraint(equalTo: stackViews[4].arrangedSubviews[1].widthAnchor,multiplier: 1).isActive = true //sonbutton bir yandakine
stackViews[4].arrangedSubviews[1].widthAnchor.constraint(equalTo: stackViews[4].arrangedSubviews[0].widthAnchor,multiplier: 0.5).isActive = true // ortadaki buton en soldakine
yamaView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
yamaView.topAnchor.constraint(equalTo: stackViews[4].bottomAnchor).isActive = true
yamaView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
yamaView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
}
}
func createButtons(_ named: String...)->[UIButton]{
var c = 0
return named.map { name in
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle(name, for: .normal)
button.backgroundColor = UIColor.gray
button.setTitleColor(.white, for: .normal)
button.layer.cornerRadius = 1
button.addTarget(button, action: #selector(buttonClicked) ,for:.touchUpInside)
return button
}
}
#objc func buttonClicked(_ sender:UIButton){
print("clicked")
}
func createStackViews(from x: Int,to y:Int, align type: String)->[UIStackView]{
// use tag instead of name---
//use dictionary..keys name values
if (type == "v"){
for a in x...y{
let stackVertical = UIStackView()
stackVertical.translatesAutoresizingMaskIntoConstraints = false
stackVertical.axis = .vertical
stackVertical.spacing = 1
stackVertical.distribution = .fillEqually
stackVertical.tag = a
}
}
else if(type=="h"){
var counter = 0
for a in x...y{
counter += 1
switch counter{
case 1: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("Clear","+/-","%","÷"))
stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
stackHorizontal.axis = .horizontal
stackHorizontal.spacing = 1
stackHorizontal.distribution = .fillEqually
stackHorizontal.tag = 90+a
stackViews.append(stackHorizontal)
case 2: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("7","8","9","x"))
stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
stackHorizontal.axis = .horizontal
stackHorizontal.spacing = 1
stackHorizontal.distribution = .fillEqually
stackHorizontal.tag = 100 + a
stackViews.append(stackHorizontal)
case 3: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("4","5","6","-"))
stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
stackHorizontal.axis = .horizontal
stackHorizontal.spacing = 1
stackHorizontal.distribution = .fillEqually
stackHorizontal.tag = 110+a
stackViews.append(stackHorizontal)
case 4: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("1","2","3","+"))
stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
stackHorizontal.axis = .horizontal
stackHorizontal.spacing = 1
stackHorizontal.distribution = .fillEqually
stackHorizontal.tag = 120 + a
stackViews.append(stackHorizontal)
case 5: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("0",",","="))
stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
stackHorizontal.axis = .horizontal
stackHorizontal.spacing = 1
stackHorizontal.distribution = .fillProportionally
stackHorizontal.tag = 130 + a
stackViews.append(stackHorizontal)
default:
break
}
}
return stackViews
}
return [UIStackView.init()]
}
------------SOLUTION----------
All of the functions are inside the viewcontroller class
class ViewController: UIViewController {
override func viewDidLoad() {
stackViews = createStackViews(from: 0, to: 4, align: "h")
}
func createButtons(_ named: String...)->[UIButton]{
//codes
button.addTarget(self, action: #selector(buttonClicked) ,for:.touchUpInside)
//codes
}
#objc func buttonClicked(_ sender:UIButton){
print("clicked")
}
func createStackViews(from x: Int,to y:Int, align type: String)->[UIStackView]{
//codes
UIStackView(arrangedSubviews:createButtons("Clear","+/-","%","÷"))
//codes
}
}
You have several problems:
Your selector needs to be selector(buttonClicked(:)), so
button.addTarget(self, action: #selector(buttonClicked(:)) ,for:.touchUpInside)
Your functions buttonClicked(_:) and createButtons() need to be inside your view controller class. As it is, buttonClicked(_:) is a global function, which means it can't be part of a target/action. (Action methods need to be inside a target object (usually the view controller that owns the button.)
Replace
button.addTarget(button, action: "buttonClicked:" ,for:.touchUpInside)
with
button.addTarget(self, action: #selector(buttonClicked) ,for:.touchUpInside)
#objc func buttonClicked(_ sender:UIButton){
import UIKit
var stackViews = [UIStackView]()
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//Layer 1
let containerStackView1 = UIStackView()
containerStackView1.translatesAutoresizingMaskIntoConstraints = false
containerStackView1.axis = .vertical
containerStackView1.distribution = .fillEqually
containerStackView1.spacing = 1
//Layer 2
let topHalfView2 = UIView()
topHalfView2.translatesAutoresizingMaskIntoConstraints = false
topHalfView2.backgroundColor = .white
let botHalfView2 = UIView()
botHalfView2.translatesAutoresizingMaskIntoConstraints = false
//Layer 3
let topLabel3 = UILabel()
topLabel3.translatesAutoresizingMaskIntoConstraints = false
topLabel3.text = "0"
topLabel3.font = UIFont.boldSystemFont(ofSize: 40)
let containerStackView3 = UIStackView()
containerStackView3.translatesAutoresizingMaskIntoConstraints = false
containerStackView3.axis = .vertical
containerStackView3.distribution = .fillEqually
containerStackView3.spacing = 1
//Layer 4
stackViews = createStackViews(from: 0, to: 4, align: "h")
let yamaView = UIView()
yamaView.translatesAutoresizingMaskIntoConstraints = false
yamaView.backgroundColor = .black
//ADDING VIEWS TO SCENE .VIEW->Contstckview1->Top-BotHalfView->contstckview2-ResultLabel->horzstackviews
containerStackView1.addArrangedSubview(topHalfView2)
containerStackView1.addArrangedSubview(botHalfView2)
view.addSubview(containerStackView1)
topHalfView2.addSubview(topLabel3)
botHalfView2.addSubview(containerStackView3)
containerStackView3.addArrangedSubview(stackViews[0])
view.addSubview(yamaView)
//stackViews[0].topAnchor.constraint(equalTo: containerStackView3.topAnchor, constant: 0).isActive = true
for a in 1...stackViews.count-1{
containerStackView3.addArrangedSubview(stackViews[a])
// stackViews[a].leadingAnchor.constraint(equalTo: stackViews[0].leadingAnchor, constant: 0).isActive = true
// stackViews[a].trailingAnchor.constraint(equalTo: stackViews[0].trailingAnchor, constant: 0).isActive = true
}
//stackViews[0].leadingAnchor.constraint(equalTo: containerStackView3.leadingAnchor, constant: 0).isActive = true
// stackViews[0].trailingAnchor.constraint(equalTo: containerStackView3.trailingAnchor, constant: 0).isActive = true
//Uiheight--v:?--uibottom--uifillequ
//ConstraintsStackView1
containerStackView1.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0).isActive = true
containerStackView1.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
containerStackView1.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: 0).isActive = true
containerStackView1.heightAnchor.constraint(equalToConstant: view.frame.height).isActive = true
//TopHalfView2
topHalfView2.topAnchor.constraint(equalTo: containerStackView1.topAnchor, constant: 0).isActive = true
topHalfView2.leadingAnchor.constraint(equalTo: containerStackView1.leadingAnchor, constant: 0).isActive = true
topHalfView2.trailingAnchor.constraint(equalTo: containerStackView1.trailingAnchor, constant: 0).isActive = true
// topHalfView2.heightAnchor.constraint(equalToConstant: containerStackView1.frame.height/2).isActive = true
//creates problem conflicts with other constraint fill equally?
//BotHalfView2
botHalfView2.bottomAnchor.constraint(equalTo: containerStackView1.bottomAnchor, constant: 0).isActive = true
botHalfView2.leadingAnchor.constraint(equalTo: containerStackView1.leadingAnchor, constant: 0).isActive = true
botHalfView2.trailingAnchor.constraint(equalTo: containerStackView1.trailingAnchor, constant: 0).isActive = true
// botHalfView2.heightAnchor.constraint(equalToConstant: containerStackView1.frame.height/2).isActive = true
//topLabel3
topLabel3.bottomAnchor.constraint(equalTo: topHalfView2.bottomAnchor, constant: 0).isActive = true
topLabel3.trailingAnchor.constraint(equalTo: topHalfView2.trailingAnchor, constant: -5).isActive = true
//ConstraintsStackView3
containerStackView3.leadingAnchor.constraint(equalTo: botHalfView2.leadingAnchor, constant: 0).isActive = true
containerStackView3.trailingAnchor.constraint(equalTo: botHalfView2.trailingAnchor, constant: 0).isActive = true
containerStackView3.topAnchor.constraint(equalTo: botHalfView2.topAnchor, constant: 0).isActive = true
containerStackView3.bottomAnchor.constraint(equalTo: botHalfView2.bottomAnchor, constant: 0).isActive = true
//constraint button
stackViews[4].arrangedSubviews[2].widthAnchor.constraint(equalTo: stackViews[4].arrangedSubviews[1].widthAnchor,multiplier: 1).isActive = true //sonbutton bir yandakine
stackViews[4].arrangedSubviews[1].widthAnchor.constraint(equalTo: stackViews[4].arrangedSubviews[0].widthAnchor,multiplier: 0.5).isActive = true // ortadaki buton en soldakine
yamaView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
yamaView.topAnchor.constraint(equalTo: stackViews[4].bottomAnchor).isActive = true
yamaView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
yamaView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
}
func createButtons(_ named: String...)->[UIButton]{
var c = 0
return named.map { name in
let button = UIButton()
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle(name, for: .normal)
button.backgroundColor = UIColor.gray
button.setTitleColor(.white, for: .normal)
button.layer.cornerRadius = 1
button.addTarget(self, action: #selector(buttonClicked) ,for:.touchUpInside)
return button
}
}
#objc func buttonClicked(_ sender:UIButton){
print("clicked")
}
func createStackViews(from x: Int,to y:Int, align type: String)->[UIStackView]{
// use tag instead of name---
//use dictionary..keys name values
if (type == "v"){
for a in x...y{
let stackVertical = UIStackView()
stackVertical.translatesAutoresizingMaskIntoConstraints = false
stackVertical.axis = .vertical
stackVertical.spacing = 1
stackVertical.distribution = .fillEqually
stackVertical.tag = a
}
}
else if(type=="h"){
var counter = 0
for a in x...y{
counter += 1
switch counter{
case 1: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("Clear","+/-","%","÷"))
stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
stackHorizontal.axis = .horizontal
stackHorizontal.spacing = 1
stackHorizontal.distribution = .fillEqually
stackHorizontal.tag = 90+a
stackViews.append(stackHorizontal)
case 2: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("7","8","9","x"))
stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
stackHorizontal.axis = .horizontal
stackHorizontal.spacing = 1
stackHorizontal.distribution = .fillEqually
stackHorizontal.tag = 100 + a
stackViews.append(stackHorizontal)
case 3: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("4","5","6","-"))
stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
stackHorizontal.axis = .horizontal
stackHorizontal.spacing = 1
stackHorizontal.distribution = .fillEqually
stackHorizontal.tag = 110+a
stackViews.append(stackHorizontal)
case 4: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("1","2","3","+"))
stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
stackHorizontal.axis = .horizontal
stackHorizontal.spacing = 1
stackHorizontal.distribution = .fillEqually
stackHorizontal.tag = 120 + a
stackViews.append(stackHorizontal)
case 5: let stackHorizontal = UIStackView(arrangedSubviews:createButtons("0",",","="))
stackHorizontal.translatesAutoresizingMaskIntoConstraints = false
stackHorizontal.axis = .horizontal
stackHorizontal.spacing = 1
stackHorizontal.distribution = .fillProportionally
stackHorizontal.tag = 130 + a
stackViews.append(stackHorizontal)
default:
break
}
}
return stackViews
}
return [UIStackView.init()]
}
}

Button is showing on screen but textField is not appearing every time. what is the error in my code?

I am setting textfied and a button programmatically. The button is showing when we run the code but not textfield. is there any problem with constraints or any other please help.
let submitButton: UIButton = {
let btn = UIButton(type:.system)
btn.backgroundColor = .blue
btn.setTitle("Login", for: .normal)
btn.tintColor = .white
btn.layer.cornerRadius = 5
btn.clipsToBounds = true
btn.translatesAutoresizingMaskIntoConstraints = false
return btn
}()
let textBox: UITextView = {
let textView = UITextView()
textView.text = "we are learning iOs"
textView.font = UIFont.boldSystemFont(ofSize: 18)
textView.textAlignment = .center
textView.translatesAutoresizingMaskIntoConstraints = false
return textView
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(textBox)
setupTexBoxLayout()
view.addSubview(submitButton)
setupSubmitBUttonLayout()
}
private func setupTexBoxLayout(){
textBox.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
textBox.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
textBox.widthAnchor.constraint(equalToConstant: 100).isActive = true
}
private func setupSubmitBUttonLayout(){
submitButton.topAnchor.constraint(equalTo: textBox.bottomAnchor, constant: 100).isActive = true
submitButton.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 100).isActive = true
}
}
I have checked your code and debug it.
You have not specified height for textview so it is not showing it.
You can check the below code. I have added height constraint to it and it is displaying your textfield.
If you do not specify a height for textfield then it will take 0 height by default.
private func setupTexBoxLayout(){
textBox.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
textBox.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
textBox.widthAnchor.constraint(equalToConstant: 300).isActive = true
textBox.heightAnchor.constraint(equalToConstant: 40).isActive = true
}

Swift ImagePicker Throws SIGNAL SIGABRT on AutoLayout Constraints

I'm building a project in Swift5 and I need the user to upload a photo. I have it to the point where the user can open the ImagePicker and select a photo, but whenever they select the image and return to the original VC, I get a SIGNAL SIGABRT error (at bottom of post):
Here is where I add my constraints programatically:
func setupLayout(){
imgView.topAnchor.constraint(equalTo: view.topAnchor, constant: 150).isActive = true
imgView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
imgView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
imgView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
imgView.heightAnchor.constraint(equalToConstant: 125).isActive = true
topLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
topLabel.topAnchor.constraint(equalTo: imgView.bottomAnchor, constant: 60).isActive = true
topLabel.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -50).isActive = true
topLabel.heightAnchor.constraint(equalToConstant: 50).isActive = true
topLabel.adjustsFontSizeToFitWidth = true
inputBox.topAnchor.constraint(equalTo: topLabel.bottomAnchor, constant: 30).isActive = true
inputBox.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
inputBox.heightAnchor.constraint(equalToConstant: 50).isActive = true
inputBox.widthAnchor.constraint(equalToConstant: 250).isActive = true
btn.topAnchor.constraint(equalTo: inputBox.bottomAnchor, constant: 40).isActive = true
btn.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
let navBarImageView = UIImageView(frame: CGRect(x: 0, y: 0, width: 10, height: 10))
navBarImageView.contentMode = .scaleAspectFit
let navBarImage = UIImage(named: "bzaLogo")
navBarImageView.image = navBarImage
self.navigationController?.navigationItem.titleView = navBarImageView
}
And where I set the image back on the imageView:
func didSelect(image: UIImage?) {
self.imgView.image = image
self.global.uploadFile(imageView: self.uploadIcon.imageView!)
}
And where I add the subviews:
override func viewDidLoad() {
super.viewDidLoad()
currentState = 0
imgView.translatesAutoresizingMaskIntoConstraints = false
topLabel.translatesAutoresizingMaskIntoConstraints = false
inputBox.translatesAutoresizingMaskIntoConstraints = false
btn.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(imgView)
view.addSubview(topLabel)
view.addSubview(inputBox)
view.addSubview(btn)
inputBox.addTarget(self, action: #selector(inputBoxClicked(textField:)), for: .touchDown)
imagePicker = ImagePicker(presentationController: self, delegate: self)
viewModel.state = currentState
inputBox.delegate = self
setupLayout()
}
And here is the error getting thrown:
2019-06-12 13:22:16.635903-0600 bZa[39792:1836482] *** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to activate constraint with anchors and because they have no common ancestor. Does the constraint or its anchors reference items in different view hierarchies? That's illegal.'
Currently the problem is that you add constraints between views who has no comment ancestor so verify that you add
view.addSubview(imgView)
view.addSubview(topLabel)
view.addSubview(inputBox)
view.addSubview(btn)
Also don't forget
imgView.translatesAutoresizingMaskIntoConstraints = false
topLabel.translatesAutoresizingMaskIntoConstraints = false
inputBox.translatesAutoresizingMaskIntoConstraints = false
btn.translatesAutoresizingMaskIntoConstraints = false

heightAnchor.constraint not change height of view

I use this code:
func show(){
view.translatesAutoresizingMaskIntoConstraints = false
view.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
view.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
view.heightAnchor.constraint(equalToConstant: view.frame.height - 300).isActive = true
view.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
}
func hide(){
view.translatesAutoresizingMaskIntoConstraints = false
view.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
view.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
view.heightAnchor.constraint(equalToConstant: view.frame.height + 300).isActive = true
view.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
}
show function works fine, but hide function does not work and heightAnchor does not work.
First declare constraints
var heightArchonWhenShow = view.heightAnchor.constraint(equalToConstant: view.frame.height - 300)
var heightArchonWhenHide = view.heightAnchor.constraint(equalToConstant: view.frame.height + 300)
After init your constraints on ViewDidLoad
func setConstraints(){
view.translatesAutoresizingMaskIntoConstraints = false
view.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
view.topAnchor.constraint(equalTo: view.topAnchor, constant: 0).isActive = true
view.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
heightArchonWhenShow.isActive = true
}
And simple active them , don't overwrite. Like this:
func show(){
heightArchonWhenShow.isActive = true
heightArchonWhenHide.isActive = false
}
func hide(){
heightArchonWhenShow.isActive = false
heightArchonWhenHide.isActive = true
}
If u want u can also animate changes, like that :
func hide(){
heightArchonWhenShow.isActive = false
heightArchonWhenHide.isActive = true
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
}
I recommend you to setup your constraint in a different function like maybe setup() and store them in some variable that you can modify after, I'll show you an example
var constraint: NSLayoutConstraint?
func setup() {
constraint = view.heightAnchor.constraint(equalToConstant: view.frame.height)
}
func show() {
if constraint != nil {
constraint!.constant = constraint!.constant + 300
}
}
func hide() {
if constraint != nil {
constraint!.constant = constraint!.constant - 300
}
}
You need only 1 var
var heightCon = view.heightAnchor.constraint(equalToConstant: view.frame.height - 300)
heightCon.isActive = true
Then manage it's constant value
func showOrHide(_ te:Bool){
heightCon.constant = te ? view.frame.height - 300 : view.frame.height + 300
UIView.animate(withDuration: 0.3) {
self.view.layoutIfNeeded()
}
}