swift can't call function after clicking button - ios

I have made a container view with a image view and a button inside for some reason when running the app in simulator i can't click button and call the function taking me to the next screen , i have encountered this kind of problem before and it was as simple as changing the button to a lazy var though that hasn't work on this occasion?
lazy var nameLabelButton = UIButton()
func setupNavBarWithUser() {
guard let displayName = user?.DisplayName else { return }
let titleView = UIView()
titleView.frame = CGRect(x: 0, y: 0, width: 100, height: 40)
titleView.backgroundColor = UIColor.red
let containerView = UIView()
containerView.translatesAutoresizingMaskIntoConstraints = false
titleView.addSubview(containerView)
let profileImageView = UIImageView()
profileImageView.translatesAutoresizingMaskIntoConstraints = false
profileImageView.contentMode = .scaleAspectFill
profileImageView.layer.cornerRadius = 20
profileImageView.clipsToBounds = true
if let profileImageUrl = user?.profileImageURL {
profileImageView.loadImageUsingCacheWithUrlString(urlString:profileImageUrl)
}
containerView.addSubview(profileImageView)
//ios 9 constraint anchors
//need x,y,width,height anchors
profileImageView.leftAnchor.constraint(equalTo: containerView.leftAnchor).isActive = true
profileImageView.centerYAnchor.constraint(equalTo: containerView.centerYAnchor).isActive = true
profileImageView.widthAnchor.constraint(equalToConstant: 40).isActive = true
profileImageView.heightAnchor.constraint(equalToConstant: 40).isActive = true
containerView.addSubview(nameLabelButton)
nameLabelButton.setTitle("\(displayName)", for: .normal)
nameLabelButton.setTitleColor(.black, for: .normal)
nameLabelButton.translatesAutoresizingMaskIntoConstraints = false
//need x,y,width,height anchors
nameLabelButton.leftAnchor.constraint(equalTo: profileImageView.rightAnchor, constant: 8).isActive = true
nameLabelButton.centerYAnchor.constraint(equalTo: profileImageView.centerYAnchor).isActive = true
nameLabelButton.rightAnchor.constraint(equalTo: containerView.rightAnchor).isActive = true
nameLabelButton.heightAnchor.constraint(equalTo: profileImageView.heightAnchor).isActive = true
containerView.centerXAnchor.constraint(equalTo: titleView.centerXAnchor).isActive = true
containerView.centerYAnchor.constraint(equalTo: titleView.centerYAnchor).isActive = true
nameLabelButton.addTarget(self, action: #selector(self.openUsersProfileController), for: .touchUpInside)
self.navigationItem.titleView = titleView
}
func openUsersProfileController(){
print("asdasdadsad")
let openUsersProfileController = UserProfileController(collectionViewLayout: UICollectionViewFlowLayout())
openUsersProfileController.user = self.user
navigationController?.pushViewController(openUsersProfileController, animated: true)
}

well, code looks fine you just need to add #objc
#objc func openUsersProfileController(){
print("asdasdadsad")
let openUsersProfileController = UserProfileController(collectionViewLayout: UICollectionViewFlowLayout())
openUsersProfileController.user = self.user
navigationController?.pushViewController(openUsersProfileController, animated: true)
}
Reason:
From Swift 4, we manually need to add #objc before function.

Related

Swift - Subviews frame.maxY reading incorrectly

