I have built an app and discovered that there is a memory leak. When I segue from my home page view controller to any other view controller and then back to my homepage, the memory grows by a small amount each time. From everything I can tell, this is due to a problem with my home page view controller. In my ViewController class (the class for my home page) I set constraints programmatically to fit every iOS device. Could this be a cause of my memory leak? how could I clear these constraints once I segue to a new view controller? The code for my ViewController class (homepage) can be seen below.
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var GoButton: UIButton!
#IBOutlet weak var Background: UIImageView!
#IBOutlet weak var SettingsButton: UIButton!
#IBOutlet weak var aboutButton: UIButton!
#IBAction func toFlashcards(_ sender: Any) {
self.Background.image = nil
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func viewWillLayoutSubviews() {
if(view.frame.size.width == 375 || view.frame.size.width == 812)&&(view.frame.size.height == 375 || view.frame.size.height == 812){
iphoneX()
}
if(view.frame.size.width == 320 || view.frame.size.width == 568)&&(view.frame.size.height == 320 || view.frame.size.height == 568){
iphoneSE()
}
if(view.frame.size.width == 414 || view.frame.size.width == 736)&&(view.frame.size.height == 414 || view.frame.size.height == 736){
iphone8Plus()
}
if(view.frame.size.width == 375 || view.frame.size.width == 667)&&(view.frame.size.height == 375 || view.frame.size.height == 667){
iphone8()
}
if(view.frame.size.width == 1024 || view.frame.size.width == 1366)&&(view.frame.size.height == 1024 || view.frame.size.height == 1366){
ipadPro()
}
if(view.frame.size.width == 1112 || view.frame.size.width == 834)&&(view.frame.size.height == 1112 || view.frame.size.height == 834){
ipad10inch()
}
if(view.frame.size.width == 768 || view.frame.size.width == 1024)&&(view.frame.size.height == 768 || view.frame.size.height == 1024){
ipad9inch()
}
}
func iphoneX(){
Background.contentMode = .scaleToFill
Background.image = #imageLiteral(resourceName: "iphoneXBackground")
GoButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 50)
GoButton.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: 220).isActive = true
GoButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 150).isActive = true
view.bottomAnchor.constraint(equalTo: GoButton.bottomAnchor, constant: 88).isActive = true
SettingsButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 30)
view.trailingAnchor.constraint(equalTo: SettingsButton.trailingAnchor, constant: 575).isActive = true
SettingsButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 90).isActive = true
SettingsButton.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: 139).isActive = true
aboutButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 30)
view.bottomAnchor.constraint(equalTo: aboutButton.bottomAnchor, constant: 34).isActive = true
aboutButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 300).isActive = true
aboutButton.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: 280).isActive = true
}
func iphoneSE(){
Background.contentMode = .scaleToFill
Background.image = #imageLiteral(resourceName: "iphoneXBackground")
view.bottomAnchor.constraint(equalTo: GoButton.bottomAnchor, constant: 75).isActive = true
GoButton.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: 195).isActive = true
GoButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 95).isActive = true
view.trailingAnchor.constraint(equalTo: SettingsButton.trailingAnchor, constant: 400).isActive = true
SettingsButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 60).isActive = true
SettingsButton.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: 120).isActive = true
view.bottomAnchor.constraint(equalTo: aboutButton.bottomAnchor, constant:40).isActive = true
aboutButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 205).isActive = true
aboutButton.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: 245).isActive = true
aboutButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 25)
GoButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 45)
SettingsButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 25)
}
func iphone8Plus(){
Background.contentMode = .scaleToFill
Background.image = #imageLiteral(resourceName: "iphoneXBackground")
GoButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 50)
view.bottomAnchor.constraint(equalTo: GoButton.bottomAnchor, constant: 94).isActive = true
GoButton.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: 245).isActive = true
GoButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 130).isActive = true
SettingsButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 30)
view.trailingAnchor.constraint(equalTo: SettingsButton.trailingAnchor, constant: 525).isActive = true
SettingsButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 75).isActive = true
SettingsButton.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: 157).isActive = true
aboutButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 32)
view.bottomAnchor.constraint(equalTo: aboutButton.bottomAnchor, constant: 46).isActive = true
aboutButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 267).isActive = true
aboutButton.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: 315).isActive = true
}
func iphone8(){
Background.contentMode = .scaleToFill
Background.image = #imageLiteral(resourceName: "iphoneXBackground")
GoButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 50)
view.bottomAnchor.constraint(equalTo: GoButton.bottomAnchor, constant: 85).isActive = true
GoButton.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: 215).isActive = true
GoButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 112).isActive = true
SettingsButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 30)
view.trailingAnchor.constraint(equalTo: SettingsButton.trailingAnchor, constant: 465).isActive = true
SettingsButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 65).isActive = true
SettingsButton.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: 139).isActive = true
aboutButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 30)
view.bottomAnchor.constraint(equalTo: aboutButton.bottomAnchor, constant: 35).isActive = true
aboutButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 239).isActive = true
aboutButton.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: 284).isActive = true
}
func ipadPro(){
Background.contentMode = .scaleToFill
GoButton.frame.size.width = 170
GoButton.frame.size.height = 170
GoButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 100)
view.bottomAnchor.constraint(equalTo: GoButton.bottomAnchor, constant: 209).isActive = true
view.trailingAnchor.constraint(equalTo: GoButton.trailingAnchor, constant: 961).isActive = true
GoButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 200).isActive = true
SettingsButton.frame.size.width = 220
SettingsButton.frame.size.height = 147
SettingsButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 60)
view.trailingAnchor.constraint(equalTo: SettingsButton.trailingAnchor, constant: 935).isActive = true
SettingsButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 118).isActive = true
SettingsButton.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: 420).isActive = true
aboutButton.frame.size.width = 222
aboutButton.frame.size.height = 129
aboutButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 60)
view.trailingAnchor.constraint(equalTo: aboutButton.trailingAnchor, constant: 667).isActive = true
aboutButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 445).isActive = true
view.bottomAnchor.constraint(equalTo: aboutButton.bottomAnchor, constant: 94).isActive = true
}
func ipad10inch(){
Background.contentMode = .scaleToFill
GoButton.frame.size.width = 220
GoButton.frame.size.height = 110
GoButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 82)
view.bottomAnchor.constraint(equalTo: GoButton.bottomAnchor, constant: 174).isActive = true
view.trailingAnchor.constraint(equalTo: GoButton.trailingAnchor, constant: 810).isActive = true
GoButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 161).isActive = true
SettingsButton.frame.size.width = 220
SettingsButton.frame.size.height = 110
SettingsButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 55)
view.trailingAnchor.constraint(equalTo: SettingsButton.trailingAnchor, constant: 737).isActive = true
SettingsButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 92).isActive = true
SettingsButton.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: 335).isActive = true
aboutButton.frame.size.width = 200
aboutButton.frame.size.height = 108
aboutButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 55)
view.trailingAnchor.constraint(equalTo: aboutButton.trailingAnchor, constant: 515).isActive = true
aboutButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 338).isActive = true
view.bottomAnchor.constraint(equalTo: aboutButton.bottomAnchor, constant: 80).isActive = true
}
func ipad9inch(){
Background.contentMode = .scaleToFill
GoButton.frame.size.width = 220
GoButton.frame.size.height = 110
GoButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 82)
view.bottomAnchor.constraint(equalTo: GoButton.bottomAnchor, constant: 160).isActive = true
view.trailingAnchor.constraint(equalTo: GoButton.trailingAnchor, constant: 738).isActive = true
GoButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 155).isActive = true
SettingsButton.frame.size.width = 220
SettingsButton.frame.size.height = 110
SettingsButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 55)
view.trailingAnchor.constraint(equalTo: SettingsButton.trailingAnchor, constant: 700).isActive = true
SettingsButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 85).isActive = true
SettingsButton.topAnchor.constraint(equalTo: topLayoutGuide.bottomAnchor, constant: 305).isActive = true
aboutButton.frame.size.width = 200
aboutButton.frame.size.height = 108
aboutButton.titleLabel?.font = UIFont.boldSystemFont(ofSize: 55)
view.trailingAnchor.constraint(equalTo: aboutButton.trailingAnchor, constant: 495).isActive = true
aboutButton.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 312).isActive = true
view.bottomAnchor.constraint(equalTo: aboutButton.bottomAnchor, constant: 65).isActive = true
}
}
Related
I have three views on the bottom of the view. I'm trying to make them have the same size and the size can be resized automatically depending on the size of the container view. I'd like to do it programmatically.
Here's how I want them to look
Here's how it looks by my current code
import UIKit
class ViewController: UIViewController {
var view1 = UIView(frame: CGRect(x: 100, y: 100, width: 100, height: 100))
var view2 = UIView(frame: CGRect(x: 300, y: 300, width: 50, height: 50))
var view3 = UIView(frame: CGRect(x: 400, y: 500, width: 70, height: 70))
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(view1)
view.addSubview(view2)
view.addSubview(view3)
view1.backgroundColor = .orange
view2.backgroundColor = .black
view3.backgroundColor = .gray
view1.translatesAutoresizingMaskIntoConstraints = false
view2.translatesAutoresizingMaskIntoConstraints = false
view3.translatesAutoresizingMaskIntoConstraints = false
// view1.topAnchor.constraint(equalTo: view.topAnchor, constant: 10).isActive = true
view1.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -10).isActive = true
view1.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: -10).isActive = true
view1.widthAnchor.constraint(equalTo: view.widthAnchor, constant: view.frame.size.width*0.01).isActive = true
view2.heightAnchor.constraint(equalToConstant: view.frame.size.height*0.1).isActive = true
//view2.topAnchor.constraint(equalTo: view.topAnchor, constant: 10).isActive = true
view2.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -10).isActive = true
view2.leadingAnchor.constraint(equalTo: view1.leadingAnchor, constant: view.frame.size.width*(2/3)).isActive = true
view2.widthAnchor.constraint(equalTo: view1.widthAnchor, constant: 0).isActive = true
view2.heightAnchor.constraint(equalTo: view1.heightAnchor, constant: 0).isActive = true
// view3.topAnchor.constraint(equalTo: view.topAnchor, constant: 10).isActive = true
view3.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -10).isActive = true
view3.leadingAnchor.constraint(equalTo: view2.leadingAnchor, constant: 10).isActive = true
view3.widthAnchor.constraint(equalTo: view2.widthAnchor, constant: 0).isActive = true
view3.heightAnchor.constraint(equalTo: view2.heightAnchor, constant: 0).isActive = true
}
}
Here, you can use the concept of UIStackView. Here, you can get your desired output using the following code(sample demo)
import UIKit
class ViewController: UIViewController {
var view1 = UIView()
var view2 = UIView()
var view3 = UIView()
override func viewDidLoad() {
super.viewDidLoad()
let stackView = UIStackView(arrangedSubviews: [view1, view2, view3])
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .horizontal
stackView.distribution = .fillEqually
stackView.spacing = 50 //add amount of space between your views
view.addSubview(stackView)
view1.backgroundColor = .orange
view2.backgroundColor = .black
view3.backgroundColor = .gray
stackView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -10).isActive = true
stackView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor, constant: 10).isActive = true
stackView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor, constant: -10).isActive = true
stackView.heightAnchor.constraint(equalToConstant: view.frame.size.height*0.1).isActive = true
}
}
For more about UIStackView with example check this: https://nshipster.com/uistackview
Output:
Welcome to Stackoverflow. Please read on UIStackView. And by using that stackView, you can easily achieve what you want to achieve in your screenshot.
import UIKit
class ViewController: UIViewController {
var view1 = UIView()
var view2 = UIView()
var view3 = UIView()
lazy var stackView: UIStackView = {
return UIStackView(arrangedSubviews: [
self.view1,
self.view2,
self.view3
])
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(stackView)
view1.backgroundColor = .orange
view2.backgroundColor = .black
view3.backgroundColor = .gray
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .horizontal
stackView.distribution = .equalSpacing
stackView.alignment = .center
view1.translatesAutoresizingMaskIntoConstraints = false
view2.translatesAutoresizingMaskIntoConstraints = false
view3.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
self.stackView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 16),
self.stackView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -16),
self.stackView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -16),
self.view1.heightAnchor.constraint(equalToConstant: view.frame.size.height*0.1),
self.view1.widthAnchor.constraint(equalToConstant: view.frame.size.height*0.1),
self.view2.heightAnchor.constraint(equalToConstant: view.frame.size.height*0.1),
self.view2.widthAnchor.constraint(equalToConstant: view.frame.size.height*0.1),
self.view3.heightAnchor.constraint(equalToConstant: view.frame.size.height*0.1),
self.view3.widthAnchor.constraint(equalToConstant: view.frame.size.height*0.1)
])
}
}
RESULT:
I am having problems to constrain my items inside my UIScrollView, to be more specific trailing - anchors are behaving weird:
As you can see trailing-anchors are not the same as leading-anchors..
These are my constrains:
scrollView.topAnchor.constraint(equalTo: view.topAnchor, constant: 130).isActive = true
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30).isActive = true
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
emailTextField.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
emailTextField.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
emailTextField.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
emailTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
anzeigeNameTextField.topAnchor.constraint(equalTo: emailTextField.topAnchor, constant: 80).isActive = true
anzeigeNameTextField.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
anzeigeNameTextField.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
anzeigeNameTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
wishlistHandleTextField.topAnchor.constraint(equalTo: anzeigeNameTextField.topAnchor, constant: 80).isActive = true
wishlistHandleTextField.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
wishlistHandleTextField.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
wishlistHandleTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
passwordTextField.topAnchor.constraint(equalTo: wishlistHandleTextField.topAnchor, constant: 80).isActive = true
passwordTextField.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
passwordTextField.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
passwordTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
eyeButtonOne.centerYAnchor.constraint(equalTo: passwordTextField.centerYAnchor, constant: 10).isActive = true
eyeButtonOne.trailingAnchor.constraint(equalTo: passwordTextField.trailingAnchor).isActive = true
passwordWiederholenTextField.topAnchor.constraint(equalTo: passwordTextField.topAnchor, constant: 80).isActive = true
passwordWiederholenTextField.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
passwordWiederholenTextField.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
passwordWiederholenTextField.heightAnchor.constraint(equalToConstant: 50).isActive = true
eyeButtonTwo.centerYAnchor.constraint(equalTo: passwordWiederholenTextField.centerYAnchor, constant: 10).isActive = true
eyeButtonTwo.trailingAnchor.constraint(equalTo: passwordWiederholenTextField.trailingAnchor).isActive = true
documentsLabel.topAnchor.constraint(equalTo: passwordWiederholenTextField.topAnchor, constant: 80).isActive = true
documentsLabel.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
documentsLabel.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
documentsLabel.heightAnchor.constraint(equalToConstant: 50).isActive = true
signUpButton.topAnchor.constraint(equalTo: documentsLabel.topAnchor, constant: 80).isActive = true
signUpButton.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
signUpButton.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
signUpButton.heightAnchor.constraint(equalToConstant: 50).isActive = true
What am I doing wrong? Do I have to constraint differently inside a UIScrollView? And if so, how and why?
create sample code for you. Hope it will be useful
and read this link for better sene below code: scrollView with auto layout
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.view.backgroundColor = UIColor.red.withAlphaComponent(0.5)
// create scrollView
let scrollView = UIScrollView.init()
scrollView.translatesAutoresizingMaskIntoConstraints = false
scrollView.backgroundColor = UIColor.blue.withAlphaComponent(0.5)
self.view.addSubview(scrollView)
scrollView.topAnchor.constraint(equalTo: self.view.topAnchor).isActive = true
scrollView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor).isActive = true
// create tempView inside scrollView for use autolayout with scrollView
let tempView = UIView.init()
tempView.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(tempView)
tempView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
tempView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
tempView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
tempView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
// is important, just for use autolayout inside scrollView with scroll if content large screen
tempView.widthAnchor.constraint(equalTo: self.view.widthAnchor).isActive = true
let heightConstraint = tempView.heightAnchor.constraint(equalTo: self.view.heightAnchor)
heightConstraint.priority = .init(250)
heightConstraint.isActive = true
// create sample UI inside tempView
let emailTextField = UITextField.init()
emailTextField.translatesAutoresizingMaskIntoConstraints = false
emailTextField.backgroundColor = .white
tempView.addSubview(emailTextField)
emailTextField.topAnchor.constraint(equalTo: tempView.topAnchor, constant: 200).isActive = true
emailTextField.leadingAnchor.constraint(equalTo: tempView.leadingAnchor, constant: 50).isActive = true
emailTextField.trailingAnchor.constraint(equalTo: tempView.trailingAnchor, constant: -50).isActive = true
emailTextField.heightAnchor.constraint(equalToConstant: 100).isActive = true
}
screenShot
uiview needed to be subview of scrollview, after that you can embed you're elements into uiview
I'm currently trying to achieve a Shimmer effect in Swift. To do that I create a gray UIView, and another on top of it with an effect.
The problem is that I'm writing the same code twice...
let profileShimmerView = UIView()
profileShimmerView.backgroundColor = whiteClear
profileShimmerView.layer.cornerRadius = 20
profileShimmerView.clipsToBounds = true
let profileView = UIView()
profileView.backgroundColor = grayClear
profileView.layer.cornerRadius = 20
profileView.clipsToBounds = true
self.addSubview(profileView)
self.addSubview(profileShimmerView)
profileShimmerView.translatesAutoresizingMaskIntoConstraints = false
profileShimmerView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 45).isActive = true
profileShimmerView.topAnchor.constraint(equalTo: self.topAnchor, constant: 15).isActive = true
profileShimmerView.widthAnchor.constraint(equalToConstant: 40).isActive = true
profileShimmerView.heightAnchor.constraint(equalToConstant: 40).isActive = true
profileView.translatesAutoresizingMaskIntoConstraints = false
profileView.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 45).isActive = true
profileView.topAnchor.constraint(equalTo: self.topAnchor, constant: 15).isActive = true
profileView.widthAnchor.constraint(equalToConstant: 40).isActive = true
profileView.heightAnchor.constraint(equalToConstant: 40).isActive = true
Is there a more simple way to achieve that?
You can create a function
func shared(color : UIColor)->UIView {
let v = UIView()
v.backgroundColor = color
v.layer.cornerRadius = 20
v.clipsToBounds = true
self.addSubview(v)
v.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
v.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 45),
v.topAnchor.constraint(equalTo: self.topAnchor, constant: 15),
v.widthAnchor.constraint(equalToConstant: 40),
v.heightAnchor.constraint(equalToConstant: 40)
])
return v
}
I have some problems with UIScrollView. Trying to add scrollable are for some sliders but nothing is working. I think it is because I'm using anchors for layout. Please, explain to me, what I'm doing wrong. Eventually, I need to have a scrollable area for iPhone SE version that user can use sliders.
Here is my code, where I'm creating scrollview and adding all the sliders on it and putting anchors in relation with scrollview.
//MARK: Scroll View
scrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: view.bounds.width, height: 812))
scrollView.backgroundColor = .gray
scrollView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(scrollView)
scrollView.topAnchor.constraint(equalTo: collectionView.bottomAnchor, constant: 0).isActive = true
scrollView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 0).isActive = true
scrollView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: 0).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0).isActive = true
scrollView.contentSize = CGSize(width: view.bounds.width, height: 812)
//MARK: Brightness Label
brightnessLabel = UILabel()
brightnessLabel.text = "Brightness"
brightnessLabel.font = UIFont(name: "Avenir", size: 14)
brightnessLabel.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(brightnessLabel)
brightnessLabel.topAnchor.constraint(equalTo: collectionView.bottomAnchor, constant: 10).isActive = true
brightnessLabel.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: view.bounds.width / -2).isActive = true
brightnessLabel.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 10).isActive = true
brightnessLabel.heightAnchor.constraint(equalToConstant: 25).isActive = true
//MARK: Brightness Slider
brightnessSlider = UISlider()
brightnessSlider.setThumbImage(UIImage(named: "sliderThumb"), for: .normal)
brightnessSlider.tintColor = .black
brightnessSlider.minimumValue = 0
brightnessSlider.maximumValue = 100
brightnessSlider.translatesAutoresizingMaskIntoConstraints = false
brightnessSlider.setValue(50, animated: true)
scrollView.addSubview(brightnessSlider)
brightnessSlider.topAnchor.constraint(equalTo: brightnessLabel.bottomAnchor, constant: 5).isActive = true
brightnessSlider.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -10).isActive = true
brightnessSlider.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 10).isActive = true
brightnessSlider.heightAnchor.constraint(equalToConstant: 25).isActive = true
//MArk: Brightness Value Label
brightnessValueLabel = UILabel()
brightnessValueLabel.text = "50"
brightnessValueLabel.font = UIFont(name: "Avenir", size: 14)
brightnessValueLabel.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(brightnessValueLabel)
brightnessValueLabel.topAnchor.constraint(equalTo: collectionView.bottomAnchor, constant: 10).isActive = true
brightnessValueLabel.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -10).isActive = true
brightnessValueLabel.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: view.bounds.width - 30).isActive = true
brightnessValueLabel.heightAnchor.constraint(equalToConstant: 25).isActive = true
//MARK: Contrast Label
contrastLabel = UILabel()
contrastLabel.text = "Contrast"
contrastLabel.font = UIFont(name: "Avenir", size: 14)
contrastLabel.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(contrastLabel)
contrastLabel.topAnchor.constraint(equalTo: brightnessSlider.bottomAnchor, constant: 10).isActive = true
contrastLabel.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: view.bounds.width / -2).isActive = true
contrastLabel.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 10).isActive = true
contrastLabel.heightAnchor.constraint(equalToConstant: 25).isActive = true
//MARK: Contrast Slider
contrastSlider = UISlider()
contrastSlider.setThumbImage(UIImage(named: "sliderThumb"), for: .normal)
contrastSlider.tintColor = .black
contrastSlider.minimumValue = 0
contrastSlider.maximumValue = 100
contrastSlider.translatesAutoresizingMaskIntoConstraints = false
contrastSlider.setValue(50, animated: true)
scrollView.addSubview(contrastSlider)
contrastSlider.topAnchor.constraint(equalTo: contrastLabel.bottomAnchor, constant: 5).isActive = true
contrastSlider.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -10).isActive = true
contrastSlider.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 10).isActive = true
contrastSlider.heightAnchor.constraint(equalToConstant: 25).isActive = true
//MArk: Contrast Value Label
contrastValueLabel = UILabel()
contrastValueLabel.text = "50"
contrastValueLabel.font = UIFont(name: "Avenir", size: 14)
contrastValueLabel.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(contrastValueLabel)
contrastValueLabel.topAnchor.constraint(equalTo: brightnessSlider.bottomAnchor, constant: 10).isActive = true
contrastValueLabel.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -10).isActive = true
contrastValueLabel.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: view.bounds.width - 30).isActive = true
contrastValueLabel.heightAnchor.constraint(equalToConstant: 25).isActive = true
//MARK: Saturation Label
saturationLabel = UILabel()
saturationLabel.text = "Saturation"
saturationLabel.font = UIFont(name: "Avenir", size: 14)
saturationLabel.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(saturationLabel)
saturationLabel.topAnchor.constraint(equalTo: contrastSlider.bottomAnchor, constant: 10).isActive = true
saturationLabel.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: view.bounds.width / -2).isActive = true
saturationLabel.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 10).isActive = true
saturationLabel.heightAnchor.constraint(equalToConstant: 25).isActive = true
//MARK: Saturation Slider
saturationSlider = UISlider()
saturationSlider.setThumbImage(UIImage(named: "sliderThumb"), for: .normal)
saturationSlider.tintColor = .black
saturationSlider.minimumValue = 0
saturationSlider.maximumValue = 100
saturationSlider.translatesAutoresizingMaskIntoConstraints = false
saturationSlider.setValue(50, animated: true)
scrollView.addSubview(saturationSlider)
saturationSlider.topAnchor.constraint(equalTo: saturationLabel.bottomAnchor, constant: 5).isActive = true
saturationSlider.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -10).isActive = true
saturationSlider.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 10).isActive = true
saturationSlider.heightAnchor.constraint(equalToConstant: 25).isActive = true
//MArk: Saturation Value Label
saturationValueLabel = UILabel()
saturationValueLabel.text = "50"
saturationValueLabel.font = UIFont(name: "Avenir", size: 14)
saturationValueLabel.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(saturationValueLabel)
saturationValueLabel.topAnchor.constraint(equalTo: contrastSlider.bottomAnchor, constant: 10).isActive = true
saturationValueLabel.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -10).isActive = true
saturationValueLabel.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: view.bounds.width - 30).isActive = true
saturationValueLabel.heightAnchor.constraint(equalToConstant: 25).isActive = true
//MARK: Noise Label
noiseLabel = UILabel()
noiseLabel.text = "Noise"
noiseLabel.font = UIFont(name: "Avenir", size: 14)
noiseLabel.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(noiseLabel)
noiseLabel.topAnchor.constraint(equalTo: saturationSlider.bottomAnchor, constant: 10).isActive = true
noiseLabel.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: view.bounds.width / -2).isActive = true
noiseLabel.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 10).isActive = true
noiseLabel.heightAnchor.constraint(equalToConstant: 25).isActive = true
//MARK: Noise Slider
noiseSlider = UISlider()
noiseSlider.setThumbImage(UIImage(named: "sliderThumb"), for: .normal)
noiseSlider.tintColor = .black
noiseSlider.minimumValue = 0
noiseSlider.maximumValue = 100
noiseSlider.translatesAutoresizingMaskIntoConstraints = false
noiseSlider.setValue(50, animated: true)
scrollView.addSubview(noiseSlider)
noiseSlider.topAnchor.constraint(equalTo: noiseLabel.bottomAnchor, constant: 5).isActive = true
noiseSlider.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -10).isActive = true
noiseSlider.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 10).isActive = true
noiseSlider.heightAnchor.constraint(equalToConstant: 25).isActive = true
//MArk: Noise Value Label
noiseValueLabel = UILabel()
noiseValueLabel.text = "50"
noiseValueLabel.font = UIFont(name: "Avenir", size: 14)
noiseValueLabel.translatesAutoresizingMaskIntoConstraints = false
scrollView.addSubview(noiseValueLabel)
noiseValueLabel.topAnchor.constraint(equalTo: saturationSlider.bottomAnchor, constant: 10).isActive = true
noiseValueLabel.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor, constant: -10).isActive = true
noiseValueLabel.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: view.bounds.width - 30).isActive = true
noiseValueLabel.heightAnchor.constraint(equalToConstant: 25).isActive = true
If somebody wonders, this is my view hierarchy, where all the items I need to be on scroll view are in fact on scroll view. I added gray color to scroll view to make it visable.
When you are using autolayout you do not need to specify contentSize, it will infer that from the subviews. The conditions are:
topmostView.topAnchor should be attached to scrollView.topAnchor
bottommostView.bottomAnchor should be attached to scrollView.bottomAnchor
Leading and trailing of scrollView should be attached to any view which has a width.
A few problems i see in your code.
You seem to have attached a label's leading and trailing to a scrollView which is not what you want to do most of the time because the scrollView width will be only as much as that of the label.
You also seem to have attached the scrollView leading and trailing at multiple places which will compute different leading and trailing constraints leading to conflicts. (I'm pretty sure if you check your log it will show some constraint breaking)
You have not attached the top or bottom of the topmost and bottommost views that are inside the scrollView to the scrollView's top and bottom.
Apple recommends that when using UIScrollView, have a dummy view (contentView) which will pinned to the top, leading, trailing, bottom of the scrollView and have a specified width. The height of that view will be calculated dynamically from the views you add to it. The same concept of the top of the topmost view attached to the contentView's top and bottom of the bottommost view attached to the contentView's bottom.
You can check my github repo where there is a minimalistic example which explains a UIScrollView with autolayout.
I have a booking app, where user can book a serviceName and servantName, i have to create dynamic (incremental) UITextFields for those two types, those TextFields get filled from Two UIPickerViews (PickerViews works fine).
How can i assign text to TextFields, which is dynamically created from those pickerViews.
I created TextFieldss using Autolayout in scrollView as below function
func addBookingRow(firstTime: Bool) {
let containerView = UIView()
containerView.backgroundColor = .white
containerView.layer.cornerRadius = 5
containerView.layer.borderColor = .white
containerView.layer.borderWidth = 2
containerView.tag = count
contentView.addSubview(containerView)
containerView.translatesAutoresizingMaskIntoConstraints = false
if firstTime {
containerView.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 10).isActive = true
} else {
containerView.topAnchor.constraint(equalTo: bookedServices[count - 1].bottomAnchor, constant: 10).isActive = true
}
containerView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 16).isActive = true
containerView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -16).isActive = true
let serviceNameTF = CustomTextField()
serviceNameTF.backgroundColor = .white
serviceNameTF.placeholder = "Choose Service"
serviceNameTF.font = UIFont(name: "RB", size: 17)
serviceNameTF.textAlignment = .right
serviceNameTF.tag = count
containerView.addSubview(serviceNameTF)
setupPickerViews(textField: serviceNameTF, picker: serviceNamePicker)
serviceNameTF.addTarget(self, action: #selector(self.serviceNameIsTapped), for: .touchDown)
serviceNameTF.translatesAutoresizingMaskIntoConstraints = false
serviceNameTF.topAnchor.constraint(equalTo: containerView.topAnchor, constant: 5).isActive = true
serviceNameTF.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 5).isActive = true
serviceNameTF.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -5).isActive = true
serviceNameTF.heightAnchor.constraint(equalToConstant: 40).isActive = true
let workerTF = CustomTextField()
workerTF.backgroundColor = .white
workerTF.placeholder = "Choose Servant"
workerTF.font = UIFont(name: "RB", size: 17)
workerTF.textAlignment = .right
workerTF.tag = count
containerView.addSubview(workerTF)
setupPickerViews(textField: workerTF, picker: workerPicker)
workerTF.addTarget(self, action: #selector(self.workerTFIsTapped), for: .touchDown)
workerTF.translatesAutoresizingMaskIntoConstraints = false
workerTF.topAnchor.constraint(equalTo: serviceNameTF.bottomAnchor, constant: 5).isActive = true
workerTF.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 5).isActive = true
workerTF.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -5).isActive = true
workerTF.heightAnchor.constraint(equalToConstant: 40).isActive = true
let price = UILabel()
price.font = UIFont(name: "RB", size: 17)
price.textColor = .white
containerView.addSubview(price)
price.translatesAutoresizingMaskIntoConstraints = false
price.topAnchor.constraint(equalTo: workerTF.bottomAnchor, constant: 5).isActive = true
price.leadingAnchor.constraint(equalTo: containerView.leadingAnchor, constant: 5).isActive = true
price.trailingAnchor.constraint(equalTo: containerView.trailingAnchor, constant: -5).isActive = true
price.heightAnchor.constraint(equalToConstant: 40).isActive = true
containerView.bottomAnchor.constraint(equalTo: price.bottomAnchor, constant: 5).isActive = true
contentView.bottomAnchor.constraint(greaterThanOrEqualTo: containerView.bottomAnchor, constant: 250).isActive = true
bookedServices.append(containerView)
count += 1
}