Multiple buttons triggered with one function programmaticaly swift - 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()]
}
}

Related

UITextFields keyboard not appearing in UIScrollview

I have 2 textfields as subViews of a contentView and the contentView is a subView of a scrollView. The textfields appear with no issue.But the problem I am having is when I tap or select the textfield to enter text neither a keyboard appears or the blue cursor, the textfields placeholder remains there. Is there something wrong with my constraints? How can I get the keyboard to appear and edit the text?
class SignInViewController: UIViewController {
private let scrollView: UIScrollView = {
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
return scrollView
}()
private let contentView: UIView = {
let view = UIView()
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
private let emailOrPhoneTextField: UITextField = {
let textField = UITextField()
textField.translatesAutoresizingMaskIntoConstraints = false
textField.placeholder = "Email or Phone Number"
textField.textAlignment = .center
textField.backgroundColor = .red
return textField
}()
private let passwordTextField: UITextField = {
let textField = UITextField()
textField.translatesAutoresizingMaskIntoConstraints = false
textField.placeholder = "Password"
textField.backgroundColor = .yellow
return textField
}()
override func viewDidLoad() {
super.viewDidLoad()
setupScrollView()
setupTextFields()
}
}
extension SignInViewController{
private func setupScrollView(){
view.addSubview(scrollView)
scrollView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
scrollView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
scrollView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
scrollView.addSubview(contentView)
contentView.centerXAnchor.constraint(equalTo: scrollView.centerXAnchor).isActive = true
contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
}
private func setupTextFields(){
contentView.addSubview(emailOrPhoneTextField)
contentView.addSubview(passwordTextField)
emailOrPhoneTextField.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
emailOrPhoneTextField.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 25).isActive = true
emailOrPhoneTextField.widthAnchor.constraint(equalTo: contentView.widthAnchor).isActive = true
emailOrPhoneTextField.heightAnchor.constraint(equalToConstant: 44).isActive = true
passwordTextField.centerXAnchor.constraint(equalTo: contentView.centerXAnchor).isActive = true
passwordTextField.topAnchor.constraint(equalTo: emailOrPhoneTextField.bottomAnchor, constant: 25).isActive = true
passwordTextField.widthAnchor.constraint(equalTo: contentView.widthAnchor).isActive = true
passwordTextField.heightAnchor.constraint(equalToConstant: 44).isActive = true
}
}
Try this and check if it works:
extension ViewController{
private func setupScrollView(){
view.addSubview(scrollView)
scrollView.addSubview(contentView)
contentView.addSubview(emailOrPhoneTextField)
contentView.addSubview(passwordTextField)
NSLayoutConstraint.activate([
scrollView.topAnchor.constraint(equalTo: view.topAnchor),
scrollView.rightAnchor.constraint(equalTo: view.rightAnchor),
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
scrollView.leftAnchor.constraint(equalTo: view.leftAnchor)
])
NSLayoutConstraint.activate([
contentView.topAnchor.constraint(equalTo: scrollView.topAnchor),
contentView.rightAnchor.constraint(equalTo: scrollView.rightAnchor),
contentView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
contentView.leftAnchor.constraint(equalTo: scrollView.leftAnchor),
contentView.widthAnchor.constraint(equalTo: scrollView.widthAnchor),
contentView.heightAnchor.constraint(equalTo: scrollView.heightAnchor)
])
NSLayoutConstraint.activate([
emailOrPhoneTextField.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 50),
emailOrPhoneTextField.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20),
emailOrPhoneTextField.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20),
])
NSLayoutConstraint.activate([
passwordTextField.topAnchor.constraint(equalTo: emailOrPhoneTextField.bottomAnchor, constant: 25),
passwordTextField.rightAnchor.constraint(equalTo: contentView.rightAnchor, constant: -20),
passwordTextField.leftAnchor.constraint(equalTo: contentView.leftAnchor, constant: 20),
])
}
}

Why is my StackView not working? Elements are completely displaced

