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)
}
Related
inputAccessoryView's background view is falling under its own textField and profile picture imageView.
It works fine on regular screen iPhones, but on new iPhones with notches it looks like this:
Here's how it looks animated when keyboard appears: Transition animation on becomeFirstResponder()
Here's my tableView in which I'm trying to add accessoryView:
import UIKit
import SDWebImage
class CommentsTableViewController: UITableViewController {
let viewModel = CommentsViewModel()
let postID: String
let postCaption: String
let postDate: Date
let postAuthor: ZoogramUser
var keyboardAccessoryView: CommentAccessoryView = {
let commentAccessoryView = CommentAccessoryView()
return commentAccessoryView
}()
init(post: UserPost) {
self.postID = post.postID
self.postCaption = post.caption
self.postDate = post.postedDate
self.postAuthor = post.author
super.init(style: .grouped)
self.tableView.register(PostCommentsTableViewCell.self, forCellReuseIdentifier: PostCommentsTableViewCell.identifier)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
self.title = "Comments"
keyboardAccessoryView.delegate = self
configureKeyboardAccessoryView()
viewModel.getComments(for: self.postID) {
self.tableView.reloadData()
}
tableView.backgroundColor = .systemBackground
tableView.keyboardDismissMode = .interactive
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 100
tableView.allowsSelection = false
tableView.separatorStyle = .none
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
becomeFirstResponder()
}
override var inputAccessoryView: UIView? {
keyboardAccessoryView.heightAnchor.constraint(greaterThanOrEqualToConstant: 60).isActive = true
keyboardAccessoryView.backgroundColor = .systemOrange
return keyboardAccessoryView
}
override var canBecomeFirstResponder: Bool {
return true
}
func configureKeyboardAccessoryView() {
guard let photoURL = AuthenticationManager.shared.getCurrentUserProfilePhotoURL() else {
return
}
keyboardAccessoryView.userProfilePicture.sd_setImage(with: photoURL)
}
}
And here's code for my CommentAccessoryView which I use to override inputAccessoryView:
import UIKit
protocol CommentAccessoryViewProtocol {
func postButtonTapped(commentText: String)
}
class CommentAccessoryView: UIView {
var delegate: CommentAccessoryViewProtocol?
var userProfilePicture: UIImageView = {
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.contentMode = .scaleAspectFit
imageView.clipsToBounds = true
imageView.backgroundColor = .secondarySystemBackground
imageView.contentMode = .scaleAspectFill
return imageView
}()
var commentTextField: AccessoryViewTextField = {
let textField = AccessoryViewTextField()
textField.translatesAutoresizingMaskIntoConstraints = false
textField.backgroundColor = .systemBackground
textField.placeholder = "Enter comment"
textField.clipsToBounds = true
textField.layer.borderWidth = 1
textField.layer.borderColor = UIColor.placeholderText.cgColor
return textField
}()
var postButton: UIButton = {
let button = UIButton(type: .system)
button.translatesAutoresizingMaskIntoConstraints = false
button.widthAnchor.constraint(equalToConstant: 30).isActive = true
button.heightAnchor.constraint(equalToConstant: 30).isActive = true
button.clipsToBounds = true
button.layer.cornerRadius = 30/2
button.setImage(UIImage(systemName: "arrow.up.circle.fill", withConfiguration: UIImage.SymbolConfiguration(pointSize: 35)), for: .normal)
button.tintColor = .systemBlue
button.addTarget(self, action: #selector(didTapPostButton), for: .touchUpInside)
return button
}()
override init(frame: CGRect) {
super.init(frame: frame)
setupConstraints()
backgroundColor = .systemBackground
commentTextField.rightView = postButton
commentTextField.rightViewMode = .always
autoresizingMask = .flexibleHeight
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
super.layoutSubviews()
setViewCornerRadius()
}
func setViewCornerRadius() {
userProfilePicture.layer.cornerRadius = userProfilePicture.frame.height / 2
commentTextField.layer.cornerRadius = commentTextField.frame.height / 2
}
func setupConstraints() {
self.addSubviews(userProfilePicture, commentTextField)
NSLayoutConstraint.activate([
userProfilePicture.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 10),
userProfilePicture.centerYAnchor.constraint(equalTo: self.safeAreaLayoutGuide.centerYAnchor),
userProfilePicture.widthAnchor.constraint(equalToConstant: 40),
userProfilePicture.heightAnchor.constraint(equalToConstant: 40),
commentTextField.leadingAnchor.constraint(equalTo: userProfilePicture.trailingAnchor, constant: 10),
commentTextField.centerYAnchor.constraint(equalTo: userProfilePicture.centerYAnchor),
commentTextField.heightAnchor.constraint(equalToConstant: 40),
commentTextField.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -10),
])
}
override var intrinsicContentSize: CGSize {
return CGSize.zero
}
#objc func didTapPostButton() {
guard let text = commentTextField.text else {
return
}
commentTextField.resignFirstResponder()
delegate?.postButtonTapped(commentText: text)
}
}
I've spent days trying to google a fix for that but nothing helps.
There were posts saying they were able to fix something similar by setting customView's bottom constraint to a safe area with the following method:
override func didMoveToWindow() {
if #available(iOS 11.0, *) {
if let window = window {
let bottomAnchor = bottomAnchor.constraint(lessThanOrEqualToSystemSpacingBelow: window.safeAreaLayoutGuide.bottomAnchor, multiplier: 1.0)
bottomAnchor.isActive = true
}
}
}
But when I use it, AutoLayout starts complaining.
UPDATE: I did what HangarRash recommended, changed CommentAccessoryView from UIView to UIInputView and centering profileImageView and textField to view itself and not to safe area. Now it's a little bit better, but seems to ignore safe area, inputAccessoryView should be above Home indicator but lies beneath it instead. Looking at last cell in TableView and Scroll indicator, it seems like TableView also isn't aware of inputAccessoryView and goes under it.
I am using storyboard for ScreenOne, and I did not use the storyboard for ScreenTwo, I was coding as programmatically and until now no problem for me, but I am still not success to declare
"storyboardIdentifier" for ScreenTwo. Here there is an example but I don't understand how I will handle this example inside of the app. Any idea will be appreciated.
Screenshot:
ScreenTwo:
class ForgotPasswordEmailCheckController: UIViewController {
var storyboardId: String {
return (value(forKey: "ForgotPasswordEmailCheckController") as? String)!
}
Storyboard Controller (Also Embed this controller in Navigation Controller):
class FirstVC: UIViewController {
#IBOutlet weak var btn: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
btn.addAction(UIAction(handler: { action in
let secondVC = SecVC()
self.navigationController?.pushViewController(secondVC, animated: true)
}), for: .touchUpInside)
}
}
Second Viewcontroller:
class SecVC: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
self.view.backgroundColor = UIColor.blue
}
}
This is programmatically way to do it:
in sceneDelegate set your initial navigation controller:
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
guard let windowScene = (scene as? UIWindowScene) else { return }
window = UIWindow(windowScene: windowScene)
window?.makeKeyAndVisible()
let controller = UINavigationController(rootViewController: MyController())
window?.rootViewController = controller
}
now configure your navigationBar in firstController, use my extension to do it:
extension UIViewController {
func configureNavigationBar(largeTitleColor: UIColor, backgoundColor: UIColor, tintColor: UIColor, title: String, preferredLargeTitle: Bool) {
if #available(iOS 13.0, *) {
let navBarAppearance = UINavigationBarAppearance()
navBarAppearance.configureWithOpaqueBackground()
navBarAppearance.largeTitleTextAttributes = [.foregroundColor: largeTitleColor]
navBarAppearance.titleTextAttributes = [.foregroundColor: largeTitleColor]
navBarAppearance.backgroundColor = backgoundColor
navigationController?.navigationBar.standardAppearance = navBarAppearance
navigationController?.navigationBar.compactAppearance = navBarAppearance
navigationController?.navigationBar.scrollEdgeAppearance = navBarAppearance
navigationController?.navigationBar.prefersLargeTitles = preferredLargeTitle
navigationItem.largeTitleDisplayMode = .always
navigationController?.navigationBar.tintColor = tintColor
navigationItem.title = title
} else {
// Fallback on earlier versions
navigationController?.navigationBar.barTintColor = backgoundColor
navigationController?.navigationBar.tintColor = tintColor
navigationController?.navigationBar.isTranslucent = false
navigationItem.title = title
}
}
}
This is your first controller looks like:
class MyController: UIViewController {
let button = UIButton() // declare your button
override func viewDidLoad() {
super.viewDidLoad()
configureNavigationBar(largeTitleColor: .white, backgoundColor: .black, tintColor: .white, title: "My Vc", preferredLargeTitle: true) // set nav bar with exetnsion
view.backgroundColor = .white
view.addSubview(button)
button.backgroundColor = .systemBlue
button.layer.cornerRadius = 9
button.setTitle("My Button", for: .normal)
button.addTarget(self, action: #selector (handelGoToSecondVc), for: .touchUpInside)
button.translatesAutoresizingMaskIntoConstraints = false
button.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 16).isActive = true
button.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -16).isActive = true
button.heightAnchor.constraint(equalToConstant: 50).isActive = true
button.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -10).isActive = true
}
#objc func handelGoToSecondVc() {
let controller = SecondController()
controller.title = "second Vc"
navigationController?.pushViewController(controller, animated: true)
}
}
second controller:
class SecondController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .green
}
}
This is the result:
Complete code:
import UIKit
class MyController: UIViewController {
let button = UIButton() // declare your button
override func viewDidLoad() {
super.viewDidLoad()
configureNavigationBar(largeTitleColor: .white, backgoundColor: .black, tintColor: .white, title: "My Vc", preferredLargeTitle: true) // set nav bar with exetnsion
view.backgroundColor = .white
view.addSubview(button)
button.backgroundColor = .systemBlue
button.layer.cornerRadius = 9
button.setTitle("My Button", for: .normal)
button.addTarget(self, action: #selector (handelGoToSecondVc), for: .touchUpInside)
button.translatesAutoresizingMaskIntoConstraints = false
button.leadingAnchor.constraint(equalTo: self.view.leadingAnchor, constant: 16).isActive = true
button.trailingAnchor.constraint(equalTo: self.view.trailingAnchor, constant: -16).isActive = true
button.heightAnchor.constraint(equalToConstant: 50).isActive = true
button.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -10).isActive = true
}
#objc func handelGoToSecondVc() {
let controller = SecondController()
controller.title = "second Vc"
navigationController?.pushViewController(controller, animated: true)
}
}
class SecondController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .green
}
}
extension UIViewController {
func configureNavigationBar(largeTitleColor: UIColor, backgoundColor: UIColor, tintColor: UIColor, title: String, preferredLargeTitle: Bool) {
if #available(iOS 13.0, *) {
let navBarAppearance = UINavigationBarAppearance()
navBarAppearance.configureWithOpaqueBackground()
navBarAppearance.largeTitleTextAttributes = [.foregroundColor: largeTitleColor]
navBarAppearance.titleTextAttributes = [.foregroundColor: largeTitleColor]
navBarAppearance.backgroundColor = backgoundColor
navigationController?.navigationBar.standardAppearance = navBarAppearance
navigationController?.navigationBar.compactAppearance = navBarAppearance
navigationController?.navigationBar.scrollEdgeAppearance = navBarAppearance
navigationController?.navigationBar.prefersLargeTitles = preferredLargeTitle
navigationItem.largeTitleDisplayMode = .always
navigationController?.navigationBar.tintColor = tintColor
navigationItem.title = title
} else {
// Fallback on earlier versions
navigationController?.navigationBar.barTintColor = backgoundColor
navigationController?.navigationBar.tintColor = tintColor
navigationController?.navigationBar.isTranslucent = false
navigationItem.title = title
}
}
}
Please tell me the application crashes with an error:
Thread 1: EXC_BAD_ACCESS (code=1, address=0x30)
when clicking on the button for reminders for a table cell (switching to a new View Controller).
The error appears in the class when creating a UILabel in the line let label = UILabel ():
let oneLabel: UILabel = {
let label = UILabel()
if (UIDevice.current.userInterfaceIdiom == .pad) {
label.font = UIFont.systemFont(ofSize: 32, weight: .semibold)
label.numberOfLines = 4
}
else {
label.font = UIFont.systemFont(ofSize: 16, weight: .semibold)
label.numberOfLines = 1
}
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
Here is the code from another class that transitions to the View Controller, for which the UILabel is created:
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let alarm = UIContextualAction(
style: .normal,
title: "",
handler: {(_, _, completion) in
self.notificationCenter.requestAuthorization(options: [.alert, .sound]) { (granted, error) in
guard granted else { return DispatchQueue.main.async { self.createAlertForNotifications() } }
self.notificationCenter.getNotificationSettings { (settings) in
guard settings.authorizationStatus == .authorized else { return }
DispatchQueue.main.async {
let vc = OneViewController()
self.parentController!.navigationController?.setViewControllers([vc], animated: false)
}
completion(true)
}
}
}
)
alarm.image = ListImages.alarmImage
alarm.backgroundColor = .systemPurple
return UISwipeActionsConfiguration(actions: [alarm])
}
Sometimes this error appears, sometimes not, and it may appear for the second UILabel, which is created after the first. How can you fix this error?
Sometimes I get error in let dataPicker = UIDatePicker()
Here you go to the OneViewController:
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let oneObject = isFiltering ? filteredObjects[indexPath.row] : listObjects[indexPath.row]
let alarm = UIContextualAction(
style: .normal,
title: "",
handler: {(_, _, completion) in
self.notificationCenter.requestAuthorization(options: [.alert, .sound]) { (granted, error) in
guard granted else { return DispatchQueue.main.async { self.createAlertForNotifications() } }
self.notificationCenter.getNotificationSettings { (settings) in
guard settings.authorizationStatus == .authorized else { return }
DispatchQueue.main.async {
let vc = OneViewController()
ListNameLabel.oneText = oneObject.name
self.parentController!.navigationController?.setViewControllers([vc], animated: false)
}
completion(true)
}
}
}
)
alarm.image = ListImages.alarmImage
alarm.backgroundColor = .systemPurple
return UISwipeActionsConfiguration(actions: [alarm])
}
This is class with UILabel:
import UIKit
class MainView: UIView {
let oneLabel: UILabel = {
let label = UILabel()
if (UIDevice.current.userInterfaceIdiom == .pad) {
label.font = UIFont.systemFont(ofSize: 32, weight: .semibold)
label.numberOfLines = 4
}
else {
label.font = UIFont.systemFont(ofSize: 16, weight: .semibold)
label.numberOfLines = 1
}
label.translatesAutoresizingMaskIntoConstraints = false
return label
}()
let sheduleTimeDataPicker: UIDatePicker = {
let dataPicker = UIDatePicker()
if #available(iOS 14, *) {
dataPicker.preferredDatePickerStyle = .inline
}
else {
dataPicker.preferredDatePickerStyle = .compact
}
dataPicker.datePickerMode = .dateAndTime
dataPicker.date = Date()
dataPicker.minimumDate = Date()
dataPicker.translatesAutoresizingMaskIntoConstraints = false
return dataPicker
}()
let oneView: UIView = {
let view = UIView()
view.backgroundColor = .systemGray5
view.layer.cornerRadius = 15
view.translatesAutoresizingMaskIntoConstraints = false
return view
}()
override init(frame: CGRect) {
super.init(frame: frame)
self.addSubview(oneView)
oneView.addSubview(oneLabel)
oneView.addSubview(sheduleTimeDataPicker)
if (UIDevice.current.userInterfaceIdiom == .pad) {
// oneLabel constraints
oneLabel.leadingAnchor.constraint(equalTo: oneView.leadingAnchor, constant: 20).isActive = true
oneLabel.trailingAnchor.constraint(equalTo: oneView.trailingAnchor, constant: -20).isActive = true
oneLabel.topAnchor.constraint(equalTo: oneView.topAnchor, constant: 20).isActive = true
oneLabel.heightAnchor.constraint(equalToConstant: 120).isActive = true
// sheduleTimeDataPicker constraints
sheduleTimeDataPicker.centerXAnchor.constraint(equalTo: oneView.centerXAnchor).isActive = true
sheduleTimeDataPicker.topAnchor.constraint(equalTo: oneLabel.bottomAnchor).isActive = true
}
else {
// oneLabel constraints
oneLabel.leadingAnchor.constraint(equalTo: oneView.leadingAnchor, constant: 10).isActive = true
oneLabel.trailingAnchor.constraint(equalTo: oneView.trailingAnchor, constant: -10).isActive = true
oneLabel.topAnchor.constraint(equalTo: oneView.topAnchor, constant: 5).isActive = true
oneLabel.heightAnchor.constraint(greaterThanOrEqualToConstant: 20).isActive = true
// sheduleTimeDataPicker constraints
sheduleTimeDataPicker.leadingAnchor.constraint(equalTo: oneView.leadingAnchor, constant: 10).isActive = true
sheduleTimeDataPicker.trailingAnchor.constraint(equalTo: oneView.trailingAnchor, constant: -10).isActive = true
sheduleTimeDataPicker.topAnchor.constraint(equalTo: oneLabel.bottomAnchor).isActive = true
}
// oneView constraints
oneView.leadingAnchor.constraint(equalTo: self.leadingAnchor, constant: 10).isActive = true
oneView.trailingAnchor.constraint(equalTo: self.trailingAnchor, constant: -10).isActive = true
oneView.topAnchor.constraint(equalTo: self.topAnchor, constant: 10).isActive = true
oneView.bottomAnchor.constraint(equalTo: self.bottomAnchor, constant: -10).isActive = true
}
func setContentView(content: OneModel) {
self.oneLabel.text = content.oneName
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
This is class OneModel:
import UIKit
struct ListNameLabel {
static var oneText = ""
}
struct OneModel {
var oneName: String
static func fetchView() -> OneModel {
return OneModel(oneName: ListNameLabel.oneText)
}
}
This is class OneViewController:
import UIKit
import UserNotifications
class OneViewController: UIViewController {
var mainView = MainView()
let notificationCenter = UNUserNotificationCenter.current()
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
setupNavigationBar()
setupView()
}
// MARK: NavigationBar
private func setupNavigationBar() {
let backBarButtonItem = UIBarButtonItem()
backBarButtonItem.image = ListImages.chevronImage
backBarButtonItem.action = #selector(backBarButtonItemTapped)
backBarButtonItem.target = self
navigationItem.leftBarButtonItem = backBarButtonItem
navigationItem.title = ""
}
// MARK: View
private func setupView() {
view.backgroundColor = .systemBackground
view.addSubview(mainView)
mainView.translatesAutoresizingMaskIntoConstraints = false
let guide = self.view.safeAreaLayoutGuide
// mainView constraints
mainView.leadingAnchor.constraint(equalTo: guide.leadingAnchor).isActive = true
mainView.trailingAnchor.constraint(equalTo: guide.trailingAnchor).isActive = true
mainView.topAnchor.constraint(equalTo: guide.topAnchor).isActive = true
mainView.bottomAnchor.constraint(equalTo: guide.bottomAnchor).isActive = true
// fetch
mainView.setContentView(content: OneModel.fetchView())
}
}
// MARK: Back
extension OneViewController {
#objc func backBarButtonItemTapped() {
let vc = TwoViewController()
self.navigationController?.setViewControllers([vc], animated: false)
}
}
// MARK: UNUserNotificationCenterDelegate
extension OneViewController: UNUserNotificationCenterDelegate {
func userNotificationCenter(_ center: UNUserNotificationCenter, willPresent notification: UNNotification, withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void) {
completionHandler([.banner, .sound])
print(#function)
}
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: #escaping () -> Void) {
print(#function)
}
}
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()
}
I have this situation where my LargeTitles became "popped" after a refresh was done. I have implemented accordingly like so in this linked post but programmatically, but received this issue like so:
My code as such:
//Declarations:
lazy var tableView: UITableView = {
let tv = UITableView(frame: .zero, style: .grouped)
tv.translatesAutoresizingMaskIntoConstraints = false
tv.dataSource = self
tv.delegate = self
tv.backgroundColor = .customGroupedTableViewBackgroundColor
tv.contentInset.top = -36
return tv
}()
lazy var refreshControl: UIRefreshControl = {
let rc = UIRefreshControl(frame: .zero)
rc.addTarget(self, action: #selector(refreshControlDidRefresh), for: .valueChanged)
return rc
}()
//At viewDidLoad()
view.addSubview(tableView)
navigationController?.navigationBar.barTintColor = .white
navigationController?.navigationBar.prefersLargeTitles = true
navigationItem.title = "Carparks"
tableView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
tableView.leadingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leadingAnchor).isActive = true
tableView.trailingAnchor.constraint(equalTo: view.safeAreaLayoutGuide.trailingAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "cell")
tableView.estimatedRowHeight = 200
tableView.rowHeight = UITableViewAutomaticDimension
tableView.refreshControl = refreshControl
Any advice how do I remove that snappy behaviour?
Ok, I managed to solve it by adding tv.contentInsetAdjustmentBehavior = .never to my tableView declaration:
lazy var tableView: UITableView = {
let tv = UITableView(frame: .zero, style: .grouped)
tv.translatesAutoresizingMaskIntoConstraints = false
tv.dataSource = self
tv.delegate = self
tv.backgroundColor = .customGroupedTableViewBackgroundColor
tv.contentInset.top = -35
tv.contentInsetAdjustmentBehavior = .never
return tv
}()