UITextField not working with add constraints programmatically - swift

Here is my code , I am adding UITextfield programtically in scrollview. But UITextField is unable to open keyboard.
It looks like UITextField is not enabling even added user interaction enabled true.
I only use the constraints, no storyboard, no xibs. Only through Constraints Programmatically.
Below is my code :
class SignupViewController : UIViewController {
var backButton : UIButton!
var titleLabel : UILabel!
var navBarView : UIView!
var scrollView : UIScrollView!
var scrollMainView : UIView!
var emailfieldView : UIView!
var emailTextField : UITextField = UITextField() override func viewDidLoad() {
super.viewDidLoad()
setDesign()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(true)
}func setDesign(){
setNavegationBar()
setBackgroundImage()
addScrollView()
}
func setBackgroundImage(){
let backgroundImage = UIImageView(image: UIImage(named: "loginbg.png"))
self.view.addSubview(backgroundImage)
backgroundImage.translatesAutoresizingMaskIntoConstraints = false
let leadingConst = backgroundImage.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 0)
let trailingConst = backgroundImage.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 0)
let topConst = backgroundImage.topAnchor.constraint(equalTo: self.view.topAnchor, constant: 0)
let bottomConst = backgroundImage.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0)
NSLayoutConstraint.activate([leadingConst,trailingConst,topConst,bottomConst])
}
func setNavegationBar(){
navigationItem.title = "Join"
view.backgroundColor = UIColor.white
navigationController?.navigationBar.isHidden = true
navigationController?.navigationBar.tintColor = UIColor.white
navigationController?.navigationBar.titleTextAttributes = [NSAttributedStringKey.foregroundColor: UIColor.white]
setNavBarView()
}
func setNavBarView(){
navBarView = UIView()
self.view.addSubview(navBarView)
navBarView.translatesAutoresizingMaskIntoConstraints = false
let guide = view.safeAreaLayoutGuide
let heightCost = navBarView.heightAnchor.constraint(equalToConstant: 64.0)
let leadingCost = navBarView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 0.0)
let trailingConst = navBarView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 0)
let topCost = navBarView.topAnchor.constraint(equalTo: guide.topAnchor, constant: 0.0)
NSLayoutConstraint.activate([trailingConst,heightCost,topCost,leadingCost])
setBackButton()
setNavTitle()
}
func setBackButton(){
backButton = UIButton(type: UIButtonType.custom)
backButton.setImage(UIImage(named: "join_back"), for: UIControlState.normal)
navBarView.addSubview(backButton)
backButton.translatesAutoresizingMaskIntoConstraints = false
let widthCost = backButton.widthAnchor.constraint(equalToConstant: 44.0)
let heightCost = backButton.heightAnchor.constraint(equalToConstant: 44.0)
let leadingCost = backButton.leadingAnchor.constraint(equalTo: navBarView.leadingAnchor, constant: 0.0)
let topCost = backButton.topAnchor.constraint(equalTo: navBarView.topAnchor, constant: 0.0)
NSLayoutConstraint.activate([widthCost,heightCost,topCost,leadingCost])
backButton.addTarget(self, action: #selector(self.backButtonPress), for: UIControlEvents.touchUpInside)
}
func setNavTitle(){
titleLabel = UILabel()
titleLabel.text = "Join Dubai Store"
titleLabel.font = UIFont(name: "Dubai-Regular", size: 22.0)
titleLabel.textAlignment = NSTextAlignment.center
titleLabel.tintColor = UIColor(hexString: "#353535")
navBarView.addSubview(titleLabel)
titleLabel.translatesAutoresizingMaskIntoConstraints = false
let heightCost = titleLabel.heightAnchor.constraint(equalToConstant: 44.0)
let topCost = titleLabel.topAnchor.constraint(equalTo: navBarView.topAnchor, constant: 0.0)
let centerCost = titleLabel.centerXAnchor.constraint(equalTo: navBarView.centerXAnchor)
NSLayoutConstraint.activate([heightCost,topCost,centerCost])
}
#objc func backButtonPress(){
self.view.endEditing(true)
self.dismissView()
}
func addScrollView(){
scrollView = UIScrollView()
view.addSubview(scrollView)
scrollView.layer.borderWidth = 1.0
scrollView.layer.borderColor = UIColor.red.cgColor
scrollView.translatesAutoresizingMaskIntoConstraints = false
let leadingConst = scrollView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 0)
let trailingConst = scrollView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 0)
let topConst = scrollView.topAnchor.constraint(equalTo: navBarView.bottomAnchor, constant: 0)
let bottomConst = scrollView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: 0)
NSLayoutConstraint.activate([leadingConst,trailingConst,topConst,bottomConst])
addScrollMainView()
}
func addScrollMainView() {
scrollMainView = UIView()
scrollView.addSubview(scrollMainView)
scrollMainView.translatesAutoresizingMaskIntoConstraints = false
let leadingConst = scrollMainView.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor, constant: 0)
let trailingConst = scrollMainView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 0)
let topConst = scrollMainView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 0)
let bottomConst = scrollMainView.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor, constant: 0)
NSLayoutConstraint.activate([topConst,leadingConst,trailingConst,bottomConst])
emailFieldView()
}
func emailFieldView(){
emailfieldView = UIView()
emailfieldView.isUserInteractionEnabled = true
emailfieldView.translatesAutoresizingMaskIntoConstraints = false
scrollMainView.addSubview(emailfieldView)
let topCost = emailfieldView.topAnchor.constraint(equalTo: scrollMainView.topAnchor, constant: 0.0)
let leadingConst = emailfieldView.leadingAnchor.constraint(equalTo: scrollMainView.leadingAnchor, constant: 0)
let trailingConst = emailfieldView.trailingAnchor.constraint(equalTo: scrollMainView.trailingAnchor, constant: 0)
let heightCost = emailfieldView.heightAnchor.constraint(equalToConstant: 62.0)
NSLayoutConstraint.activate([trailingConst,heightCost,topCost,leadingConst])
//emailTextField = UITextField(frame: CGRect(x: 10, y: 0, width: SCREEN_WIDTH, height: 50))
emailTextField.placeholder = "Email"
emailTextField.layer.borderColor = UIColor.red.cgColor
emailTextField.layer.borderWidth = 1.0
// emailTextField.font = UIFont.systemFont(ofSize: 15)
// emailTextField.borderStyle = UITextBorderStyle.none
// emailTextField.keyboardType = UIKeyboardType.default
// emailTextField.returnKeyType = UIReturnKeyType.done
// //emailTextField.clearButtonMode = UITextFieldViewMode.whileEditing
emailTextField.isUserInteractionEnabled = true
emailTextField.allowsEditingTextAttributes = true
//emailTextField.contentVerticalAlignment = UIControlContentVerticalAlignment.center
emailTextField.addTarget(self, action: #selector(self.textFieldShouldBeginEditing), for: UIControlEvents.touchUpInside)
emailfieldView.addSubview(emailTextField)
emailTextField.translatesAutoresizingMaskIntoConstraints = false
emailTextField.contentMode = UIViewContentMode.left
emailTextField.delegate = self
let etopCost = emailTextField.topAnchor.constraint(equalTo: emailfieldView.topAnchor, constant: 0.0)
let eleadingConst = emailTextField.leadingAnchor.constraint(equalTo: emailfieldView.leadingAnchor, constant: 10)
let etrailingConst = emailTextField.trailingAnchor.constraint(equalTo: emailfieldView.trailingAnchor, constant: -10)
let eheightCost = emailTextField.heightAnchor.constraint(equalToConstant: 50.0)
NSLayoutConstraint.activate([etopCost,eleadingConst,etrailingConst,eheightCost])
self.scrollMainView.bringSubview(toFront: emailTextField)
emailTextField.isAccessibilityElement = true
} }
extension SignupViewController: UITextFieldDelegate {
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
// return NO to disallow editing.
print("TextField should begin editing method called")
return true
}
func textFieldDidBeginEditing(_ textField: UITextField) {
// became first responder
print("TextField did begin editing method called")
}
func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
// return YES to allow editing to stop and to resign first responder status. NO to disallow the editing session to end
print("TextField should snd editing method called")
return true
}
func textFieldDidEndEditing(_ textField: UITextField) {
// may be called if forced even if shouldEndEditing returns NO (e.g. view removed from window) or endEditing:YES called
print("TextField did end editing method called")
}
func textFieldDidEndEditing(_ textField: UITextField, reason: UITextFieldDidEndEditingReason) {
// if implemented, called in place of textFieldDidEndEditing:
print("TextField did end editing with reason method called")
}
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
// return NO to not change text
print("While entering the characters this method gets called")
return true
}
func textFieldShouldClear(_ textField: UITextField) -> Bool {
// called when clear button pressed. return NO to ignore (no notifications)
print("TextField should clear method called")
return true
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
// called when 'return' key pressed. return NO to ignore.
print("TextField should return method called")
// may be useful: textField.resignFirstResponder()
return true
}
}