Hey my StackView is doing nothing, there are two problems:
The first is that the elements on the VC are completely displaced when I turn around the simulator or change the device, so the StackView is not doing what it should do!
The second thing is that the StackView is covering the navigation bar and I don't know how to make it visible.
Can someone help me?
import UIKit
class RegisterViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
let stackView = UIStackView()
var profilePicture = UIButton()
var profileIcon = UIImage()
let usernameTextField = UITextField()
let emailTextField = UITextField()
let passswordTextField = UITextField()
let signInButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.title = "Create an Account"
view.backgroundColor = .white
// SetUp StackView:
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.alignment = .center
stackView.distribution = .fillEqually
stackView.spacing = 50
view.addSubview(stackView)
// SetUp Stack View Constraints:
stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20).isActive = true
stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
//Add Elements
stackView.addArrangedSubview(profilePicture)
stackView.addArrangedSubview(usernameTextField)
stackView.addArrangedSubview(passswordTextField)
stackView.addArrangedSubview(signInButton)
// MARK: - Set-Up View-Elements
// SetUp ProfileIcon:
profileIcon = UIImage(named: "characteer")!
profilePicture.setImage(profileIcon, for: .normal)
profilePicture.imageView?.contentMode = .scaleAspectFill
let cornerRadius: CGFloat
cornerRadius = 75 // half of widht/height
profilePicture.layer.cornerRadius = cornerRadius
profilePicture.layer.masksToBounds = true
profilePicture.layer.borderWidth = 1
profilePicture.layer.borderColor = UIColor.white.cgColor
profilePicture.addTarget(self, action: #selector(handleSelectedPhoto), for: .touchUpInside)
view.addSubview(profilePicture)
profilePicture.translatesAutoresizingMaskIntoConstraints = false
profilePicture.heightAnchor.constraint(equalToConstant: 150).isActive = true
profilePicture.widthAnchor.constraint(equalToConstant: 150).isActive = true
profilePicture.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
profilePicture.topAnchor.constraint(equalTo: view.topAnchor, constant: 110).isActive = true
// SetUp UsernameTextfield:
usernameTextField.backgroundColor = .white
usernameTextField.attributedPlaceholder = NSAttributedString(string: "Username", attributes: [NSAttributedString.Key.foregroundColor: UIColor.lightGray])
usernameTextField.textAlignment = NSTextAlignment.center
usernameTextField.layer.cornerRadius = 8
usernameTextField.layer.borderWidth = 1
usernameTextField.layer.borderColor = UIColor.lightGray.cgColor
self.view.addSubview(usernameTextField)
let username = usernameTextField.text
usernameTextField.translatesAutoresizingMaskIntoConstraints = false
usernameTextField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true
usernameTextField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true
usernameTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
usernameTextField.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
// SetUpEmailTextfield:
emailTextField.backgroundColor = .white
emailTextField.attributedPlaceholder = NSAttributedString(string: "Email", attributes: [NSAttributedString.Key.foregroundColor: UIColor.lightGray])
emailTextField.textAlignment = NSTextAlignment.center
emailTextField.layer.cornerRadius = 8
emailTextField.layer.borderWidth = 1
emailTextField.layer.borderColor = UIColor.lightGray.cgColor
self.view.addSubview(emailTextField)
emailTextField.translatesAutoresizingMaskIntoConstraints = false
emailTextField.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true
emailTextField.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true
emailTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
emailTextField.topAnchor.constraint(equalTo: usernameTextField.bottomAnchor, constant: 20).isActive = true
```
Just I set for profilePicture and usernameTextField but for others are same it works. Wrong side of your code is about constraint and you add object two different views. There is a solution.
let stackView = UIStackView()
var profilePicture = UIButton()
var profileIcon = UIImage()
let usernameTextField = UITextField()
let emailTextField = UITextField()
let passswordTextField = UITextField()
let signInButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.title = "Create an Account"
view.backgroundColor = .white
// SetUp StackView:
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.alignment = .center
stackView.distribution = .fillEqually
stackView.spacing = 50
view.addSubview(stackView)
// SetUp Stack View Constraints:
stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20).isActive = true
stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 20).isActive = true
stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -20).isActive = true
//Add Elements
stackView.addArrangedSubview(profilePicture)
stackView.addArrangedSubview(usernameTextField)
// MARK: - Set-Up View-Elements
// SetUp ProfileIcon:
profileIcon = UIImage(named: "characteer")!
profilePicture.setImage(profileIcon, for: .normal)
profilePicture.imageView?.contentMode = .scaleAspectFill
let cornerRadius: CGFloat
cornerRadius = 75 // half of widht/height
profilePicture.layer.cornerRadius = cornerRadius
profilePicture.layer.masksToBounds = true
profilePicture.layer.borderWidth = 1
profilePicture.layer.borderColor = UIColor.white.cgColor
//profilePicture.addTarget(self, action: #selector(handleSelectedPhoto), for: .touchUpInside)
profilePicture.translatesAutoresizingMaskIntoConstraints = false
profilePicture.heightAnchor.constraint(equalToConstant: 150).isActive = true
profilePicture.widthAnchor.constraint(equalToConstant: 150).isActive = true
// SetUp UsernameTextfield:
usernameTextField.backgroundColor = .white
usernameTextField.attributedPlaceholder = NSAttributedString(string: "Username", attributes: [NSAttributedString.Key.foregroundColor: UIColor.lightGray])
usernameTextField.textAlignment = NSTextAlignment.center
usernameTextField.layer.cornerRadius = 8
usernameTextField.layer.borderWidth = 1
usernameTextField.layer.borderColor = UIColor.lightGray.cgColor
let username = usernameTextField.text
usernameTextField.translatesAutoresizingMaskIntoConstraints = false
usernameTextField.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width-40).isActive = true
usernameTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
You're doing a number of things wrong... It would be well worth your while to go through a few tutorials on auto-layout and using UIStackView.
First, if you add a view (image view, text field, label, button, etc) to a stack view, do not also give those views position constraints. That's what the stack view is doing.
Second, once you've added a view:
stackView.addArrangedSubview(profilePicture)
do not then add it as a subview like this:
view.addSubview(profilePicture)
Doing that will remove profilePicture from the stack view.
Take a look through your code -- review the comments where I've made changes:
class RegisterViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
let stackView = UIStackView()
var profilePicture = UIButton()
var profileIcon = UIImage()
let usernameTextField = UITextField()
let emailTextField = UITextField()
let passswordTextField = UITextField()
let signInButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.title = "Create an Account"
view.backgroundColor = .white
// SetUp StackView:
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.alignment = .center
// distribution should be .fill NOT .fillEqually
stackView.distribution = .fill
stackView.spacing = 50
view.addSubview(stackView)
// SetUp Stack View Constraints:
stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: 20).isActive = true
stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
//Add Elements
stackView.addArrangedSubview(profilePicture)
stackView.addArrangedSubview(usernameTextField)
stackView.addArrangedSubview(emailTextField)
stackView.addArrangedSubview(passswordTextField)
stackView.addArrangedSubview(signInButton)
// MARK: - Set-Up View-Elements
// SetUp ProfileIcon:
//profileIcon = UIImage(named: "characteer")!
profileIcon = UIImage(named: "pro1")!
profilePicture.setImage(profileIcon, for: .normal)
profilePicture.imageView?.contentMode = .scaleAspectFill
let cornerRadius: CGFloat
cornerRadius = 75 // half of widht/height
profilePicture.layer.cornerRadius = cornerRadius
profilePicture.layer.masksToBounds = true
profilePicture.layer.borderWidth = 1
profilePicture.layer.borderColor = UIColor.white.cgColor
//profilePicture.addTarget(self, action: #selector(handleSelectedPhoto), for: .touchUpInside)
// NO - it's already in the stack view
//view.addSubview(profilePicture)
// Set Only Width and Height - position is managed by the stack view
profilePicture.heightAnchor.constraint(equalToConstant: 150).isActive = true
profilePicture.widthAnchor.constraint(equalToConstant: 150).isActive = true
// SetUp UsernameTextfield:
usernameTextField.backgroundColor = .white
usernameTextField.attributedPlaceholder = NSAttributedString(string: "Username", attributes: [NSAttributedString.Key.foregroundColor: UIColor.lightGray])
usernameTextField.textAlignment = NSTextAlignment.center
usernameTextField.layer.cornerRadius = 8
usernameTextField.layer.borderWidth = 1
usernameTextField.layer.borderColor = UIColor.lightGray.cgColor
// NO - it's already in the stack view
// self.view.addSubview(usernameTextField)
let username = usernameTextField.text
// Set Only Width and Height - position is managed by the stack view
usernameTextField.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -40).isActive = true
usernameTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
// SetUpEmailTextfield:
emailTextField.backgroundColor = .white
emailTextField.attributedPlaceholder = NSAttributedString(string: "Email", attributes: [NSAttributedString.Key.foregroundColor: UIColor.lightGray])
emailTextField.textAlignment = NSTextAlignment.center
emailTextField.layer.cornerRadius = 8
emailTextField.layer.borderWidth = 1
emailTextField.layer.borderColor = UIColor.lightGray.cgColor
// NO - it's already in the stack view
// self.view.addSubview(emailTextField)
// Set Only Width and Height - position is managed by the stack view
emailTextField.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -40).isActive = true
emailTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
// SetUp PasswordTextfield:
passswordTextField.backgroundColor = .white
passswordTextField.attributedPlaceholder = NSAttributedString(string: "Password", attributes: [NSAttributedString.Key.foregroundColor: UIColor.lightGray])
passswordTextField.textAlignment = NSTextAlignment.center
passswordTextField.layer.cornerRadius = 8
passswordTextField.layer.borderWidth = 1
passswordTextField.layer.borderColor = UIColor.lightGray.cgColor
// NO - it's already in the stack view
// self.view.addSubview(emailTextField)
// Set Only Width and Height - position is managed by the stack view
passswordTextField.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -40).isActive = true
passswordTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
signInButton.setTitle("Sign In", for: [])
signInButton.backgroundColor = .blue
// Set Only Width and Height - position is managed by the stack view
signInButton.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -40).isActive = true
signInButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
}
}
Of course, using that layout - where you specified vertical spacing between the elements of 50-pts, and you've set explicit heights for each element, you'll likely find that it doesn't "fit quite right" across different devices / screen sizes.
So, as pointed out to you in your previous question here: Why is my VC displaced after changing the Simulator? AutoLayout - you probably want to change the stack view's Distribution to Equal Spacing and add a bottom constraint:
stackView.distribution = .equalSpacing
stackView.spacing = 0
stackView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -20).isActive = true
That may or may not give you exactly what you want, but it's a starting point.
I think there is a problem about your constraint.
profilePicture.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
profilePicture.topAnchor.constraint(equalTo: view.topAnchor, constant: 110).isActive = true
are trying to center of the screen but they are inside of stack view. Also you have to give a static height to stack view on this scenario.

UIStackView with custom size elements and item in the center - Swift - Programmatically

I want to set a UIStackView with 3 views to the bottom of my so that the centre view is positioned in the centre and the other views are adjusted accordingly, I want also to be able to set the width and height anchors for all 3 views.
This is the desired outcome:
This is what I'm getting:
This is the code I'm using:
bottomStackView = UIStackView(arrangedSubviews: [pickerView, downloadContentButton, shareButton])
bottomStackView.alignment = .center
bottomStackView.distribution = .fill
bottomStackView.axis = .horizontal
bottomStackView.spacing = 5
bottomStackView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(bottomStackView)
bottomStackView.anchor(top: nil, leading: view.leadingAnchor, bottom: view.safeAreaLayoutGuide.bottomAnchor, trailing: view.trailingAnchor)
bottomStackView.heightAnchor.constraint(equalToConstant: 150).isActive = true
bottomStackView.widthAnchor.constraint(equalTo: view.widthAnchor).isActive = true
pickerView.heightAnchor.constraint(equalToConstant: 120).isActive = true
shareButton.heightAnchor.constraint(equalToConstant: 150).isActive = true
shareButton.widthAnchor.constraint(equalTo: pickerView.widthAnchor).isActive = true
downloadContentButton.heightAnchor.constraint(equalToConstant: 30).isActive = true
downloadContentButton.widthAnchor.constraint(equalToConstant: 30).isActive = true
shareButton.widthAnchor.constraint(equalToConstant: 80).isActive = true
shareButton.heightAnchor.constraint(equalToConstant: 80).isActive = true
I think you are after this kind of thing:
Or, if we get wider:
If that's the idea, then one key mistake is when you say:
bottomStackView.distribution = .fill
You actually want .equalDistribution. To demonstrate, I created the example entirely in code, so you can see all the settings:
let sv = UIStackView()
sv.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(sv)
sv.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 20).isActive = true
sv.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -20).isActive = true
sv.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -20).isActive = true
sv.heightAnchor.constraint(equalToConstant: 160).isActive = true
sv.distribution = .equalSpacing
sv.alignment = .center
let v1 = UIView()
v1.translatesAutoresizingMaskIntoConstraints = false
v1.widthAnchor.constraint(equalToConstant: 120).isActive = true
v1.heightAnchor.constraint(equalToConstant: 150).isActive = true
v1.backgroundColor = .red
sv.addArrangedSubview(v1)
let v2 = UIView()
v2.translatesAutoresizingMaskIntoConstraints = false
v2.widthAnchor.constraint(equalToConstant: 80).isActive = true
v2.heightAnchor.constraint(equalToConstant: 80).isActive = true
v2.backgroundColor = .yellow
sv.addArrangedSubview(v2)
let v3 = UIView()
v3.translatesAutoresizingMaskIntoConstraints = false
v3.widthAnchor.constraint(equalToConstant: 120).isActive = true
v3.heightAnchor.constraint(equalToConstant: 150).isActive = true
v3.backgroundColor = .blue
sv.addArrangedSubview(v3)

Adding Image to view in swift

I am trying to add an image to a subview. but whenever I run a simulation I cant see the image while I have label that shows up on the same view
let View:UIView = UIView()
let CheckImageView:UIImageView = UIImageView(image: UIImage(named: "Checked 1"))
view.addSubview(View)
View.backgroundColor = .white
View.translatesAutoresizingMaskIntoConstraints = false
View.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor,constant: -20).isActive = true
View.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 20).isActive = true
View.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor,constant: 0).isActive = true
View.heightAnchor.constraint(equalToConstant: 200).isActive = true
View.layer.cornerRadius = 25
View.layer.shadowOpacity = 0.15
View.layer.shadowRadius = 20
View.layer.shadowOffset = .zero
View.layer.shadowColor = UIColor.black.cgColor
View.addSubview(CheckImageView)
CheckImageView.translatesAutoresizingMaskIntoConstraints = false
CheckImageView.heightAnchor.constraint(equalTo: CheckImageView.widthAnchor).isActive = true
CheckImageView.topAnchor.constraint(equalTo: View.topAnchor, constant: 30).isActive = true
CheckImageView.centerXAnchor.constraint(equalTo: View.centerXAnchor).isActive = true
CheckImageView.widthAnchor.constraint(equalToConstant: 50).isActive = true
It seems like your image size is smaller than expected.
Try to change your image width Anchor
CheckImageView.widthAnchor.constraint(equalToConstant: 100).isActive = true

UIImage Aspect Fill and clipsToBounds

I want to set an image to a UIImage, but as soon as I set it it the UIImageView gets bigger and goes over other elements.
There is a solution provided here:
Crop UIImage to fit a frame image
But I can not get it to work, I set the properties like in the solution provided.
Maybe somebody can have a look and help me:
Without setting the image:
After setting the image:
class Cell: UICollectionViewCell, CollectionViewCellConfigurable {
var image = UIImageView()
var dateDay = UILabel()
var dateMonth = UILabel()
var title = UILabel()
lazy private var dateContainer: UIView = {
let v = UIView()
v.sv(dateDay, dateMonth)
dateDay.heightAnchor.constraint(equalTo: self.dateMonth.heightAnchor, multiplier: 1).isActive = true
dateDay.leadingAnchor.constraint(equalTo: v.leadingAnchor, constant: 5).isActive = true
dateDay.trailingAnchor.constraint(equalTo: v.trailingAnchor, constant: -5).isActive = true
dateDay.topAnchor.constraint(equalTo: v.topAnchor, constant: 15).isActive = true
dateDay.bottomAnchor.constraint(equalTo: dateMonth.topAnchor, constant: -5).isActive = true
dateMonth.heightAnchor.constraint(equalTo: self.dateDay.heightAnchor, multiplier: 1).isActive = true
dateMonth.leadingAnchor.constraint(equalTo: v.leadingAnchor, constant: 5).isActive = true
dateMonth.trailingAnchor.constraint(equalTo: v.trailingAnchor, constant: -5).isActive = true
dateMonth.topAnchor.constraint(equalTo: dateDay.bottomAnchor, constant: 5).isActive = true
// dateMonth.bottomAnchor.constraint(greaterThanOrEqualTo: v.bottomAnchor, constant: -5).isActive = true
return v
}()
lazy private var container: UIView = {
return UIView()
}()
func configureCellAtIndexPath(item: Journaling) {
self.image.image = UIImage.baliBeach
self.image.backgroundColor = .green
self.dateDay.text = "16"
self.dateMonth.text = "May"
self.title.text = "Text visible"
}
override init(frame: CGRect) {
super.init(frame:frame)
setUpLayout()
additionalSetUp()
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func additionalSetUp() {
backgroundColor = .clear
let colorText: UIColor = .grau
dateDay.textColor = colorText
dateMonth.textColor = colorText
title.textColor = colorText
dateDay.textAlignment = .center
dateMonth.textAlignment = .center
title.textAlignment = .center
image.contentMode = .scaleAspectFill
image.clipsToBounds = true
image.autoresizesSubviews = true
}
func setUpLayout() {
sv(dateContainer, container)
container.sv(image,title)
dateContainer.widthAnchor.constraint(equalToConstant: 45).isActive = true
// dateContainer.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 0.15).isActive = true
dateContainer.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 0).isActive = true
dateContainer.trailingAnchor.constraint(equalTo: container.leadingAnchor, constant: 0).isActive = true
dateContainer.topAnchor.constraint(equalTo: self.topAnchor, constant: 0).isActive = true
dateContainer.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true
// container.widthAnchor.constraint(equalTo: self.widthAnchor, multiplier: 0.5).isActive = true
container.leadingAnchor.constraint(equalTo: dateContainer.trailingAnchor, constant: 0).isActive = true
container.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: 0).isActive = true
container.topAnchor.constraint(equalTo: self.topAnchor, constant: 0).isActive = true
container.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: 0).isActive = true
image.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 5).isActive = true
image.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: -5).isActive = true
image.topAnchor.constraint(equalTo: self.topAnchor, constant: 15).isActive = true
image.bottomAnchor.constraint(equalTo: title.topAnchor, constant: -5).isActive = true
title.leadingAnchor.constraint(equalTo: container.leadingAnchor, constant: 0).isActive = true
title.trailingAnchor.constraint(equalTo: container.trailingAnchor, constant: 0).isActive = true
title.topAnchor.constraint(equalTo: image.bottomAnchor, constant: 5).isActive = true
title.bottomAnchor.constraint(equalTo: container.bottomAnchor, constant: 0).isActive = true
}
}
You need to higher vertical compression priority of the title label as the imageView is equal it = 750 , so it occupies the space
title.setContentCompressionResistancePriority(UILayoutPriority(rawValue: 751), for: .vertical)