I have a basic sign up screen set up programmatically with the UI elements inside a view that is itself inside a scroll view.
The last UI element in the screen is a register button. I set up a keyboard notification observer with the Will Show and Will Hide notifications.
I am running this code on iPod touch 7th gen simulator.
My problem is when trying to read the maxY value of the sign up button and compare it to the keyboard minY it prints wrong numbers.
The keyboard is clearly blocking the register button which mean the button's maxY value will be greater the the keyboard minY value.
However the values printed shows that there is something wrong with the reading of the register button frame.
Here is my code:
import UIKit
class RegisterVC: UIViewController {
private let scrollView: UIScrollView = {
let scroll = UIScrollView()
scroll.clipsToBounds = true
scroll.isScrollEnabled = true
scroll.translatesAutoresizingMaskIntoConstraints = false
scroll.showsVerticalScrollIndicator = false
return scroll
}()
private let scrollInnerView: UIView = {
let innerView = UIView()
innerView.translatesAutoresizingMaskIntoConstraints = false
return innerView
}()
private let profilePic: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(systemName: "person.circle")
imageView.contentMode = .scaleAspectFit
imageView.tintColor = .gray
imageView.translatesAutoresizingMaskIntoConstraints = false
return imageView
}()
private let usernameField: UITextField = {
let field = UITextField()
field.autocapitalizationType = .none
field.autocorrectionType = .no
field.returnKeyType = .next
field.layer.cornerRadius = 12
field.layer.borderWidth = 1
field.layer.borderColor = UIColor.lightGray.cgColor
field.placeholder = "Username..."
field.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 5, height: 0))
field.leftViewMode = .always
field.backgroundColor = .white
field.keyboardType = .default
field.isHighlighted = false
field.textAlignment = .left
field.translatesAutoresizingMaskIntoConstraints = false
return field
}()
private let emailField: UITextField = {
let field = UITextField()
field.autocapitalizationType = .none
field.autocorrectionType = .no
field.returnKeyType = .next
field.layer.cornerRadius = 12
field.layer.borderWidth = 1
field.layer.borderColor = UIColor.lightGray.cgColor
field.placeholder = "Email Address..."
field.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 5, height: 0))
field.leftViewMode = .always
field.backgroundColor = .white
field.keyboardType = .default
field.textAlignment = .left
field.translatesAutoresizingMaskIntoConstraints = false
return field
}()
private let passwordField: UITextField = {
let field = UITextField()
field.autocapitalizationType = .none
field.autocorrectionType = .no
field.returnKeyType = .done
field.layer.cornerRadius = 12
field.layer.borderWidth = 1
field.layer.borderColor = UIColor.lightGray.cgColor
field.placeholder = "Password..."
field.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 5, height: 0))
field.leftViewMode = .always
field.backgroundColor = .white
field.isSecureTextEntry = true
field.textAlignment = .left
field.keyboardType = .default
field.translatesAutoresizingMaskIntoConstraints = false
return field
}()
private let registerButton: UIButton = {
let button = UIButton()
button.setTitle("Create Account", for: .normal)
button.backgroundColor = .systemGreen
button.setTitleColor(.white, for: .normal)
button.layer.cornerRadius = 12
button.layer.masksToBounds = true
button.titleLabel?.font = .systemFont(ofSize: 20, weight: .bold)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
title = "Create Account"
view.backgroundColor = .white
view.addSubview(scrollView)
scrollView.addSubview(scrollInnerView)
scrollInnerView.addSubview(profilePic)
scrollInnerView.addSubview(usernameField)
scrollInnerView.addSubview(emailField)
scrollInnerView.addSubview(passwordField)
scrollInnerView.addSubview(registerButton)
usernameField.delegate = self
emailField.delegate = self
passwordField.delegate = self
profilePic.isUserInteractionEnabled = true
registerButton.addTarget(self,
action: #selector(registerButtonTapped),
for: .touchUpInside)
setUpKeyboard()
setUpConstraints()
}
private func setUpConstraints() {
// Scroll View Constraints
scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
scrollView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor).isActive = true
// Scroll Inner View Constraints
scrollInnerView.topAnchor.constraint(equalTo: scrollView.topAnchor).isActive = true
scrollInnerView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor).isActive = true
scrollInnerView.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor).isActive = true
scrollInnerView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor).isActive = true
scrollInnerView.widthAnchor.constraint(equalTo: scrollView.widthAnchor).isActive = true
scrollInnerView.heightAnchor.constraint(equalTo: scrollView.heightAnchor, constant: 1).isActive = true
// Profile Picture Constraints
profilePic.widthAnchor.constraint(equalTo: scrollInnerView.widthAnchor, multiplier: 1/3).isActive = true
profilePic.heightAnchor.constraint(equalTo: scrollInnerView.widthAnchor, multiplier: 1/3).isActive = true
profilePic.centerXAnchor.constraint(equalTo: scrollInnerView.centerXAnchor).isActive = true
profilePic.topAnchor.constraint(equalTo: scrollInnerView.topAnchor, constant: 10).isActive = true
// User Name Field Constraints
usernameField.widthAnchor.constraint(equalTo: scrollInnerView.widthAnchor, constant: -60).isActive = true
usernameField.heightAnchor.constraint(equalToConstant: 45).isActive = true
usernameField.topAnchor.constraint(equalTo: profilePic.bottomAnchor, constant: 10).isActive = true
usernameField.centerXAnchor.constraint(equalTo: profilePic.centerXAnchor).isActive = true
// Email Field Constraints
emailField.widthAnchor.constraint(equalTo: usernameField.widthAnchor).isActive = true
emailField.heightAnchor.constraint(equalTo: usernameField.heightAnchor).isActive = true
emailField.topAnchor.constraint(equalTo: usernameField.bottomAnchor, constant: 10).isActive = true
emailField.centerXAnchor.constraint(equalTo: usernameField.centerXAnchor).isActive = true
// Password Field Constraints
passwordField.widthAnchor.constraint(equalTo: emailField.widthAnchor).isActive = true
passwordField.heightAnchor.constraint(equalTo: emailField.heightAnchor).isActive = true
passwordField.topAnchor.constraint(equalTo: emailField.bottomAnchor, constant: 10).isActive = true
passwordField.centerXAnchor.constraint(equalTo: emailField.centerXAnchor).isActive = true
// Register Button Constraints
registerButton.widthAnchor.constraint(equalTo: passwordField.widthAnchor).isActive = true
registerButton.heightAnchor.constraint(equalTo: passwordField.heightAnchor).isActive = true
registerButton.topAnchor.constraint(equalTo: passwordField.bottomAnchor, constant: 20).isActive = true
registerButton.centerXAnchor.constraint(equalTo: passwordField.centerXAnchor).isActive = true
}
private func setUpKeyboard() {
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShowNotification), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHideNotification), name: UIResponder.keyboardWillHideNotification, object: nil)
}
#objc private func keyboardWillShowNotification(_ notification: NSNotification) {
guard let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue
else {
return
}
print(keyboardSize.minY)
print(registerButton.frame.maxY)
}
}
It's because the keyboard frame and the button frame are in two different coordinate systems. You cannot compare them directly. You need to convert the button frame to window coordinates before comparing them. Or else convert the keyboard frame to the button frame coordinates (the button's superview).
Actually what I typically do is convert the keyboard frame to the internal coordinates of the target view and compare that to the target view's bounds. For example:
// n is the notification
let d = n.userInfo!
var r = d[UIResponder.keyboardFrameEndUserInfoKey] as! CGRect
r = self.slidingView.convert(r, from:nil) // <- this is the key move!
let h = self.slidingView.bounds.intersection(r).height
That tells me whether the keyboard would cover the sliding view, and if so, by how much.

TapGestureRecognizer not working in UIView subviews