I just run your code, it looks like scrollMainView is not visible in the views' hierarchy. Just change the constraints. Here is the code:
func addScrollMainView() {
scrollMainView = UIView()
scrollView.addSubview(scrollMainView)
scrollMainView.translatesAutoresizingMaskIntoConstraints = false
let leadingConst = scrollMainView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 0)
let trailingConst = scrollMainView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: 0)
let topConst = scrollMainView.topAnchor.constraint(equalTo: scrollView.topAnchor, constant: 0)
let bottomConst = scrollMainView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: 0)
NSLayoutConstraint.activate([topConst,leadingConst,trailingConst,bottomConst])
emailFieldView()
}
BTW, It is not related to your question, but it is better to create bg at the beginning. Just use the code below:
func setDesign(){
setBackgroundImage()
setNavegationBar()
addScrollView()
}

Related

UITextView with Adjustable Font Size

I tried to make an editable uitextview with centered text that can have a maximum of 2 lines and that automatically adjusts its font size in order to fit its text within a fixed width and height.
My solution: Type some text in a UITextView, automatically copy that text and paste it in a uilabel that itself automatically adjusts its font size perfectly, and then retrieve the newly adjusted font size of the uilabel and set that size on the UITextView text.
I have spent about a month on this and repeatedly failed. I can't find a way to make it work. My attempted textview below glitches some letters out and hides large portions of out-of-bounds text instead of resizing everything. Please help me stack overflow Gods.
My attempt:
import UIKit
class TextViewViewController: UIViewController{
private let editableUITextView: UITextView = {
let tv = UITextView()
tv.font = UIFont.systemFont(ofSize: 20)
tv.text = "Delete red text, and type here"
tv.backgroundColor = .clear
tv.textAlignment = .center
tv.textContainer.maximumNumberOfLines = 2
tv.textContainer.lineBreakMode = .byWordWrapping
tv.textColor = .red
return tv
}()
private let correctTextSizeLabel: UILabel = {
let tv = UILabel()
tv.font = UIFont.systemFont(ofSize: 20)
tv.backgroundColor = .clear
tv.text = "This is properly resized"
tv.adjustsFontSizeToFitWidth = true
tv.lineBreakMode = .byTruncatingTail
tv.numberOfLines = 2
tv.textAlignment = .center
tv.textColor = .green
return tv
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
view.addSubview(correctTextSizeLabel)
view.addSubview(editableUITextView)
editableUITextView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
editableUITextView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
editableUITextView.heightAnchor.constraint(equalToConstant: 150).isActive = true
editableUITextView.widthAnchor.constraint(equalToConstant: 150).isActive = true
editableUITextView.translatesAutoresizingMaskIntoConstraints = false
editableUITextView.delegate = self
correctTextSizeLabel.leftAnchor.constraint(equalTo: editableUITextView.leftAnchor).isActive = true
correctTextSizeLabel.rightAnchor.constraint(equalTo: editableUITextView.rightAnchor).isActive = true
correctTextSizeLabel.topAnchor.constraint(equalTo: editableUITextView.topAnchor).isActive = true
correctTextSizeLabel.bottomAnchor.constraint(equalTo: editableUITextView.bottomAnchor).isActive = true
correctTextSizeLabel.translatesAutoresizingMaskIntoConstraints = false
editableUITextView.isScrollEnabled = false
}
func getApproximateAdjustedFontSizeOfLabel(label: UILabel) -> CGFloat {
if label.adjustsFontSizeToFitWidth == true {
var currentFont: UIFont = label.font
let originalFontSize = currentFont.pointSize
var currentSize: CGSize = (label.text! as NSString).size(withAttributes: [NSAttributedString.Key.font: currentFont])
while currentSize.width > label.frame.size.width * 2 && currentFont.pointSize > (originalFontSize * label.minimumScaleFactor) {
currentFont = currentFont.withSize(currentFont.pointSize - 1)
currentSize = (label.text! as NSString).size(withAttributes: [NSAttributedString.Key.font: currentFont])
}
return currentFont.pointSize
} else {
return label.font.pointSize
}
}
}
//MARK: - UITextViewDelegate
extension TextViewViewController : UITextViewDelegate {
private func textViewShouldBeginEditing(_ textView: UITextView) {
textView.becomeFirstResponder()
}
func textViewDidBeginEditing(_ textView: UITextView) {
}
func textViewDidEndEditing(_ textView: UITextView) {
}
func textViewDidChange(_ textView: UITextView) {
textView.becomeFirstResponder()
self.correctTextSizeLabel.text = textView.text
self.correctTextSizeLabel.isHidden = false
let estimatedTextSize = self.getApproximateAdjustedFontSizeOfLabel(label: self.correctTextSizeLabel)
print("estimatedTextSize: ",estimatedTextSize)
self.editableUITextView.font = UIFont.systemFont(ofSize: estimatedTextSize)
}
}
UITextField's have the option to automatically adjust font size to fit a fixed width but they only allow 1 line of text, I need it to have a maximum of 2. UILabel's solve this problem perfectly but they aren't editable.
After some searching, this looks like it will be very difficult to get working as desired.
This doesn't directly answer your question, but it may be an option:
Here's the example code:
class TestInputViewController: UIViewController {
let testLabel: InputLabel = InputLabel()
override func viewDidLoad() {
super.viewDidLoad()
let instructionLabel = UILabel()
instructionLabel.textAlignment = .center
instructionLabel.text = "Tap yellow label to edit..."
let centeringFrameView = UIView()
// label properties
let fnt: UIFont = .systemFont(ofSize: 32.0)
testLabel.isUserInteractionEnabled = true
testLabel.font = fnt
testLabel.adjustsFontSizeToFitWidth = true
testLabel.minimumScaleFactor = 0.25
testLabel.numberOfLines = 2
testLabel.setContentHuggingPriority(.required, for: .vertical)
let minLabelHeight = ceil(fnt.lineHeight)
// so we can see the frames
centeringFrameView.backgroundColor = .red
testLabel.backgroundColor = .yellow
[centeringFrameView, instructionLabel, testLabel].forEach {
$0.translatesAutoresizingMaskIntoConstraints = false
}
view.addSubview(instructionLabel)
view.addSubview(centeringFrameView)
centeringFrameView.addSubview(testLabel)
let g = view.safeAreaLayoutGuide
NSLayoutConstraint.activate([
// instruction label centered at top
instructionLabel.topAnchor.constraint(equalTo: g.topAnchor, constant: 20.0),
instructionLabel.centerXAnchor.constraint(equalTo: g.centerXAnchor),
// centeringFrameView 20-pts from instructionLabel bottom
centeringFrameView.topAnchor.constraint(equalTo: instructionLabel.bottomAnchor, constant: 20.0),
// Leading / Trailing with 20-pts "padding"
centeringFrameView.leadingAnchor.constraint(equalTo: g.leadingAnchor, constant: 20.0),
centeringFrameView.trailingAnchor.constraint(equalTo: g.trailingAnchor, constant: -20.0),
// test label centered vertically in centeringFrameView
testLabel.centerYAnchor.constraint(equalTo: centeringFrameView.centerYAnchor, constant: 0.0),
// Leading / Trailing with 20-pts "padding"
testLabel.leadingAnchor.constraint(equalTo: centeringFrameView.leadingAnchor, constant: 20.0),
testLabel.trailingAnchor.constraint(equalTo: centeringFrameView.trailingAnchor, constant: -20.0),
// height will be zero if label has no text,
// so give it a min height of one line
testLabel.heightAnchor.constraint(greaterThanOrEqualToConstant: minLabelHeight),
// centeringFrameView height = 3 * minLabelHeight
centeringFrameView.heightAnchor.constraint(equalToConstant: minLabelHeight * 3.0)
])
// to handle user input
testLabel.editCallBack = { [weak self] str in
guard let self = self else { return }
self.testLabel.text = str
}
testLabel.doneCallBack = { [weak self] in
guard let self = self else { return }
// do something when user taps done / enter
}
let t = UITapGestureRecognizer(target: self, action: #selector(self.labelTapped(_:)))
testLabel.addGestureRecognizer(t)
}
#objc func labelTapped(_ g: UITapGestureRecognizer) -> Void {
testLabel.becomeFirstResponder()
testLabel.inputContainerView.theTextView.text = testLabel.text
testLabel.inputContainerView.theTextView.becomeFirstResponder()
}
}
class InputLabel: UILabel {
var editCallBack: ((String) -> ())?
var doneCallBack: (() -> ())?
override var canBecomeFirstResponder: Bool {
return true
}
override var canResignFirstResponder: Bool {
return true
}
override var inputAccessoryView: UIView? {
get { return inputContainerView }
}
lazy var inputContainerView: CustomInputAccessoryView = {
let customInputAccessoryView = CustomInputAccessoryView(frame: .zero)
customInputAccessoryView.backgroundColor = .blue
customInputAccessoryView.editCallBack = { [weak self] str in
guard let self = self else { return }
self.editCallBack?(str)
}
customInputAccessoryView.doneCallBack = { [weak self] in
guard let self = self else { return }
self.resignFirstResponder()
}
return customInputAccessoryView
}()
}
class CustomInputAccessoryView: UIView, UITextViewDelegate {
var editCallBack: ((String) -> ())?
var doneCallBack: (() -> ())?
let theTextView: UITextView = {
let tv = UITextView()
tv.isScrollEnabled = false
tv.font = .systemFont(ofSize: 16)
tv.autocorrectionType = .no
tv.returnKeyType = .done
return tv
}()
override init(frame: CGRect) {
super.init(frame: frame)
backgroundColor = UIColor.white
autoresizingMask = [.flexibleHeight, .flexibleWidth]
addSubview(theTextView)
theTextView.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
// constraint text view with 8-pts "padding" on all 4 sides
theTextView.topAnchor.constraint(equalTo: topAnchor, constant: 8),
theTextView.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 8),
theTextView.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -8),
theTextView.bottomAnchor.constraint(equalTo: bottomAnchor, constant: -8),
])
theTextView.delegate = self
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if (text == "\n") {
textView.resignFirstResponder()
doneCallBack?()
}
return true
}
func textViewDidChange(_ textView: UITextView) {
editCallBack?(textView.text ?? "")
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override var intrinsicContentSize: CGSize {
return .zero
}
}

setup google maps as view

after I finish setting up google maps I have added three subviews UIButton it's clickable I think its works fine, and UIView and on the top of the UIView I have added UITextField as (Subview) But I can't use it I can't input anything it's not editable
so when I comment google map code everything works fine the textField that I but in UIView will allow editing works fine
import UIKit
import GoogleMaps
class GoogleMap: UIViewController, UITextFieldDelegate {
let locationBtn: UIButton = {
let button = UIButton(type: .system)
button.addTarget(self, action: #selector(orderBtnAction), for: UIControl.Event.touchUpInside)
button.setTitle("إستخدام هذا الموقع", for: UIControl.State.normal)
button.titleLabel?.font = UIFont.systemFont(ofSize: 15)
button.tintColor = UIColor.white
button.layer.cornerRadius = 10
button.backgroundColor = UIColor.delevareColor
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
let locationView: UIView = {
let view = UIView()
view.layer.cornerRadius = 15
view.backgroundColor = UIColor.white
view.layer.shadowPath = UIBezierPath(rect: view.bounds).cgPath
view.layer.shadowRadius = 5
view.layer.shadowOffset = .zero
view.layer.shadowOpacity = 1
view.clipsToBounds = true
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
let currentLocTextField: UITextField = {
let textField = UITextField()
textField.text = "جاري تحميل موقعك..."
textField.font = UIFont.boldSystemFont(ofSize: 19)
textField.textColor = UIColor.black
textField.borderStyle = .roundedRect
textField.isUserInteractionEnabled = true
textField.translatesAutoresizingMaskIntoConstraints = false
textField.textAlignment = .center
return textField
}()
var locationManager = CLLocationManager()
var mapView: GMSMapView!
override func viewDidLoad() {
super.viewDidLoad()
currentLocTextField.delegate = self
locationView.addSubview(currentLocTextField)
setUpNavigationController()
setUpGoogleMap()
setUpLayout()
}
func setUpLayout() {
locationBtn.heightAnchor.constraint(equalToConstant: 50).isActive = true
locationBtn.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
locationBtn.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -25).isActive = true
locationBtn.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 10).isActive = true
locationBtn.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -10).isActive = true
locationView.heightAnchor.constraint(equalToConstant: 120).isActive = true
locationView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
locationView.bottomAnchor.constraint(equalTo: locationBtn.topAnchor, constant: -10).isActive = true
locationView.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 10).isActive = true
locationView.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -10).isActive = true
currentLocTextField.heightAnchor.constraint(equalToConstant: 30).isActive = true
currentLocTextField.centerXAnchor.constraint(equalTo: locationView.centerXAnchor).isActive = true
currentLocTextField.topAnchor.constraint(equalTo: locationView.topAnchor, constant: 20).isActive = true
currentLocTextField.leftAnchor.constraint(equalTo: locationView.leftAnchor, constant: 20).isActive = true
currentLocTextField.rightAnchor.constraint(equalTo: locationView.rightAnchor, constant: -50).isActive = true
}
func setUpGoogleMap(){
let camera = GMSCameraPosition.camera(withLatitude: 15.592778, longitude: 32.552278, zoom: 12)
mapView = GMSMapView.map(withFrame: .zero, camera: camera)
view = mapView
mapView.animate(to: camera)
mapView.isMyLocationEnabled = true
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
mapView.delegate = self
mapView.addSubview(locationBtn)
mapView.addSubview(locationView)
}
}
extension GoogleMap: CLLocationManagerDelegate {
func locationManager(_ manager: CLLocationManager, didChangeAuthorization status: CLAuthorizationStatus) {
guard status == .authorizedWhenInUse else {
return
}
locationManager.startUpdatingLocation()
mapView.isMyLocationEnabled = true
mapView.settings.myLocationButton = true
}
func locationManager(_ manager: CLLocationManager, didUpdateLocations locations: [CLLocation]) {
guard let location = locations.first else {
return
}
// 7
mapView.camera = GMSCameraPosition(target: location.coordinate, zoom: 15, bearing: 0, viewingAngle: 0)
// 8
locationManager.stopUpdatingLocation()
}
}
extension GoogleMap: GMSMapViewDelegate {
func mapView(_ mapView: GMSMapView, willMove gesture: Bool) {
return
}
func mapView(_ mapView: GMSMapView, idleAt position: GMSCameraPosition) {
if #available(iOS 11.0, *) {
reverseGeocodeCoordinate(position.target)
} else {
// Fallback on earlier versions
}
}
}
Change you setup method
func setUpGoogleMap(){
let camera = GMSCameraPosition.camera(withLatitude: 15.592778, longitude: 32.552278, zoom: 12)
mapView = GMSMapView.map(withFrame: self.view.bounds, camera: camera)
view .addSubview( mapView)
mapView.animate(to: camera)
mapView.isMyLocationEnabled = true
locationManager.delegate = self
locationManager.requestWhenInUseAuthorization()
mapView.delegate = self
// mapView.translatesAutoresizingMaskIntoConstraints = false
self.view.addSubview(locationBtn)
self.view.addSubview(locationView)
}