I want to add a tap gesture recognizer to a custom UIView (which represent an Image and a Label). It seems that the gesture recognizer is not added to the view or that the subviews are not considered as the UIView itself, hence not working.
Here is how I add my view :
Navbar.swift :
let indexSubview = IconTextView(svgName: "https://placeholder.pics/svg/30", textKey: "Index")
self.indexButton.addSubview(indexSubview)
let indexButtonTap = UITapGestureRecognizer(target: self, action: #selector(goToIndex))
indexButton.addGestureRecognizer(indexButtonTap)
(IconTextView being my custom view)
Then when I tap the indexButtonnothing is working.
My tap function, just in case:
#objc func goToIndex(sender:UITapGestureRecognizer) {
print("GO TO INDEX")
router.setRoute(routeName: "INDEX", routeParam: "")
}
I don't understand why it is not working, the userInteractions are enabled on all the elements.
Your precedent code + tap gesture, I edit constraints, add containerView:
class Aiutotipo: UIViewController {
let myImageView: UIImageView = {
let iv = UIImageView()
iv.contentMode = .scaleToFill
iv.clipsToBounds = true
iv.backgroundColor = .red
iv.translatesAutoresizingMaskIntoConstraints = false
return iv
}()
let myLabel: UILabel = {
let label = UILabel()
label.text = "Débats"
label.textColor = .white
label.textAlignment = .center
label.font = .systemFont(ofSize: 30, weight: .semibold)
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let containerView = UIView() //your container view
override func viewDidLoad() {
super.viewDidLoad()
containerView.backgroundColor = .red // red bacground for container view visible, set .clear for transparent bg
containerView.isUserInteractionEnabled = true
containerView.translatesAutoresizingMaskIntoConstraints = false
let indexButtonTap = UITapGestureRecognizer(target: self, action: #selector(goToIndex))
containerView.addGestureRecognizer(indexButtonTap)
myImageView.image = UIImage(named: "profilo") // set here your image
let myWidth = myLabel.intrinsicContentSize.width // This reveal only text width in label
view.addSubview(containerView)
containerView.heightAnchor.constraint(equalToConstant: myWidth + 50).isActive = true
containerView.widthAnchor.constraint(equalToConstant: myWidth).isActive = true
containerView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
containerView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
containerView.addSubview(myImageView)
myImageView.topAnchor.constraint(equalTo: containerView.topAnchor).isActive = true
myImageView.leadingAnchor.constraint(equalTo: containerView.leadingAnchor).isActive = true
myImageView.trailingAnchor.constraint(equalTo: containerView.trailingAnchor).isActive = true
myImageView.heightAnchor.constraint(equalTo: myImageView.widthAnchor).isActive = true
containerView.addSubview(myLabel)
myLabel.topAnchor.constraint(equalTo: myImageView.bottomAnchor).isActive = true
myLabel.leadingAnchor.constraint(equalTo: containerView.leadingAnchor).isActive = true
myLabel.trailingAnchor.constraint(equalTo: containerView.trailingAnchor).isActive = true
myLabel.bottomAnchor.constraint(equalTo: containerView.bottomAnchor).isActive = true
}
#objc fileprivate func goToIndex() {
print("GO TO INDEX")
}
}
This is the result

UIButton in a view with animation not detecting touch

I'm following a tutorial to create an interactive popup animation (http://www.swiftkickmobile.com/building-better-app-animations-swift-uiviewpropertyanimator/), and now would like to add buttons to the popup rather than have static text as in the tutorial.
The animation works fine, but the buttons are not detecting touch. Touching the button causes the animation to reverse, instead of printing my "test" statement.
From research, it looks to either be an issue with view hierarchies, the animation disabling the button touch, or layout/constraint issues with the button. I've tried addressing the above issues, but nothing has worked, was hoping someone might be able to help?
I've left out the code pertaining to the animation since I think the issue is to do with layout (and the animation seems to be working fine) - but it's still a lot; apologies in advance for the large amount of code.
class ViewController: UIViewController {
private let popupOffset: CGFloat = 440
private lazy var contentImageView: UIImageView = {
let imageView = UIImageView()
imageView.image = #imageLiteral(resourceName: "Background")
return imageView
}()
private lazy var overlayView: UIView = {
let view = UIView()
view.backgroundColor = .black
view.alpha = 0
return view
}()
private lazy var popupView: UIView = {
let view = UIView()
view.backgroundColor = .white
view.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMinXMinYCorner]
view.layer.shadowColor = UIColor.black.cgColor
view.layer.shadowOpacity = 0.1
view.layer.shadowRadius = 10
return view
}()
private lazy var closedTitleLabel: UILabel = {
let label = UILabel()
label.text = "Hello"
label.font = UIFont.systemFont(ofSize: 16, weight: UIFont.Weight.medium)
label.textColor = UIColor.darkGray
label.textAlignment = .center
return label
}()
private lazy var openTitleLabel: UILabel = {
let label = UILabel()
label.text = "Which door will you choose?"
label.font = UIFont.systemFont(ofSize: 16, weight: UIFont.Weight.medium)
label.textColor = UIColor.darkGray
label.textAlignment = .center
label.alpha = 0
label.transform = CGAffineTransform(scaleX: 1.6, y: 1.6).concatenating(CGAffineTransform(translationX: 0, y: 15))
return label
}()
private lazy var reviewsImageView: UIImageView = {
let imageView = UIImageView()
imageView.image = #imageLiteral(resourceName: "LabelBackground")
return imageView
}()
let stackView = UIStackView()
let buttonA = UIButton()
let buttonB = UIButton()
let buttonC = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
layout()
popupView.addGestureRecognizer(panRecognizer)
}
override var prefersStatusBarHidden: Bool {
return true
}
//Layout
private var bottomConstraint = NSLayoutConstraint()
private func layout() {
contentImageView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(contentImageView)
contentImageView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
contentImageView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
contentImageView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
contentImageView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
overlayView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(overlayView)
overlayView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
overlayView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
overlayView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
overlayView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
popupView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(popupView)
popupView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
popupView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
bottomConstraint = popupView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: popupOffset)
bottomConstraint.isActive = true
popupView.heightAnchor.constraint(equalToConstant: 500).isActive = true
closedTitleLabel.translatesAutoresizingMaskIntoConstraints = false
popupView.addSubview(closedTitleLabel)
closedTitleLabel.leadingAnchor.constraint(equalTo: popupView.leadingAnchor).isActive = true
closedTitleLabel.trailingAnchor.constraint(equalTo: popupView.trailingAnchor).isActive = true
closedTitleLabel.topAnchor.constraint(equalTo: popupView.topAnchor, constant: 20).isActive = true
openTitleLabel.translatesAutoresizingMaskIntoConstraints = false
popupView.addSubview(openTitleLabel)
openTitleLabel.leadingAnchor.constraint(equalTo: popupView.leadingAnchor).isActive = true
openTitleLabel.trailingAnchor.constraint(equalTo: popupView.trailingAnchor).isActive = true
openTitleLabel.topAnchor.constraint(equalTo: popupView.topAnchor, constant: 20).isActive = true
reviewsImageView.translatesAutoresizingMaskIntoConstraints = false
popupView.addSubview(reviewsImageView)
reviewsImageView.leadingAnchor.constraint(equalTo: popupView.leadingAnchor).isActive = true
reviewsImageView.trailingAnchor.constraint(equalTo: popupView.trailingAnchor).isActive = true
reviewsImageView.bottomAnchor.constraint(equalTo: popupView.bottomAnchor).isActive = true
reviewsImageView.heightAnchor.constraint(equalToConstant: 428).isActive = true
buttonA.backgroundColor = UIColor.clear
let heightConstraintA = buttonA.heightAnchor.constraint(equalToConstant: 135)
heightConstraintA.isActive = true
heightConstraintA.priority = UILayoutPriority(rawValue: 999)
buttonA.translatesAutoresizingMaskIntoConstraints = false
buttonA.setTitle("A", for: .normal)
buttonA.setTitleColor(UIColor.darkGray, for: .normal)
buttonA.backgroundColor = UIColor.clear
buttonA.addTarget(self, action: #selector(buttonATapped(sender:)), for: .touchDown)
//self.popupView.addSubview(buttonA)
buttonB.backgroundColor = UIColor.clear
let heightConstraintB = buttonB.heightAnchor.constraint(equalToConstant: 135)
heightConstraintB.isActive = true
heightConstraintB.priority = UILayoutPriority(rawValue: 999)
buttonB.translatesAutoresizingMaskIntoConstraints = false
buttonB.setTitle("B", for: .normal)
buttonB.setTitleColor(UIColor.darkGray, for: .normal)
buttonB.backgroundColor = UIColor.clear
//self.popupView.addSubview(buttonB)
buttonC.backgroundColor = UIColor.clear
let heightConstraintC = buttonC.heightAnchor.constraint(equalToConstant: 135)
heightConstraintC.isActive = true
heightConstraintC.priority = UILayoutPriority(rawValue: 999)
buttonC.translatesAutoresizingMaskIntoConstraints = false
buttonC.setTitle("C", for: .normal)
buttonC.setTitleColor(UIColor.darkGray, for: .normal)
buttonC.backgroundColor = UIColor.clear
//self.popupView.addSubview(buttonC)
popupView.addSubview(stackView)
stackView.backgroundColor = UIColor.clear
stackView.addArrangedSubview(buttonA)
stackView.addArrangedSubview(buttonB)
stackView.addArrangedSubview(buttonC)
stackView.translatesAutoresizingMaskIntoConstraints = false
popupView.addSubview(stackView)
stackView.leadingAnchor.constraint(equalTo: popupView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: popupView.trailingAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: popupView.bottomAnchor).isActive = true
stackView.heightAnchor.constraint(equalToConstant: 428).isActive = true
stackView.axis = .vertical
stackView.distribution = .fill
stackView.translatesAutoresizingMaskIntoConstraints = false
}
#objc func buttonATapped(sender: UIButton) {
print ("test")
}
private func animateTransitionIfNeeded(to state: State, duration: TimeInterval) {
//Animation code
}
#objc private func popupViewPanned(recognizer: UIPanGestureRecognizer) {
//Animation code
}
}
***For anyone else having the same issue, here is how I solved it, thanks to #OverD:
I removed the reviewsImageView completely (because that was only for color in my case, and I can easily add the color to the UIButton instead) Then instead of adding the buttons to the popupView, I added them to the stack view, and the stack view to the popupView. Lastly, my syntax for addTarget was not correct, and for some reason changing it to touchDown instead of touchUpInside made it work.
I noticed from the provided code that you are adding the same buttons multiple times, once as a subview of the popView and once in the stackView. Also you are not assigning any targets for the buttons.
I hope this helps