UITextField is partially hidden by Keyboard when opened

I am attempting to create a collection of UITextField elements. I'd like the next button on the keyboard to skip to the next field and if that field is hidden from view by the keyboard, scroll it into view.
This is my attempt. It works apart from 1 aspect.
When dismissing the keyboard and then selecting another (or the same) field, the text input is partially hidden by the keyboard (see attached gif).
The meat and potatoes is within the ViewController extension.
class ViewController: UIViewController {
var activeField: UITextField?
var lastOffset: CGPoint!
var keyboardHeight: CGFloat!
let scrollView: UIScrollView = {
let scrollView = UIScrollView()
scrollView.translatesAutoresizingMaskIntoConstraints = false
return scrollView
}()
let scrollViewContainer: UIStackView = {
let view = UIStackView()
view.axis = .vertical
view.spacing = 10
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
view.addSubview(scrollView)
scrollView.addSubview(scrollViewContainer)
let totalFieldCount = 25
for i in 1...totalFieldCount {
let textField = createTextField(self, placeholder: "Field #\(i)", type: .default)
textField.returnKeyType = i < totalFieldCount ? .next : .done
textField.tag = i
scrollViewContainer.addArrangedSubview(textField)
}
NSLayoutConstraint.activate([
scrollView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
scrollView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
scrollView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
scrollView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
scrollViewContainer.leadingAnchor.constraint(equalTo: scrollView.leadingAnchor),
scrollViewContainer.trailingAnchor.constraint(equalTo: scrollView.trailingAnchor),
scrollViewContainer.topAnchor.constraint(equalTo: scrollView.topAnchor),
scrollViewContainer.bottomAnchor.constraint(equalTo: scrollView.bottomAnchor),
scrollViewContainer.widthAnchor.constraint(equalTo: scrollView.widthAnchor)
])
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: UIResponder.keyboardWillShowNotification, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: UIResponder.keyboardWillHideNotification, object: nil)
scrollView.keyboardDismissMode = .interactive
}
func createTextField(_ delegate: UITextFieldDelegate?, placeholder: String, type: UIKeyboardType, isSecureEntry: Bool = false) -> UITextField {
let tf = UITextField(frame: .zero)
tf.placeholder = placeholder
tf.backgroundColor = .init(white: 0, alpha: 0.03)
tf.borderStyle = .roundedRect
tf.font = .systemFont(ofSize: 14)
tf.keyboardType = type
tf.autocapitalizationType = .none
tf.autocorrectionType = .no
tf.isSecureTextEntry = isSecureEntry
tf.heightAnchor.constraint(equalToConstant: 40).isActive = true
if let delegate = delegate {
tf.delegate = delegate
}
return tf
}
}
extension ViewController: UITextFieldDelegate {
func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
activeField = textField
lastOffset = self.scrollView.contentOffset
return true
}
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
let nextTag = textField.tag + 1
if let nextResponder = textField.superview?.viewWithTag(nextTag) {
nextResponder.becomeFirstResponder()
} else {
activeField?.resignFirstResponder()
activeField = nil
}
return true
}
}
extension ViewController {
#objc func keyboardWillShow(notification: NSNotification) {
guard keyboardHeight == nil else { return }
if let keyboardSize = (notification.userInfo?[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue {
keyboardHeight = keyboardSize.height
UIView.animate(withDuration: 0.3, animations: {
self.scrollView.contentInset.bottom = self.keyboardHeight
})
guard let activeField = activeField else { return }
let distanceToBottom = self.scrollView.frame.size.height - (activeField.frame.origin.y) - (activeField.frame.size.height)
let collapseSpace = keyboardHeight - distanceToBottom
guard collapseSpace > 0 else { return }
UIView.animate(withDuration: 0.3, animations: {
self.scrollView.contentOffset = CGPoint(x: self.lastOffset.x, y: collapseSpace + 10)
})
}
}
#objc func keyboardWillHide(notification: NSNotification) {
UIView.animate(withDuration: 0.3) {
self.scrollView.contentOffset = self.lastOffset
self.scrollView.contentInset.bottom = 0
}
keyboardHeight = nil
}
}
Replace keyboardFrameBeginUserInfoKey with keyboardFrameEndUserInfoKey

Text overlapping with custom button in TextView swift

Problem: Im trying to build a "comment" component to my app. I have managed to create a textview that expands as more text gets typed, and also created a button within the textview that will stay top right corner at all times. However when i write text, the text will go under the button and is not visible. What i want is that the text does not overlap the button, and instead just stays away from the button.
Question
How can i achieve this ?
This is my code:
class ClickedOnPostViewController: UIViewController, UITextFieldDelegate, UITextViewDelegate {
var answersOf: Answer?
#IBOutlet weak var tableView: UITableView!
#IBOutlet weak var commentText: UITextView!
override func viewDidLoad() {
super.viewDidLoad()
commentText.translatesAutoresizingMaskIntoConstraints = false
[
commentText.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
commentText.leadingAnchor.constraint(equalTo: view.leadingAnchor),
commentText.trailingAnchor.constraint(equalTo: view.trailingAnchor),
commentText.heightAnchor.constraint(equalToConstant: 43)
].forEach{ $0.isActive = true }
commentText.addSubview(button)
button.heightAnchor.constraint(equalToConstant: 50).isActive = true
button.widthAnchor.constraint(equalToConstant: 100).isActive = true
button.topAnchor.constraint(equalTo: commentText.topAnchor).isActive = true
button.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
view.bringSubview(toFront: button)
commentText.delegate = self
commentText.isScrollEnabled = false
//Keyboard listeners
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow(notification:)), name: NSNotification.Name.UIKeyboardDidShow, object: nil)
NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(notification:)), name: NSNotification.Name.UIKeyboardDidHide, object: nil)
// qNotificationCenter.default.addObserver(self, selector: #selector(keyboardWillChange(notification:)), name: NSNotification.Name.UIKeyboardWillChangeFrame, object: nil)
// Do any additional setup after loading the view.
}
let button: UIButton = {
let button = UIButton(type: .system)
button.backgroundColor = .orange
button.setTitle("Click Me", for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
#objc func keyboardWillShow(notification: NSNotification) {
if let keyboardSize = (notification.userInfo?[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
if self.view.frame.origin.y == 0 {
self.view.frame.origin.y -= keyboardSize.height
}
}
}
#objc func keyboardWillHide(notification: NSNotification) {
if self.view.frame.origin.y != 0 {
self.view.frame.origin.y = 0
}
}
#IBAction func refresh(_ sender: Any) {
}
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
if text == "\n" {
commentText.resignFirstResponder()
return false
}
return true
}
func textViewDidChange(_ textView: UITextView) {
let size = CGSize(width: view.frame.width, height: .infinity)
let estimatedSize = textView.sizeThatFits(size)
textView.constraints.forEach { (constraints) in
if constraints.firstAttribute == .height {
constraints.constant = estimatedSize.height
}
}
}
}
UPDATE issues with Sh_Khan current answer:
Before typing the last character that will overlap button
After typing the last character that will overlap button
You need
commentText.translatesAutoresizingMaskIntoConstraints = false
button.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(commentText)
view.addSubview(button)
NSLayoutConstraint.activate([
commentText.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
commentText.leadingAnchor.constraint(equalTo: view.leadingAnchor),
commentText.heightAnchor.constraint(equalToConstant: 43),
button.heightAnchor.constraint(equalToConstant: 50),
button.widthAnchor.constraint(equalToConstant: 100),
button.topAnchor.constraint(equalTo: commentText.topAnchor),
button.trailingAnchor.constraint(equalTo: view.trailingAnchor),
button.leadingAnchor.constraint(equalTo: commentText.trailingAnchor,constant:20)
])
commentText.delegate = self
commentText.isScrollEnabled = false
Don't mix RTL with LTR logic in your case using rightAnchor with trailingAnchor
If the UI of comment textfield is build in storyboard / xib , don't set constraints for it again
to have the width of textView = 80% , remove this
button.heightAnchor.constraint(equalToConstant: 50),
and add this
commentText.widthAnchor.constraint(equalTo: view.widthAnchor,multiplier:0.8,constant:-20),