Use of unresolved identifier

I am building a barcode scanner. the operations are simple
scan a barcode,
if the scanned barcode is in my firebase database perform func updateProductInfo() if the barcode is not in my firebase database perform func enterNewProduct().
The one problem that I am having now is how to define metadataObj so that it is accessible by all and any other function that I will define later. I have attempt to define it right below the ScanController class but I couldn't figure it out. My code is below
import UIKit
import AVFoundation
import Firebase
class ScanController: UIViewController, AVCaptureMetadataOutputObjectsDelegate {
var captureSession: AVCaptureSession?
var videoPreviewLayer: AVCaptureVideoPreviewLayer?
var qrCodeFrameView: UIView?
let itemDB = FIRDatabase.database().reference().child("Items")
let supportedCodeTypes = [AVMetadataObjectTypeUPCECode,
AVMetadataObjectTypeCode39Code,
AVMetadataObjectTypeCode39Mod43Code,
AVMetadataObjectTypeCode93Code,
AVMetadataObjectTypeCode128Code,
AVMetadataObjectTypeEAN8Code,
AVMetadataObjectTypeEAN13Code,
AVMetadataObjectTypeAztecCode,
AVMetadataObjectTypePDF417Code,
AVMetadataObjectTypeQRCode]
let messageLabel: UILabel = {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 40))
// label.center = CGPoint(x: 160, y: 285)
label.center = CGPoint(x: 160, y: 285)
label.textAlignment = .center
return label
}()
let productDescriptionTextField: UITextField = {
let tf = UITextField()
tf.placeholder = "Product Description"
tf.translatesAutoresizingMaskIntoConstraints = false
return tf
}()
let descriptionSeparatorView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(r: 220, g: 220, b: 220)
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let priceTextField: UITextField = {
let tf = UITextField()
tf.placeholder = "Price"
tf.translatesAutoresizingMaskIntoConstraints = false
return tf
}()
let priceSeparatorView: UIView = {
let view = UIView()
view.backgroundColor = UIColor(r: 220, g: 220, b: 220)
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let productLocationTextField: UITextField = {
let tf = UITextField()
tf.placeholder = "Product Location"
tf.translatesAutoresizingMaskIntoConstraints = false
return tf
}()
let productImageView: UIImageView = {
let imageView = UIImageView()
imageView.image = UIImage(named: "XXXXXXX")
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.contentMode = .scaleAspectFill
return imageView
}()
let exitScanButton: UIButton = {
let button = UIButton(type: .system)
button.backgroundColor = UIColor(r: 80, g: 101, b: 161)
button.setTitle("Exit", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget( nil, action: #selector(exitScan), for:.touchUpInside)
return button
}()
let newProductEntry: UIView = {
let view = UIView()
view.backgroundColor = UIColor.white
view.translatesAutoresizingMaskIntoConstraints = false
view.layer.cornerRadius = 5
view.layer.masksToBounds = true
return view
}()
let productSummary: UIView = {
let view = UIView()
view.backgroundColor = UIColor.white
view.translatesAutoresizingMaskIntoConstraints = false
view.layer.cornerRadius = 5
view.layer.masksToBounds = true
return view
}()
let productDescriptionLabel: UILabel = {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 40))
// label.center = CGPoint(x: 160, y: 285)
label.center = CGPoint(x: 160, y: 285)
label.textAlignment = .center
return label
}()
let storeNameLabel: UILabel = {
let label = UILabel(frame: CGRect(x: 0, y: 0, width: 200, height: 40))
// label.center = CGPoint(x: 160, y: 285)
label.center = CGPoint(x: 160, y: 285)
label.textAlignment = .center
return label
}()
let verifyProductInfoButton: UIButton = {
let button = UIButton(type: .system)
button.backgroundColor = UIColor(r: 80, g: 101, b: 161)
button.setTitle("Checked", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget( nil, action: #selector(verifyNewProduct), for:.touchUpInside)
return button
}()
let updateProductInfoButton: UIButton = {
let button = UIButton(type: .system)
button.backgroundColor = UIColor(r: 80, g: 101, b: 161)
button.setTitle("Update", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget( nil, action: #selector(updateProductInfo), for:.touchUpInside)
return button
}()
let enterNewProductButton: UIButton = {
let button = UIButton(type: .system)
button.backgroundColor = UIColor(r: 80, g: 101, b: 161)
button.setTitle("Enter", for: .normal)
button.setTitleColor(UIColor.white, for: .normal)
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 16)
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget( nil, action: #selector(enterNewProduct), for:.touchUpInside)
return button
}()
func updateProductInfo() {
guard let price = priceTextField.text,
let location = productLocationTextField.text
else{
print("Please update price and product location")
return
}
}
func verifyNewProduct() {
// need to add a counter that counts how many people verified product information
self.dismiss(animated: true, completion: nil)
}
func enterNewProduct() {
let itemID = metadataObj.stringValue
guard let Description = productDescriptionTextField.text,
let price = priceTextField.text,
let location = productLocationTextField.text
else{
print("Fill basic product information")
return
}
let ref = FIRDatabase.database().reference(fromURL: "")
// creating an item child node
let values = ["Item Description": Description, "Image": price, "Location": location, "Price": price ]
let items = ref.child("Items").child(itemID!)
items.updateChildValues(values, withCompletionBlock: { (err, ref) in
if err != nil {
print(err)
return
}
})
self.dismiss(animated: true, completion: nil)
}
func exitScan() {
//Go back to ViewController
self.dismiss(animated: true, completion: nil)
}
func setupUpdateProductInfo() {
productSummary.addSubview(productDescriptionLabel)
productSummary.addSubview(storeNameLabel)
productSummary.addSubview(priceTextField)
productSummary.addSubview(productLocationTextField)
productSummary.addSubview(verifyProductInfoButton)
productSummary.addSubview(updateProductInfoButton)
productSummary.addSubview(productImageView)
// need x, y, width, height constraints for product image
productImageView.leftAnchor.constraint(equalTo: productSummary.leftAnchor, constant: 12).isActive = true
productImageView.topAnchor.constraint(equalTo: productSummary.topAnchor).isActive = true
productImageView.widthAnchor.constraint(equalTo: productSummary.widthAnchor, constant: 100).isActive = true
productImageView.heightAnchor.constraint(equalToConstant: 100).isActive = true
// need x, y, width, height constraints for store logo
storeNameLabel.leftAnchor.constraint(equalTo: productDescriptionLabel.leftAnchor, constant: 12).isActive = true
storeNameLabel.topAnchor.constraint(equalTo: productSummary.topAnchor).isActive = true
storeNameLabel.widthAnchor.constraint(equalTo: productSummary.widthAnchor).isActive = true
// need x, y, width, height constraints for description label
productDescriptionLabel.leftAnchor.constraint(equalTo: productImageView.leftAnchor, constant: 12).isActive = true
productDescriptionLabel.topAnchor.constraint(equalTo: productSummary.topAnchor).isActive = true
productDescriptionLabel.widthAnchor.constraint(equalTo: productSummary.widthAnchor).isActive = true
productDescriptionLabel.rightAnchor.constraint(equalTo: storeNameLabel.leftAnchor,constant: 12).isActive = true
// need x, y, width, height constraints for price textfield
priceTextField.leftAnchor.constraint(equalTo: productImageView.rightAnchor, constant: 12).isActive = true
priceTextField.topAnchor.constraint(equalTo: productDescriptionLabel.bottomAnchor).isActive = true
priceTextField.widthAnchor.constraint(equalToConstant: 50).isActive = true
// need x, y, width, height constraints for location textfield
productLocationTextField.leftAnchor.constraint(equalTo: priceTextField.rightAnchor, constant: 12).isActive = true
productLocationTextField.topAnchor.constraint(equalTo: productDescriptionLabel.bottomAnchor).isActive = true
productLocationTextField.widthAnchor.constraint(equalToConstant: 50).isActive = true
}
func setupNewProductEntry() {
newProductEntry.addSubview(productImageView)
newProductEntry.addSubview(productLocationTextField)
newProductEntry.addSubview(productDescriptionTextField)
newProductEntry.addSubview(priceTextField)
newProductEntry.addSubview(enterNewProductButton)
newProductEntry.addSubview(descriptionSeparatorView)
newProductEntry.addSubview(priceSeparatorView)
// need x, y, width, height constraints
newProductEntry.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
newProductEntry.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
newProductEntry.widthAnchor.constraint(equalTo: view.widthAnchor, constant: -24).isActive = true
newProductEntry.heightAnchor.constraint(equalToConstant: 150).isActive = true
// need x, y, width, height constraints for name productDescriptionTextField
productDescriptionTextField.leftAnchor.constraint(equalTo: newProductEntry.leftAnchor, constant: 12).isActive = true
productDescriptionTextField.topAnchor.constraint(equalTo: newProductEntry.topAnchor).isActive = true
productDescriptionTextField.widthAnchor.constraint(equalTo: newProductEntry.widthAnchor).isActive = true
// need x, y, width, height constraints for description separator line
descriptionSeparatorView.leftAnchor.constraint(equalTo: newProductEntry.leftAnchor).isActive = true
descriptionSeparatorView.topAnchor.constraint(equalTo: productDescriptionTextField.bottomAnchor).isActive = true
descriptionSeparatorView.widthAnchor.constraint(equalTo: newProductEntry.widthAnchor).isActive = true
descriptionSeparatorView.heightAnchor.constraint(equalToConstant: 1).isActive = true
// need x, y, width, height constraints for name pricetextfield
priceTextField.leftAnchor.constraint(equalTo: newProductEntry.leftAnchor, constant: 12).isActive = true
priceTextField.topAnchor.constraint(equalTo: productDescriptionTextField.bottomAnchor).isActive = true
priceTextField.widthAnchor.constraint(equalTo: newProductEntry.widthAnchor).isActive = true
// need x, y, width, height constraints for price separator line
priceSeparatorView.leftAnchor.constraint(equalTo: newProductEntry.leftAnchor).isActive = true
priceSeparatorView.topAnchor.constraint(equalTo: priceTextField.bottomAnchor).isActive = true
priceSeparatorView.widthAnchor.constraint(equalTo: newProductEntry.widthAnchor).isActive = true
priceSeparatorView.heightAnchor.constraint(equalToConstant: 1).isActive = true
// need x, y, width, height constraints for name LocationTextField
productLocationTextField.leftAnchor.constraint(equalTo: newProductEntry.leftAnchor, constant: 12).isActive = true
productLocationTextField.topAnchor.constraint(equalTo: priceTextField.bottomAnchor).isActive = true
productLocationTextField.widthAnchor.constraint(equalTo: newProductEntry.widthAnchor).isActive = true
}
func setupenterNewProductButton(){
// need x, y, width, height constraints
enterNewProductButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
enterNewProductButton.topAnchor.constraint(equalTo: newProductEntry.bottomAnchor, constant: 12).isActive = true
enterNewProductButton.widthAnchor.constraint(equalTo: newProductEntry.widthAnchor).isActive = true
enterNewProductButton.heightAnchor.constraint(equalToConstant: (50)).isActive = true
}
func setupupdateProductInfoButton(){
// need x, y, width, height constraints
updateProductInfoButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
updateProductInfoButton.topAnchor.constraint(equalTo: productSummary.bottomAnchor, constant: 12).isActive = true
updateProductInfoButton.widthAnchor.constraint(equalTo: productSummary.widthAnchor).isActive = true
updateProductInfoButton.heightAnchor.constraint(equalToConstant: (50)).isActive = true
}
func setupverifyProductInfoButton(){
// need x, y, width, height constraints
verifyProductInfoButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
verifyProductInfoButton.topAnchor.constraint(equalTo: productSummary.bottomAnchor, constant: 12).isActive = true
verifyProductInfoButton.widthAnchor.constraint(equalTo: productSummary.widthAnchor).isActive = true
verifyProductInfoButton.heightAnchor.constraint(equalToConstant: (50)).isActive = true
verifyProductInfoButton.leftAnchor.constraint(equalTo: enterNewProductButton.rightAnchor).isActive = true
}
override func viewDidLoad() {
super.viewDidLoad()
//Get an instance of the AVCaptureDevice class a device object and provide the video as the media type parameter
let captureDevice = AVCaptureDevice.defaultDevice(withMediaType: AVMediaTypeVideo)
do {
// Get an instance of the AVCaptureDeviceInput class using the previous device object.
let input = try AVCaptureDeviceInput(device: captureDevice)
// Initialize the captureSession object.
captureSession = AVCaptureSession()
// Set the input device on the capture session.
captureSession?.addInput(input)
let captureMetadataOutput = AVCaptureMetadataOutput()
captureSession?.addOutput(captureMetadataOutput)
// Set delegate and use the default dispatch queue to execute the call back
captureMetadataOutput.setMetadataObjectsDelegate(self, queue: DispatchQueue.main)
captureMetadataOutput.metadataObjectTypes = supportedCodeTypes
// Initialize the video preview layer and add it as a sublayer to the viewPreview view's layer.
videoPreviewLayer = AVCaptureVideoPreviewLayer(session: captureSession)
videoPreviewLayer?.videoGravity = AVLayerVideoGravityResizeAspectFill
videoPreviewLayer?.frame = view.layer.bounds
view.layer.addSublayer(videoPreviewLayer!)
// Start video capture.
captureSession?.startRunning()
// Add the message label
self.view.addSubview(messageLabel)
self.view.addSubview(exitScanButton)
setupexitScanButton()
//initialize QR Code Frame to highlight the QR Code
qrCodeFrameView = UIView()
if let qrCodeFrameView = qrCodeFrameView {
qrCodeFrameView.layer.borderColor = UIColor.green.cgColor
qrCodeFrameView.layer.borderWidth = 2
view.addSubview(qrCodeFrameView)
}
} catch {
// If any error occurs, simply print it out and don't continue any more.
print(error)
return
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func captureOutput(_ captureOutput: AVCaptureOutput!, didOutputMetadataObjects metadataObjects: [Any]!, from connection: AVCaptureConnection!) {
// Check if the metadataObjects array is not nil and it contains at least one object.
if metadataObjects == nil || metadataObjects.count == 0 {
qrCodeFrameView?.frame = CGRect.zero
messageLabel.text = "No QR/barcode is detected"
return
}
//Get metadata object
let metadataObj = metadataObjects[0] as! AVMetadataMachineReadableCodeObject
let itemID = metadataObj.stringValue
if supportedCodeTypes.contains(metadataObj.type) {
//if the found metadata is equal to the QR code metadata then update the status label's text and set the the bounds
let barCodeObject = videoPreviewLayer?.transformedMetadataObject(for: metadataObj)
qrCodeFrameView?.frame = barCodeObject!.bounds
if metadataObj.stringValue != nil {
messageLabel.text = metadataObj.stringValue
//Searches firebase for existing barcode
let itemToSearchFor = metadataObj.stringValue
FIRDatabase.database().reference().child("Items").child(itemToSearchFor!).observeSingleEvent(of: .value, with:{(snap) in
print(snap)
}) } else {
setupNewProductEntry()
}
}
}
func setupexitScanButton() {
// need x, y, width, height constraints
exitScanButton.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
exitScanButton.topAnchor.constraint(equalTo: view.topAnchor, constant: 12).isActive = true
exitScanButton.widthAnchor.constraint(equalToConstant: 60).isActive = true
exitScanButton.heightAnchor.constraint(equalToConstant: (50)).isActive = true
}
}
My error is currently at let itemID = metadataObj.stringValue.
Define it at the top under qrcodeframeview to make it "global" in your class

UIScrollViews and anchors swift

I am having trouble setting up a scroll view and actually scrolling down. I populated the scroll view with some textfields and used anchors (topanchor,leftanchor...) to position them inside the scroll view. Even if I set the scroll view height to 1000, it wont actually move, it continues to show the same items, the scroll indicator does go down but the content itself doesnt, I already set the scroll view to scrollenabled, and delegate to self.
I think the problem might be with the anchors but then how will I arrange my items inside the scroll view, any sugestion will be greatly appreaciated.
EDIT : The code below indicates the anchors applied to the scroll view ( inputContainer ), the img corresponds to an UIImageView and the mainContainer to the UIView containing the img and the inputContainer.
inputContainer.topAnchor.constraintEqualToAnchor( img.bottomAnchor ).active = true
inputContainer.leftAnchor.constraintEqualToAnchor( mainContainer.leftAnchor ).active = true
inputContainer.widthAnchor.constraintEqualToAnchor( mainContainer.widthAnchor ).active = true
inputContainerBottomConstraint = inputContainer.bottomAnchor.constraintEqualToAnchor( cancelButton.topAnchor )
inputContainerBottomConstraint?.active = true
EDIT: This is how the code looks like :
class SView : UIView, UITextFieldDelegate, UIScrollViewDelegate {
let mainContainer : UIView = {
let v = UIView()
v.backgroundColor = .whiteColor()
v.layer.cornerRadius = 8
v.layer.masksToBounds = true
v.translatesAutoresizingMaskIntoConstraints = false
return v
}()
let Img : UIImageView = {
let img = UIImageView()
img.image = UIImage(named: "noImage")
img.backgroundColor = .blueColor()
img.translatesAutoresizingMaskIntoConstraints = false
img.contentMode = .ScaleAspectFill
img.clipsToBounds = true
return img
}()
let inputContainer : UIScrollView = {
let ic = UIScrollView()
ic.backgroundColor = .whiteColor()
ic.translatesAutoresizingMaskIntoConstraints = false
return ic
}()
let datePickerTextField : UITextField = {
let tf = UITextField()
tf.placeholder = "Fecha"
tf.textAlignment = .Center
tf.translatesAutoresizingMaskIntoConstraints = false
return tf
}()
let tagsTextField : UITextField = {
let tf = UITextField()
tf.placeholder = "Tags"
tf.textAlignment = .Center
tf.clearButtonMode = .Always
tf.translatesAutoresizingMaskIntoConstraints = false
return tf
}()
lazy var cancelButton : UIButton = {
let button = UIButton()
button.backgroundColor = UIColor.rgb(255, green: 65, blue: 65, alpha: 1)
button.setTitle("Cancelar", forState: .Normal)
button.tintColor = .whiteColor()
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget( self , action: #selector(handleCancelButtonPressed), forControlEvents: .TouchUpInside)
return button
}()
lazy var publicarButton : UIButton = {
let button = UIButton()
button.backgroundColor = UIColor.rgb(0 , green: 204, blue: 102, alpha: 1)
button.setTitle("Publicar", forState: .Normal)
button.tintColor = .whiteColor()
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget( self , action: #selector(handlePublicarButtonPressed), forControlEvents: .TouchUpInside)
return button
}()
override init(frame: CGRect)
{
super.init(frame: frame)
inputContainer.delegate = self
datePickerTextField.delegate = self
tagsTextField.delegate = self
setupMainContainer()
setupImg()
setupButtons()
setupInputContainer()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setupMainContainer ()
{
addSubview(mainContainer)
mainContainer.centerXAnchor.constraintEqualToAnchor( centerXAnchor ).active = true
mainContainer.centerYAnchor.constraintEqualToAnchor( centerYAnchor ).active = true
mainContainer.widthAnchor.constraintEqualToAnchor( widthAnchor ).active = true
mainContainer.heightAnchor.constraintEqualToAnchor( heightAnchor )
}
func setupImg ()
{
mainContainer.addSubview(Img)
Img.topAnchor.constraintEqualToAnchor( mainContainer.topAnchor ).active = true
Img.leftAnchor.constraintEqualToAnchor( mainContainer.leftAnchor ).active = true
Img.widthAnchor.constraintEqualToAnchor( mainContainer.widthAnchor ).active = true
Img.heightAnchor.constraintEqualToAnchor( mainContainer.heightAnchor , multiplier: 0.3).active = true
}
var inputContainerBottomConstraint : NSLayoutConstraint?
func setupInputContainer ()
{
mainContainer.addSubview(inputContainer)
inputContainer.topAnchor.constraintEqualToAnchor( Img.bottomAnchor ).active = true
inputContainer.leftAnchor.constraintEqualToAnchor( mainContainer.leftAnchor ).active = true
inputContainer.rightAnchor.constraintEqualToAnchor( mainContainer.rightAnchor ).active = true
inputContainerBottomConstraint = inputContainer.bottomAnchor.constraintEqualToAnchor( cancelButton.topAnchor )
inputContainerBottomConstraint?.active = true
inputContainer.addSubview( datePickerTextField )
inputContainer.addSubview( tagsTextField )
datePickerTextField.topAnchor.constraintEqualToAnchor( inputContainer.topAnchor ).active = true
datePickerTextField.centerXAnchor.constraintEqualToAnchor( inputContainer.centerXAnchor ).active = true
datePickerTextField.widthAnchor.constraintEqualToAnchor( inputContainer.widthAnchor ).active = true
datePickerTextField.heightAnchor.constraintEqualToAnchor( inputContainer.heightAnchor, multiplier: 0.2 ).active = true
tagsTextField.bottomAnchor.constraintEqualToAnchor( inputContainer.bottomAnchor ).active = true
tagsTextField.centerXAnchor.constraintEqualToAnchor( inputContainer.centerXAnchor ).active = true
tagsTextField.widthAnchor.constraintEqualToAnchor( inputContainer.widthAnchor ).active = true
tagsTextField.heightAnchor.constraintEqualToAnchor( inputContainer.heightAnchor, multiplier: 0.2 ).active = true
}
func setupButtons()
{
mainContainer.addSubview( cancelButton )
mainContainer.addSubview( publicarButton )
cancelButton.bottomAnchor.constraintEqualToAnchor( mainContainer.bottomAnchor).active = true
cancelButton.leftAnchor.constraintEqualToAnchor( mainContainer.leftAnchor ).active = true
cancelButton.widthAnchor.constraintEqualToAnchor( mainContainer.widthAnchor, multiplier: 0.5 ).active = true
cancelButton.heightAnchor.constraintEqualToAnchor( mainContainer.heightAnchor, multiplier: 0.1).active = true
publicarButton.bottomAnchor.constraintEqualToAnchor( mainContainer.bottomAnchor).active = true
publicarButton.leftAnchor.constraintEqualToAnchor( cancelButton.rightAnchor ).active = true
publicarButton.widthAnchor.constraintEqualToAnchor( mainContainer.widthAnchor, multiplier: 0.5 ).active = true
publicarButton.heightAnchor.constraintEqualToAnchor( mainContainer.heightAnchor, multiplier: 0.1).active = true
} }
So when the keyboard appears the bottom anchor constant of the scroll view changes so that the keyboard "top anchor" is the new bottom anchor.
With the constraints you have described there's no way for the layout engine to determine the content height of the scroll view. You should pin your bottom text field to the bottom of the scroll view. This way the scroll view's content size will resize up to the max y of all of the text fields. Here is some code you can put in a playground to see:
import UIKit
import XCPlayground
let scrollView = UIScrollView(frame: CGRect(x: 0, y: 0, width: 200, height: 150))
scrollView.backgroundColor = UIColor.whiteColor()
let textField = UITextField()
textField.translatesAutoresizingMaskIntoConstraints = false
textField.backgroundColor = UIColor.purpleColor()
let otherTextField = UITextField()
otherTextField.translatesAutoresizingMaskIntoConstraints = false
otherTextField.backgroundColor = UIColor.purpleColor()
let otherOtherTextField = UITextField()
otherOtherTextField.translatesAutoresizingMaskIntoConstraints = false
otherOtherTextField.backgroundColor = UIColor.purpleColor()
scrollView.addSubview(textField)
textField.topAnchor.constraintEqualToAnchor(scrollView.topAnchor).active = true
textField.leadingAnchor.constraintEqualToAnchor(scrollView.leadingAnchor).active = true
textField.widthAnchor.constraintEqualToAnchor(scrollView.widthAnchor).active = true
scrollView.addSubview(otherTextField)
otherTextField.topAnchor.constraintEqualToAnchor(textField.bottomAnchor, constant: 60).active = true
otherTextField.leadingAnchor.constraintEqualToAnchor(scrollView.leadingAnchor).active = true
otherTextField.widthAnchor.constraintEqualToAnchor(scrollView.widthAnchor).active = true
scrollView.addSubview(otherOtherTextField)
otherOtherTextField.topAnchor.constraintEqualToAnchor(otherTextField.bottomAnchor, constant: 60).active = true
otherOtherTextField.leadingAnchor.constraintEqualToAnchor(scrollView.leadingAnchor).active = true
otherOtherTextField.widthAnchor.constraintEqualToAnchor(scrollView.widthAnchor).active = true
otherOtherTextField.bottomAnchor.constraintEqualToAnchor(scrollView.bottomAnchor).active = true
scrollView.setNeedsLayout()
XCPlaygroundPage.currentPage.liveView = scrollView
This places three text fields in a scroll view with 60 points between the center and top and bottom. If you comment out:
otherOtherTextField.bottomAnchor.constraintEqualToAnchor(scrollView.bottomAnchor).active = true
The scroll view in the assistant editor will not scroll, but with it it does.

Resources