fetch data from Firebase using autoID - Xcode

On the top level of my app I have a tableViewController where you can create new jobs that are saved to my firebase database using an autoID.
Here is the JSON
{
"jobInfo" : {
"-L59sEGslWF7HFza26ay" : {
"FPS" : "25",
"director" : "Mike & Jim",
"jobBrand" : "Honda",
"jobName" : "Dreammakers"
},
"-L59sWGEccWMFEeFWyNU" : {
"FPS" : "25",
"director" : "Anthony Test",
"jobBrand" : "WWF",
"jobName" : "Eye"
}
}
}
This is the code that links you to the UITabBarController:
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let jobInfo = page_jobTabController()
show(jobInfo, sender: self)
}
You can then click on one of the cells which takes you to a UItabBarViewController that has 4 tabs. In the first tab I have several textFields that lists information about the job.
I am struggling to work out how to send the autoID from the UITableViewController through the UITabBarController to the UIViewController so the textFields can be filled in with the correct information.
Here is a screenshot of the two pages to get an idea of what I want to do.
Sorry to dump all this code below - I am not trying to spam.
This is my dictionary:
class Job: NSObject {
var id: String?
var jobBrand: String?
var jobName : String?
var directorName : String?
var FPSvalue : String?
init(dictionary: [String: AnyObject]) {
self.id = dictionary["id"] as? String
self.jobBrand = dictionary["jobBrand"] as? String
self.jobName = dictionary["jobName"] as? String
self.directorName = dictionary["directorName"] as? String
self.FPSvalue = dictionary["FPSvalue"] as? String
}
}
This is my jobList page (top level)
class page_jobList: UITableViewController {
let cellId = "cellId"
var jobs = [Job]()
override func viewDidLoad() {
super.viewDidLoad()
// NAVIGATION ITEM
navigationItem.title = "Jobs"
navigationController?.navigationBar.prefersLargeTitles = true
tableView.register(JobCell.self, forCellReuseIdentifier: cellId)
// FIREBASE FETCH JOBS
fetchJobs()
}
// FETCH JOBS
func fetchJobs() {
Database.database().reference().child("jobInfo").observe(.childAdded) { (snapshot) in
if let dictionary = snapshot.value as? [String: AnyObject] {
print (snapshot)
// PROCESSES VALUES RECEIVED FROM SERVER
if ( snapshot.value is NSNull ) {
// DATA WAS NOT FOUND
print("– – – Data was not found – – –")
} else {
let job = Job(dictionary: dictionary)
job.id = snapshot.key
self.jobs.append(job)
//this will crash because of background thread, use dispatch_async to fix
DispatchQueue.main.async(execute: {
self.tableView.reloadData()
})
}
}
}
}
// AFTER DATA IS FETCHED AND ADD IT TO TABLE VIEW
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return jobs.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
let job = jobs[indexPath.row]
cell.accessoryType = UITableViewCellAccessoryType.disclosureIndicator
cell.textLabel?.text = job.jobBrand
cell.detailTextLabel?.text = job.jobName
return cell
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 72
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let jobInfo = page_jobTabController()
jobInfo.job? = jobs[indexPath.row]
show(jobInfo, sender: self)
}
}
class JobCell: UITableViewCell {
override init(style: UITableViewCellStyle, reuseIdentifier: String?){
super .init(style: .subtitle, reuseIdentifier: reuseIdentifier)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implented")
}
}
This is my tabBarController:
class page_jobTabController: UITabBarController {
override func viewDidLoad() {
super.viewDidLoad()
// NAVIGATION ITEM
let jobInfo = page_jobInformation()
jobInfo.job? = job!
let shots = page_shotList()
let attachments = page_attachments()
let notes = page_notesList()
jobInfo.tabBarItem.title = "Information"
jobInfo.tabBarItem.image = UIImage(named: "jobInfo")
shots.tabBarItem.title = "Shots"
shots.tabBarItem.image = UIImage(named: "shots")
attachments.tabBarItem.title = "Attachments"
attachments.tabBarItem.image = UIImage(named: "attachments")
notes.tabBarItem.title = "Notes"
notes.tabBarItem.image = UIImage(named: "notes")
viewControllers = [jobInfo, shots, attachments, notes]
}
#IBAction func HandleEdit(sender : UIButton) {
let transition = CATransition()
transition.duration = 0.5
transition.type = kCATransitionPush
transition.subtype = kCATransitionFromRight
transition.timingFunction = CAMediaTimingFunction(name:kCAMediaTimingFunctionEaseInEaseOut)
view.window!.layer.add(transition, forKey: kCATransition)
}
}
This is my jobInfo tab ViewController
class page_jobInformation: UIViewController{
// CONTENT CREATION
// GENERAL
let generalTitle: UILabel = {
let generalTitle = UILabel()
generalTitle.font = UIFont(name: "HelveticaNeue", size: 12.0)
generalTitle.text = "GENERAL"
generalTitle.translatesAutoresizingMaskIntoConstraints = false
return generalTitle
}()
let jobBrand: UITextField = {
let jobBrand = UITextField()
//jobBrand.text = "jobBrand"
jobBrand.isUserInteractionEnabled = false
jobBrand.keyboardType = UIKeyboardType.default
jobBrand.translatesAutoresizingMaskIntoConstraints = false
return jobBrand
}()
let jobName: UITextField = {
let jobName = UITextField()
jobName.keyboardType = UIKeyboardType.default
jobName.text = "jobName"
jobName.isUserInteractionEnabled = false
jobName.translatesAutoresizingMaskIntoConstraints = false
return jobName
}()
let directorName: UITextField = {
let directorName = UITextField()
directorName.text = "directorName"
directorName.keyboardType = UIKeyboardType.default
directorName.isUserInteractionEnabled = false
directorName.translatesAutoresizingMaskIntoConstraints = false
return directorName
}()
let AgencyName: UITextField = {
let AgencyName = UITextField()
AgencyName.text = "Agency"
AgencyName.keyboardType = UIKeyboardType.default
AgencyName.isUserInteractionEnabled = false
AgencyName.translatesAutoresizingMaskIntoConstraints = false
return AgencyName
}()
let prodCoName: UITextField = {
let prodCoName = UITextField()
prodCoName.text = "Production Company"
prodCoName.keyboardType = UIKeyboardType.default
prodCoName.isUserInteractionEnabled = false
prodCoName.translatesAutoresizingMaskIntoConstraints = false
return prodCoName
}()
// TECHNICAL
let technicalTitle: UILabel = {
let technicalTitle = UILabel()
technicalTitle.font = UIFont(name: "HelveticaNeue", size: 12.0)
technicalTitle.text = "TECHNICAL"
technicalTitle.translatesAutoresizingMaskIntoConstraints = false
return technicalTitle
}()
lazy var jobSpecsButton: UIButton = {
let jobSpecsButton = UIButton(type: .system)
jobSpecsButton.setTitle("Job Specifications", for: .normal)
jobSpecsButton.titleLabel?.font = UIFont(name: "HelveticaNeue", size: 14.0)
jobSpecsButton.layer.masksToBounds = true
jobSpecsButton.contentHorizontalAlignment = .left
jobSpecsButton.setTitleColor(UIColor.gray, for: UIControlState.normal)
jobSpecsButton.backgroundColor = UIColor(red:1.00, green:1.00, blue:1.00, alpha:1.0)
jobSpecsButton.setTitleColor(.black, for: .normal)
jobSpecsButton.translatesAutoresizingMaskIntoConstraints = false
jobSpecsButton.addTarget(self, action: #selector(HandleJobSpecs), for: .touchUpInside)
return jobSpecsButton
}()
lazy var cameraButton: UIButton = {
let cameraButton = UIButton(type: .system)
cameraButton.setTitle("Camera & Lenses", for: .normal)
cameraButton.titleLabel?.font = UIFont(name: "HelveticaNeue", size: 14.0)
cameraButton.layer.masksToBounds = true
cameraButton.contentHorizontalAlignment = .left
cameraButton.setTitleColor(UIColor.gray, for: UIControlState.normal)
cameraButton.backgroundColor = UIColor(red:1.00, green:1.00, blue:1.00, alpha:1.0)
cameraButton.setTitleColor(.black, for: .normal)
cameraButton.translatesAutoresizingMaskIntoConstraints = false
cameraButton.addTarget(self, action: #selector(HandleCameraLenses), for: .touchUpInside)
return cameraButton
}()
lazy var SKCButton: UIButton = {
let SKCButton = UIButton(type: .system)
SKCButton.setTitle("Shoot Kit Checklist", for: .normal)
SKCButton.titleLabel?.font = UIFont(name: "HelveticaNeue", size: 14.0)
SKCButton.layer.masksToBounds = true
SKCButton.contentHorizontalAlignment = .left
SKCButton.setTitleColor(UIColor.gray, for: UIControlState.normal)
SKCButton.backgroundColor = UIColor(red:1.00, green:1.00, blue:1.00, alpha:1.0)
SKCButton.setTitleColor(.black, for: .normal)
SKCButton.translatesAutoresizingMaskIntoConstraints = false
SKCButton.addTarget(self, action: #selector(HandleSKC), for: .touchUpInside)
return SKCButton
}()
// STACKED VIEWS
lazy var stack:UIStackView = {
let s = UIStackView(frame: self.view.bounds)
s.axis = .vertical
s.distribution = .equalSpacing
s.alignment = .fill
s.spacing = 10
//s.autoresizingMask = [.flexibleWidth, .flexibleHeight]
s.addArrangedSubview(self.generalTitle)
s.addArrangedSubview(self.jobBrand)
s.addArrangedSubview(self.jobName)
s.addArrangedSubview(self.directorName)
s.addArrangedSubview(self.AgencyName)
s.addArrangedSubview(self.prodCoName)
s.addArrangedSubview(self.technicalTitle)
s.addArrangedSubview(self.jobSpecsButton)
s.addArrangedSubview(self.cameraButton)
s.addArrangedSubview(self.SKCButton)
return s
}()
// SUPER VIEW DID LOAD
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white
}
// VIEW WILL APPEAR
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
self.tabBarController?.navigationItem.title = "Job Information"
self.tabBarController?.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .edit, target: self, action: #selector(HandleEditJob))
view.addSubview(stack)
jobInfoValues()
setupLayout()
}
// OBSERVE JOB
var job: Job?
// FILL IN TEXT FIELDS FROM FIREBASE
func jobInfoValues(){
jobBrand.text = job?.jobBrand
jobName.text = job?.jobName
directorName.text = job?.directorName
}
// BUTTONS & ACTIONS
#IBAction func HandleJobSpecs(sender : UIButton) {
let jobSpecs = page_jobSpecs()
show(jobSpecs, sender: self)
}
#IBAction func HandleCameraLenses(sender : UIButton) {
let cameras = page_camera_lenses()
show(cameras, sender: self)
}
#IBAction func HandleSKC(sender : UIButton) {
let shootKit = page_SKC()
show(shootKit, sender: self)
}
#IBAction func HandleEditJob(sender : UIButton) {
// CHANGE NAVIGATION BAR ITEM
self.tabBarController?.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(HandleJobEditDone))
// ALLOW TEXT FIELDS TO BE EDITABLE
jobBrand.isUserInteractionEnabled = true
jobName.isUserInteractionEnabled = true
directorName.isUserInteractionEnabled = true
AgencyName.isUserInteractionEnabled = true
prodCoName.isUserInteractionEnabled = true
// ADDING CLEAR BUTTON
jobBrand.clearButtonMode = .always
jobName.clearButtonMode = .always
directorName.clearButtonMode = .always
AgencyName.clearButtonMode = .always
prodCoName.clearButtonMode = .always
}
#IBAction func HandleJobEditDone(sender : UIButton) {
self.tabBarController?.navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .edit, target: self, action: #selector(HandleEditJob))
jobBrand.isUserInteractionEnabled = false
jobName.isUserInteractionEnabled = false
directorName.isUserInteractionEnabled = false
AgencyName.isUserInteractionEnabled = false
prodCoName.isUserInteractionEnabled = false
// ADDING CLEAR BUTTON
jobBrand.clearButtonMode = .never
jobName.clearButtonMode = .never
directorName.clearButtonMode = .never
AgencyName.clearButtonMode = .never
prodCoName.clearButtonMode = .never
}
// CONSTRAINTS
private func setupLayout(){
// Auto layout constraints for jobInfo
generalTitle.topAnchor.constraint(equalTo: view.topAnchor, constant: 150).isActive = true
generalTitle.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
// Auto layout constraints for jobInfo
jobBrand.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
// Auto layout constraints for cameras
jobName.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
// Auto layout constraints for attachments
directorName.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
// Auto layout constraints for attachments
AgencyName.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
// Auto layout constraints for attachments
prodCoName.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
// Auto layout constraints for attachments
technicalTitle.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
// Auto layout constraints for attachments
jobSpecsButton.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
// Auto layout constraints for attachments
cameraButton.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
// Auto layout constraints for SKC
SKCButton.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 20).isActive = true
SKCButton.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -100).isActive = true
}
}
Please check the codes.
https://github.com/HsiaoAi/JobInfoStackoverflow/tree/master/JobInfoStackoverflow
Make sure your Json decoding is correct, because I found you used"director" in Firebase but "directorName" when init Job
I modified the "fetchJobs()" because I dont have the Firebase plist file
I modified 5 stuff and I marked them in code as "###", you can use search and check them, I hope it works for you too.