Table Cells get attached to top - ios

If i test the app on large screen simulator everything works well, but the moment i test the code in small screen simulator, there is no error but the cells that are not visible and can be seen only while scrolling gets attached to top of screen, strangely enough if i scroll down again i can see the labels and text fields looking like they are moving from top to their original locations, but they do not and remain on screen top, i am posting the image , where could i be making the mistake below is code of file and image , the misbehaviour happens when i scroll
import UIKit
import CoreData
class RestaurantAddController: UIViewController, UITableViewDelegate, UITableViewDataSource, UITextFieldDelegate, UITextViewDelegate, UIImagePickerControllerDelegate & UINavigationControllerDelegate {
let displayInputForm = UITableView()
var restaurant: Restaurant!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 6
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = displayInputForm.dequeueReusableCell(withIdentifier: String(describing: RestaurantAddViewCells.self), for: indexPath) as! RestaurantAddViewCells
cell.heightAnchor.constraint(greaterThanOrEqualToConstant: 100).isActive = true
view.addSubview(cell)
// view.addSubview(cell.contentView)
view.addSubview(cell.imageToUpload)
view.addSubview(cell.nameToUploadLabel)
view.addSubview(cell.nameToUploadTextField)
view.addSubview(cell.typeToUploadLabel)
view.addSubview(cell.typeToUploadTextField)
view.addSubview(cell.locationToUploadLabel)
view.addSubview(cell.locationToUploadTextField)
view.addSubview(cell.phoneToUploadLabel)
view.addSubview(cell.phoneToUPloadTextField)
view.addSubview(cell.summartyToUploadLabel)
view.addSubview(cell.summaryToUploadTextView)
//Add to cell via stackView
let stackEntry = UIStackView()
view.addSubview(stackEntry)
stackEntry.translatesAutoresizingMaskIntoConstraints = false
stackEntry.alignment = .top
stackEntry.axis = .vertical
stackEntry.spacing = 5.0
stackEntry.distribution = .fill
stackEntry.leadingAnchor.constraint(equalTo: cell.leadingAnchor, constant: 10).isActive = true
stackEntry.trailingAnchor.constraint(equalTo: cell.trailingAnchor, constant: -10).isActive = true
stackEntry.topAnchor.constraint(equalTo: cell.topAnchor, constant: 20).isActive = true
//add scroll view
// let scrollView = UIScrollView()
// view.addSubview(scrollView)
// scrollView.translatesAutoresizingMaskIntoConstraints = false
// scrollView.topAnchor.constraint(equalTo: displayInputForm.topAnchor).isActive = true
// scrollView.bottomAnchor.constraint(equalTo: displayInputForm.bottomAnchor).isActive = true
// scrollView.leadingAnchor.constraint(equalTo: displayInputForm.leadingAnchor).isActive = true
// scrollView.trailingAnchor.constraint(equalTo: displayInputForm.trailingAnchor).isActive = true
// scrollView.addSubview(stackEntry)
//MARK:- give custom font
let font = UIFont(name: "Rubik-Medium", size: 18)
let fontMetrics = UIFontMetrics(forTextStyle: .body)
let labels = [cell.locationToUploadLabel, cell.typeToUploadLabel, cell.nameToUploadLabel, cell.phoneToUploadLabel, cell.summartyToUploadLabel]
labels.forEach { label in
label.font = fontMetrics.scaledFont(for: font!)
}
let textCusotm = [cell.nameToUploadTextField, cell.typeToUploadTextField, cell.locationToUploadTextField, cell.phoneToUPloadTextField]
textCusotm.forEach { (fields) in
fields.font = fontMetrics.scaledFont(for: font!)
}
cell.summaryToUploadTextView.font = fontMetrics.scaledFont(for: font!)
//MARK:- add cell per row
switch indexPath.row {
case 0:
cell.heightAnchor.constraint(greaterThanOrEqualToConstant: 250).isActive = true
let buttonImage = UIImageView()
cell.backgroundColor = UIColor.lightGray
buttonImage.translatesAutoresizingMaskIntoConstraints = false
buttonImage.image = UIImage(named: "photo")
view.addSubview(buttonImage)
buttonImage.heightAnchor.constraint(equalToConstant: 30).isActive = true
buttonImage.widthAnchor.constraint(equalToConstant: 30).isActive = true
buttonImage.centerXAnchor.constraint(equalTo: cell.centerXAnchor).isActive = true
buttonImage.centerYAnchor.constraint(equalTo: cell.centerYAnchor).isActive = true
return cell
case 1:
cell.selectionStyle = .none
cell.nameToUploadLabel.text = "Name of Hotel:"
cell.nameToUploadTextField.placeholder = "Enter Hotel Name"
cell.nameToUploadTextField.tag = 1
cell.nameToUploadTextField.trailingAnchor.constraint(equalTo: cell.trailingAnchor, constant: -10).isActive = true
stackEntry.addArrangedSubview(cell.nameToUploadLabel)
stackEntry.addArrangedSubview(cell.nameToUploadTextField)
// cell.nameToUploadTextField.becomeFirstResponder()
cell.nameToUploadTextField.delegate = self
return cell
case 2:
cell.selectionStyle = .none
cell.typeToUploadLabel.text = "Type Of Hotel:"
cell.typeToUploadTextField.placeholder = "Name type of hotel"
cell.typeToUploadTextField.tag = 2
cell.typeToUploadTextField.trailingAnchor.constraint(equalTo: cell.trailingAnchor, constant: -10).isActive = true
stackEntry.addArrangedSubview(cell.typeToUploadLabel)
stackEntry.addArrangedSubview(cell.typeToUploadTextField)
cell.typeToUploadTextField.delegate = self
return cell
case 3:
cell.selectionStyle = .none
cell.locationToUploadLabel.text = "Location of Hotel:"
cell.locationToUploadTextField.placeholder = "Enter Hotel Location"
cell.locationToUploadTextField.tag = 3
cell.locationToUploadTextField.trailingAnchor.constraint(equalTo: cell.trailingAnchor, constant: -10).isActive = true
stackEntry.addArrangedSubview(cell.locationToUploadLabel)
stackEntry.addArrangedSubview(cell.locationToUploadTextField)
cell.locationToUploadTextField.delegate = self
return cell
case 4:
cell.selectionStyle = .none
cell.phoneToUploadLabel.text = "Phone:"
cell.phoneToUPloadTextField.placeholder = "Enter Phone"
cell.phoneToUPloadTextField.tag = 4
cell.phoneToUPloadTextField.trailingAnchor.constraint(equalTo: cell.trailingAnchor, constant: -10).isActive = true
stackEntry.addArrangedSubview(cell.phoneToUploadLabel)
stackEntry.addArrangedSubview(cell.phoneToUPloadTextField)
cell.phoneToUPloadTextField.delegate = self
return cell
case 5:
cell.selectionStyle = .none
cell.summartyToUploadLabel.text = "Enter Summary:"
//cell.summaryToUploadTextView.place
cell.summaryToUploadTextView.tag = 5
cell.summaryToUploadTextView.heightAnchor.constraint(equalToConstant: 200).isActive = true
cell.summaryToUploadTextView.widthAnchor.constraint(equalToConstant: UIScreen.main.bounds.width - 20).isActive = true
cell.summaryToUploadTextView.layer.borderWidth = 1
cell.summaryToUploadTextView.layer.cornerRadius = 5.0
cell.summaryToUploadTextView.layer.borderColor = UIColor.lightGray.cgColor
stackEntry.addArrangedSubview(cell.summartyToUploadLabel)
stackEntry.addArrangedSubview(cell.summaryToUploadTextView)
cell.summaryToUploadTextView.delegate = self
return cell
default:
fatalError("No data found")
}
}
override func viewDidLoad() {
super.viewDidLoad()
displayInputForm.delegate = self
displayInputForm.dataSource = self
//MARK:- Add scroll view
view.addSubview(displayInputForm)
let footerView = UIView()
displayInputForm.tableFooterView = footerView
// Do any additional setup after loading the view.
//Add pinning of table
displayInputForm.translatesAutoresizingMaskIntoConstraints = false
self.displayInputForm.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
self.displayInputForm.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
self.displayInputForm.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
self.displayInputForm.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
//Change the back button to arrow
let imgBack = UIImage(named: "back")
navigationController?.navigationBar.backIndicatorImage = imgBack
navigationController?.navigationBar.backIndicatorTransitionMaskImage = imgBack
navigationItem.leftItemsSupplementBackButton = true
navigationController?.navigationBar.topItem?.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: self, action: nil)
// Register a cell
displayInputForm.register(RestaurantAddViewCells.self, forCellReuseIdentifier: String(describing: RestaurantAddViewCells.self))
//MARK:- add the cancel and save button
self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: UIImage(named: "close"), style: .done, target: self, action: #selector(closeRestaurant))
self.navigationItem.rightBarButtonItem = UIBarButtonItem(image: UIImage(named: "save"), style: .plain, target: self, action: #selector(saveRestaurantData))
}
//MARK:- close function
#objc func closeRestaurant() {
self.navigationController?.popViewController(animated: true)
}
//MARK:- save function
#objc func saveRestaurantData() {
let indexPath0 = IndexPath(row: 1, section: 0)
let cell0 = displayInputForm.cellForRow(at: indexPath0) as! RestaurantAddViewCells
let nameVal = cell0.nameToUploadTextField.text
let indexPath1 = IndexPath(row: 2, section: 0)
let cell1 = displayInputForm.cellForRow(at: indexPath1) as! RestaurantAddViewCells
let typeVal = cell1.typeToUploadTextField.text
let indexPath2 = IndexPath(row: 3, section: 0)
let cell2 = displayInputForm.cellForRow(at: indexPath2) as! RestaurantAddViewCells
let locationVal = cell2.locationToUploadTextField.text
let indexPath3 = IndexPath(row: 4, section: 0)
let cell3 = displayInputForm.cellForRow(at: indexPath3) as! RestaurantAddViewCells
let phoneVal = cell3.phoneToUPloadTextField.text
let indexPath4 = IndexPath(row: 5, section: 0)
let cell4 = displayInputForm.cellForRow(at: indexPath4) as! RestaurantAddViewCells
let summaryVal = cell4.summaryToUploadTextView.text
let indexPath5 = IndexPath(row: 0, section: 0)
let cell5 = displayInputForm.cellForRow(at: indexPath5) as! RestaurantAddViewCells
let imageVal = cell5.imageToUpload.image
if (imageVal == nil || nameVal == "" || typeVal == "" || locationVal == "" || phoneVal == "" || summaryVal == "") {
let saveAlertController = UIAlertController(title: "Empty Fields", message: "Fill all the fileds", preferredStyle: .alert)
let saveAlertAction = UIAlertAction(title: "OK", style: .cancel, handler: nil)
saveAlertController.addAction(saveAlertAction)
self.present(saveAlertController, animated: true) {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.dissMissAlertController))
saveAlertController.view.superview?.subviews[0].addGestureRecognizer(tapGesture)
}
}
else {
if let appDelegate = (UIApplication.shared.delegate as? AppDelegate) {
let context = appDelegate.persistentContainer.viewContext
restaurant = Restaurant(context: context)
restaurant.name = nameVal
restaurant.type = typeVal
restaurant.location = locationVal
restaurant.phone = phoneVal
restaurant.summary = summaryVal
if let restaurantImage = cell5.imageToUpload.image {
restaurant.image = restaurantImage.pngData()
}
print("data saved")
appDelegate.saveContext()
}
}
self.navigationController?.popViewController(animated: false)
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
override func viewWillAppear(_ animated: Bool) {
self.title = "Add Restaurants"
}
//MARK:- check if textfield can be moved to next one on return key press
func textFieldShouldReturn(_ textField: UITextField) -> Bool {
if let nextField = view.viewWithTag(textField.tag + 1) as? UITextField {
textField.resignFirstResponder()
nextField.becomeFirstResponder()
// nextField.endEditing(false)
}
return true
}
//MARK:- add sction to row clicks
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
if indexPath.row == 0 {
let UIImageAlertController = UIAlertController(title: "", message: "Select an option", preferredStyle: .actionSheet)
let photoGalleryAction = UIAlertAction(title: "PhotoLibrary", style: .default) { (action) in
if UIImagePickerController.isSourceTypeAvailable(.photoLibrary) {
let imageController = UIImagePickerController()
imageController.allowsEditing = false
imageController.sourceType = .photoLibrary
imageController.delegate = self
self.present(imageController, animated: true, completion: nil)
}
}
UIImageAlertController.addAction(photoGalleryAction)
let cameraPicturesAction = UIAlertAction(title: "Camera", style: .default) { (action) in
if UIImagePickerController.isSourceTypeAvailable(.camera) {
let cameraController = UIImagePickerController()
cameraController.allowsEditing = false
cameraController.sourceType = .camera
cameraController.delegate = self
self.present(cameraController, animated: true, completion: nil)
}
}
UIImageAlertController.addAction(cameraPicturesAction)
self.present(UIImageAlertController, animated: true) {
let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.dissMissAlertController))
UIImageAlertController.view.superview?.subviews[0].addGestureRecognizer(tapGesture)
}
}
}
#objc func dissMissAlertController() {
self.dismiss(animated: true, completion: nil)
}
//MARK:- function to add and select a picture and then add it
func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
if let selectedImage = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
if let indexPath = displayInputForm.indexPathForSelectedRow {
let cell = displayInputForm.cellForRow(at: indexPath) as! RestaurantAddViewCells
cell.imageToUpload.translatesAutoresizingMaskIntoConstraints = false
cell.imageToUpload.widthAnchor.constraint(equalTo: cell.widthAnchor).isActive = true
cell.imageToUpload.heightAnchor.constraint(equalToConstant: 250).isActive = true
cell.imageToUpload.topAnchor.constraint(equalTo: cell.topAnchor).isActive = true
cell.imageToUpload.image = selectedImage
cell.contentMode = .scaleAspectFill
cell.clipsToBounds = true
}
dismiss(animated: true, completion: nil)
}
}
}
Solution
add this line in viewdidload, where the tableName is the instance of your table
<tableName>.contentInsetAdjustmentBehavior = .never

Related

Is it possible to add icon at the both right and left sides of UIAlertController?

Currently, this is how I add icon to the left side of UIAlertController.
let chooseImage = UIImage(systemName: "photo")
let alert = UIAlertController(title: nil, message: nil, preferredStyle: .actionSheet)
let chooseImageAction = UIAlertAction(title: "choose_image".localized, style: .default) { _ in
self.chooseImage()
}
chooseImageAction.setValue(chooseImage, forKey: "image")
alert.addAction(chooseImageAction)
This is how it looks like
However, I would also like to add an icon at right side, as indicated by the red circle.
May I know, is it possible to achieve so? Thanks.
I don't think it's possible with the default one but you can do a custom one, for my commodity I use a navigation button to call custom action sheet (you can use a simple butto), in viewDidLoad set my button and call handleAS func to present my Custom action sheet:
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Show ActionSheet", style: .plain, target: self, action: #selector(handleAS))
function called from button above:
#objc fileprivate func handleAS() {
let controller = CustomActionSheet(title: nil, message: nil, preferredStyle: .actionSheet)
controller.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil)) // controller cancel Action
self.present(controller, animated: true, completion: nil)
}
Now create your CustomActionSheet class:
class CustomActionSheet: UIAlertController {
private var controller : UITableViewController
let cellId = "cellID"
override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
controller = UITableViewController(style: .plain)
super.init(nibName: nibNameOrNil, bundle: nibBundleOrNil)
controller.tableView.register(ActionSheetCell.self, forCellReuseIdentifier: cellId) // register your custom cell
controller.tableView.dataSource = self
controller.tableView.delegate = self
controller.tableView.addObserver(self, forKeyPath: "contentSize", options: [.initial, .new], context: nil)
self.setValue(controller, forKey: "contentViewController")
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
deinit {
controller.tableView.removeObserver(self, forKeyPath: "contentSize")
}
override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
guard keyPath == "contentSize" else {
return
}
controller.preferredContentSize = controller.tableView.contentSize
}
}
CustomActionSheet extension for tableViewDelegate and Datasource
extension CustomActionSheet: UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let cell = tableView.cellForRow(at: indexPath) as? ActionSheetCell else { return }
print("This is:", cell.loadingLabel.text ?? "")
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 4 // number of action in actionSheet
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId) as! ActionSheetCell
switch(indexPath.row) {
case 0:
cell.loadingLabel.text = "Choose image"
cell.myImageView.image = UIImage(systemName: "photo")?.withRenderingMode(.alwaysTemplate)
cell.myImageView2.image = UIImage(systemName: "clock")?.withRenderingMode(.alwaysTemplate)
break
case 1:
cell.loadingLabel.text = "Take a photo"
cell.myImageView.image = UIImage(systemName: "camera")?.withRenderingMode(.alwaysTemplate)
cell.myImageView2.image = UIImage(systemName: "car")?.withRenderingMode(.alwaysTemplate)
break
case 2:
cell.loadingLabel.text = "Drawing"
cell.myImageView.image = UIImage(systemName: "paintbrush.pointed")?.withRenderingMode(.alwaysTemplate)
cell.myImageView2.image = UIImage(systemName: "paintbrush")?.withRenderingMode(.alwaysTemplate)
break
case 3:
cell.loadingLabel.text = "Recording"
cell.myImageView.image = UIImage(systemName: "mic")?.withRenderingMode(.alwaysTemplate)
cell.myImageView2.image = UIImage(systemName: "cloud")?.withRenderingMode(.alwaysTemplate)
break
default:
fatalError()
}
cell.selectionStyle = .none // comment if do you want selection of row
return cell
}
}
Create your custom cell:
class ActionSheetCell: UITableViewCell {
let loadingLabel: UILabel = {
let label = UILabel()
label.text = "Loading Results..."
label.textColor = #colorLiteral(red: 0, green: 0.4199056029, blue: 0.9801818728, alpha: 1)
label.textAlignment = .center
label.font = .systemFont(ofSize: 18, weight: .regular)
label.heightAnchor.constraint(equalToConstant: 55).isActive = true
return label
}()
let myView: UIView = {
let iv = UIView()
iv.backgroundColor = .clear
iv.translatesAutoresizingMaskIntoConstraints = false
iv.contentMode = .scaleAspectFit
iv.widthAnchor.constraint(equalToConstant: 55).isActive = true
iv.clipsToBounds = true
return iv
}()
let myView2: UIView = {
let iv = UIView()
iv.backgroundColor = .clear
iv.translatesAutoresizingMaskIntoConstraints = false
iv.contentMode = .scaleAspectFit
iv.widthAnchor.constraint(equalToConstant: 55).isActive = true
iv.clipsToBounds = true
return iv
}()
let myImageView: UIImageView = {
let iv = UIImageView()
iv.image = UIImage(systemName: "car")?.withRenderingMode(.alwaysTemplate)
iv.tintColor = #colorLiteral(red: 0, green: 0.4199056029, blue: 0.9801818728, alpha: 1)
iv.contentMode = .scaleAspectFit
iv.translatesAutoresizingMaskIntoConstraints = false
return iv
}()
let myImageView2: UIImageView = {
let iv = UIImageView()
iv.image = UIImage(systemName: "clock")?.withRenderingMode(.alwaysTemplate)
iv.tintColor = #colorLiteral(red: 0, green: 0.4199056029, blue: 0.9801818728, alpha: 1)
iv.contentMode = .scaleAspectFill
iv.translatesAutoresizingMaskIntoConstraints = false
return iv
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
myView.addSubview(myImageView)
myImageView.centerYAnchor.constraint(equalTo: myView.centerYAnchor).isActive = true
myImageView.centerXAnchor.constraint(equalTo: myView.centerXAnchor).isActive = true
myImageView.widthAnchor.constraint(equalToConstant: 24).isActive = true
myImageView.heightAnchor.constraint(equalToConstant: 24).isActive = true
myView2.addSubview(myImageView2)
myImageView2.centerYAnchor.constraint(equalTo: myView2.centerYAnchor).isActive = true
myImageView2.centerXAnchor.constraint(equalTo: myView2.centerXAnchor).isActive = true
myImageView2.widthAnchor.constraint(equalToConstant: 24).isActive = true
myImageView2.heightAnchor.constraint(equalToConstant: 24).isActive = true
let stackView = UIStackView(arrangedSubviews: [myView, loadingLabel, myView2])
stackView.distribution = .fill
stackView.translatesAutoresizingMaskIntoConstraints = false
contentView.addSubview(stackView)
stackView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
stackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
stackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
stackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
In didSelectRowAt you can call other functions...
This is the result:

tableView never shows up

I have been at this for some time now. I can not get my tableView to appear. I think it has something to do with the fact that it is being presented as didMove(toParent)
I am trying to create a page that allows you to add a new Card to the profile. Every time I write it programmatically or use storyboard it crashes as it Unexpectedly found nil while implicitly unwrapping an Optional value.
Here is the view Controller that is presenting the Side Menu
import Foundation
import SideMenu
import FirebaseAuth
import UIKit
import CoreLocation
import SwiftUI
class BeginViewController: UIViewController, MenuControllerDelegate, CLLocationManagerDelegate {
private var sideMenu: SideMenuNavigationController?
struct customData {
var title: String
var image: UIImage
}
let data = [
customData(title: "NottingHill", image: #imageLiteral(resourceName: "norali-nayla-SAhImiWmFaw-unsplash")),
customData(title: "Southall", image: #imageLiteral(resourceName: "alistair-macrobert-8wMflrTLm2g-unsplash")),
customData(title: "Tower Hill", image: #imageLiteral(resourceName: "peregrine-communications-0OLnnZWg860-unsplash")),
customData(title: "Mansion House", image: #imageLiteral(resourceName: "adam-birkett-cndNklOnHO4-unsplash")),
customData(title: "Westminster", image: #imageLiteral(resourceName: "simon-mumenthaler-NykjYbCW6Z0-unsplash")),
customData(title: "London Bridge", image: #imageLiteral(resourceName: "hert-niks-CjouXgWrTRk-unsplash"))
]
struct Constants {
static let cornerRadius: CGFloat = 15.0 }
let manager = CLLocationManager()
private let ProfileController = ProfileViewController()
private let MyBookingsController = MyBookingsViewController()
private let WalletController = WalletViewController()
private let FAQController = FAQViewController()
private let SettingsController = SettingsViewController()
#IBOutlet weak var StoreButton: UIButton!
#IBOutlet weak var DeliverButton: UIButton!
#IBOutlet weak var AirportButton: UIButton!
#IBOutlet weak var HotelsButton: UIButton!
fileprivate let collectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
let cv = UICollectionView(frame: .zero, collectionViewLayout: layout)
cv.translatesAutoresizingMaskIntoConstraints = false
cv.register(customCell.self, forCellWithReuseIdentifier: "cell")
return cv
}()
override func viewDidLoad() {
super.viewDidLoad()
// buttons
StoreButton.layer.cornerRadius = Constants.cornerRadius
StoreButton.layer.shadowOffset = .zero
StoreButton.layer.shadowOpacity = 0.3
StoreButton.layer.shadowColor = UIColor.black.cgColor
StoreButton.layer.shadowRadius = 5
DeliverButton.layer.cornerRadius = Constants.cornerRadius
DeliverButton.layer.shadowOffset = .zero
DeliverButton.layer.shadowOpacity = 0.3
DeliverButton.layer.shadowColor = UIColor.black.cgColor
DeliverButton.layer.shadowRadius = 5
AirportButton.layer.cornerRadius = Constants.cornerRadius
AirportButton.layer.shadowOffset = .zero
AirportButton.layer.shadowOpacity = 0.3
AirportButton.layer.shadowColor = UIColor.black.cgColor
AirportButton.layer.shadowRadius = 5
HotelsButton.layer.cornerRadius = Constants.cornerRadius
HotelsButton.layer.shadowOffset = .zero
HotelsButton.layer.shadowOpacity = 0.3
HotelsButton.layer.shadowColor = UIColor.black.cgColor
HotelsButton.layer.shadowRadius = 5
//CollectionViewNearbyPlaces
view.addSubview(collectionView)
collectionView.backgroundColor = .clear
collectionView.topAnchor.constraint(equalTo: view.topAnchor, constant: 450).isActive = true
collectionView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 25).isActive = true
collectionView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0).isActive = true
collectionView.heightAnchor.constraint(equalTo: collectionView.widthAnchor, multiplier: 0.5).isActive = true
collectionView.delegate = self
collectionView.dataSource = self
// title
title = "handl"
//background
let menu = MenuController(with: [ "Home", "Profile", "My Bookings",
"Wallet",
"FAQ","Settings"])
menu.delegate = self
sideMenu = SideMenuNavigationController(rootViewController: menu)
sideMenu?.leftSide = true
sideMenu?.setNavigationBarHidden(true, animated: false)
SideMenuManager.default.leftMenuNavigationController = sideMenu
SideMenuManager.default.addPanGestureToPresent(toView: view)
addChildControllers()
}
override func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
manager.desiredAccuracy = kCLLocationAccuracyBest
manager.delegate = self
manager.requestWhenInUseAuthorization()
manager.startUpdatingLocation()
handleNotAuthenticated()
}
private func addChildControllers() {
addChild(ProfileController)
addChild(MyBookingsController)
addChild(WalletController)
addChild(FAQController)
addChild(SettingsController)
view.addSubview(ProfileController.view)
view.addSubview(MyBookingsController.view)
view.addSubview(WalletController.view)
view.addSubview(FAQController.view)
view.addSubview(SettingsController.view)
ProfileController.view.frame = view.bounds
MyBookingsController.view.frame = view.bounds
WalletController.view.frame = view.bounds
FAQController.view.frame = view.bounds
SettingsController.view.frame = view.bounds
ProfileController.didMove(toParent: self)
MyBookingsController.didMove(toParent: self)
WalletController.didMove(toParent: self)
FAQController.didMove(toParent: self)
SettingsController.didMove(toParent: self)
ProfileController.view.isHidden = true
MyBookingsController.view.isHidden = true
WalletController.view.isHidden = true
FAQController.view.isHidden = true
SettingsController.view.isHidden = true
}
#IBAction func SideMenuButton(_ sender: Any) {
present(sideMenu!, animated: true)
}
func didSelectMenuItem(named: String) {
sideMenu?.dismiss(animated: true, completion: { [weak self] in
self?.title = named
if named == "Home" {
self?.ProfileController.view.isHidden = true
self?.MyBookingsController.view.isHidden = true
self?.WalletController.view.isHidden = true
self?.FAQController.view.isHidden = true
self?.SettingsController.view.isHidden = true
}
if named == "Profile" {
self?.ProfileController.view.isHidden = false
self?.MyBookingsController.view.isHidden = true
self?.WalletController.view.isHidden = true
self?.FAQController.view.isHidden = true
self?.SettingsController.view.isHidden = true
}
if named == "My Bookings" {
self?.ProfileController.view.isHidden = true
self?.MyBookingsController.view.isHidden = false
self?.WalletController.view.isHidden = true
self?.FAQController.view.isHidden = true
self?.SettingsController.view.isHidden = true
}
else if named == "Wallet" {
self?.ProfileController.view.isHidden = true
self?.MyBookingsController.view.isHidden = true
self?.WalletController.view.isHidden = false
self?.FAQController.view.isHidden = true
self?.SettingsController.view.isHidden = true
}
else if named == "FAQ" {
self?.ProfileController.view.isHidden = true
self?.MyBookingsController.view.isHidden = true
self?.WalletController.view.isHidden = true
self?.FAQController.view.isHidden = false
self?.SettingsController.view.isHidden = true
}
else if named == "Settings" {
self?.ProfileController.view.isHidden = true
self?.MyBookingsController.view.isHidden = true
self?.WalletController.view.isHidden = true
self?.FAQController.view.isHidden = true
self?.SettingsController.view.isHidden = false
}
})
}
}
extension BeginViewController: UICollectionViewDelegateFlowLayout, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: collectionView.frame.width/2.5, height: collectionView.frame.width/2)
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return data.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! customCell
cell.data = self.data[indexPath.row]
return cell
}
class customCell: UICollectionViewCell {
var data: customData? {
didSet {
guard let data = data else { return }
bg.image = data.image
}
}
fileprivate let bg: UIImageView = {
let iv = UIImageView()
iv.image = #imageLiteral(resourceName: "adam-birkett-cndNklOnHO4-unsplash")
iv.translatesAutoresizingMaskIntoConstraints = false
iv.contentMode = .scaleAspectFill
iv.layer.shadowColor = UIColor.black.cgColor
iv.layer.shadowOpacity = 1
iv.layer.shadowOffset = CGSize.zero
iv.layer.shadowRadius = 10
iv.layer.shadowPath = UIBezierPath(rect: iv.bounds).cgPath
iv.layer.shouldRasterize = false
iv.layer.cornerRadius = 10
iv.clipsToBounds = true
return iv
}()
override init(frame: CGRect) {
super.init(frame: frame)
contentView.addSubview(bg)
bg.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
bg.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
bg.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
bg.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
//if user is not logged in show login
private func handleNotAuthenticated() {
//check auth status
if Auth.auth().currentUser == nil {
//show log in screen
let loginVC = LoginViewController()
loginVC.modalPresentationStyle = .fullScreen
present(loginVC, animated: false)
}
}
}
and Here is the viewController I am trying to present a tableView on. It comes up with a white screen, but no tableView. Nor are my navigation items showing. Even when written programmatically.
import UIKit
class WalletViewController: UIViewController {
var addNewCard = [String]()
let button = UIButton()
let tableView = UITableView()
// MARK: - Properties
override func viewDidLoad() {
super.viewDidLoad()
addTable()
view.backgroundColor = UIColor(named: "RED")
button.setTitle("Add New Card", for: .normal)
view.addSubview(button)
button.backgroundColor = UIColor(named: "yellow-2")
button.setTitleColor(UIColor(named: "RED"), for: .normal)
button.frame = CGRect(x: 25, y: 700, width: 350, height: 50)
button.layer.cornerRadius = 15
button.addTarget(self, action: #selector(didTapAddButton), for: .touchUpInside)
if !UserDefaults().bool(forKey: "setup") {
UserDefaults().set(true, forKey: "setup")
UserDefaults().set(0, forKey: "count")
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Add New Card", style: .plain, target: self,
action: #selector(didTapAdd))
}
}
func updateCard() {
guard let count = UserDefaults().value(forKey: "count") as? Int else {
return
}
for x in 0..<count {
if let addCard = UserDefaults().value(forKey: "addCard\(x+1)") as? String {
addNewCard.append(addCard)
}
}
}
func addTable() {
tableView.frame = view.bounds
tableView.delegate = self
tableView.dataSource = self
tableView.separatorStyle = .singleLine
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "addCard")
self.view.addSubview(tableView)
}
#IBAction func didTapAdd() {
let vc = storyboard?.instantiateViewController(withIdentifier: "addCard") as! addCardViewController
vc.update = {
DispatchQueue.main.async {
self.updateCard()
}
}
navigationController?.pushViewController(vc, animated: true)
}
#objc private func didTapAddButton() {
let rootVC = addCardViewController()
let navVC = UINavigationController(rootViewController: rootVC)
navVC.modalPresentationStyle = .fullScreen
present(navVC, animated: true)
}
}
extension WalletViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
tableView.deselectRow(at: indexPath, animated: true)
}
}
extension WalletViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let add = tableView.dequeueReusableCell(withIdentifier: "addCard", for: indexPath)
add.textLabel?.text = addNewCard[indexPath.row]
return add
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return addNewCard.count
}
}

Passing Data from one ViewController to Another Programmatically, Swift [duplicate]

This question already has answers here:
How to pass data from modal view controller back when dismissed
(4 answers)
Closed 2 years ago.
I just want to transfer some data between two ViewControllers and also wrote some Code. But, if I update my tableView, the user-given data isn't presented at the tableView. Can anyone help me?
import UIKit
import CoreData
class AddNewRecipeViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
private let reuseIdentifer = "IngredientCell"
let pressGesture = UILongPressGestureRecognizer()
let titleLabel = UILabel()
let tf_one = UITextField()
let tf_two = UITextField()
let tableView = UITableView()
let submitButton = UIButton()
let newButton = UIButton()
var name_array = [String]()
var unit_array = [String]()
var quantity_array = [String]()
let recipeId = Int.random(in: 0...5000)
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
createViewControllerItems()
}
#objc func refresh(){
print(name_array)
self.tableView.reloadData()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
#objc func dismissKeyboard() {
view.endEditing(true)
}
func createViewControllerItems() {
// - MARK: Titel
titleLabel.text = "Neues Rezept"
titleLabel.textColor = .black
titleLabel.textAlignment = .center
titleLabel.font = UIFont(name: "Bradley Hand", size: 24)
view.addSubview(titleLabel)
titleLabel.translatesAutoresizingMaskIntoConstraints = false
titleLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
titleLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 30).isActive = true
titleLabel.widthAnchor.constraint(equalToConstant: 200).isActive = true
titleLabel.heightAnchor.constraint(equalToConstant: 40).isActive = true
newButton.setTitle("test", for: UIControl.State.normal)
newButton.setTitleColor(.black, for: UIControl.State.normal)
newButton.addTarget(self, action: #selector(refresh), for: .touchUpInside)
view.addSubview(newButton)
newButton.translatesAutoresizingMaskIntoConstraints = false
newButton.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 30).isActive = true
newButton.topAnchor.constraint(equalTo: view.topAnchor, constant: 30).isActive = true
newButton.widthAnchor.constraint(equalToConstant: 40).isActive = true
newButton.heightAnchor.constraint(equalToConstant: 40).isActive = true
// - MARK: Überschrift
tf_one.placeholder = "Name"
tf_one.borderStyle = .roundedRect
tf_one.keyboardType = .default
tf_one.spellCheckingType = .yes
tf_one.smartInsertDeleteType = .yes
tf_one.autocorrectionType = .yes
tf_one.autocapitalizationType = .sentences
view.addSubview(tf_one)
tf_one.translatesAutoresizingMaskIntoConstraints = false
tf_one.leftAnchor.constraint(equalTo: view.leftAnchor, constant: 15).isActive = true
tf_one.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
tf_one.widthAnchor.constraint(equalToConstant: 270).isActive = true
tf_one.heightAnchor.constraint(equalToConstant: 34).isActive = true
// - MARK: Anzahl Portionen
tf_two.placeholder = "Anzahl"
tf_two.borderStyle = .roundedRect
tf_two.keyboardType = .decimalPad
view.addSubview(tf_two)
tf_two.translatesAutoresizingMaskIntoConstraints = false
tf_two.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
tf_two.leftAnchor.constraint(equalTo: tf_one.rightAnchor, constant: 3).isActive = true
tf_two.widthAnchor.constraint(equalToConstant: 70).isActive = true
tf_two.heightAnchor.constraint(equalToConstant: 34).isActive = true
// - MARK: Table View
tableView.delegate = self
tableView.dataSource = self
tableView.register(IngredientCell.self, forCellReuseIdentifier: reuseIdentifer)
tableView.rowHeight = 55
view.addSubview(tableView)
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.leftAnchor.constraint(equalTo: view.leftAnchor).isActive = true
tableView.rightAnchor.constraint(equalTo: view.rightAnchor).isActive = true
tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -100).isActive = true
tableView.topAnchor.constraint(equalTo: tf_one.bottomAnchor, constant: 10).isActive = true
// - MARK: Bestätigen
submitButton.layer.cornerRadius = 20
submitButton.clipsToBounds = true
submitButton.backgroundColor = .lightGray
submitButton.setTitle("ok", for: UIControl.State.normal)
submitButton.setTitleColor(.white, for: UIControl.State.normal)
submitButton.titleLabel?.font = UIFont(name: "Chalkduster", size: 24)
submitButton.addTarget(self, action: #selector(save), for: .touchUpInside)
view.addSubview(submitButton)
submitButton.translatesAutoresizingMaskIntoConstraints = false
submitButton.rightAnchor.constraint(equalTo: view.rightAnchor, constant: -30).isActive = true
submitButton.topAnchor.constraint(equalTo: view.topAnchor, constant: 30).isActive = true
submitButton.widthAnchor.constraint(equalToConstant: 40).isActive = true
submitButton.heightAnchor.constraint(equalToConstant: 40).isActive = true
// - MARK: Add Gesture
pressGesture.addTarget(self, action: #selector(pressAction))
view.addGestureRecognizer(pressGesture)
}
#objc func pressAction() {
let generator = UIImpactFeedbackGenerator(style: .heavy)
generator.impactOccurred()
let vc: AddNewIngredientViewController!
vc = AddNewIngredientViewController()
vc.modalPresentationStyle = .automatic
self.present(vc, animated: true)
}
#objc func save() {
//save befor dismiss
dismiss(animated: true, completion: nil)
/*
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
let context = appDelegate.persistentContainer.viewContext
let entityName = "Recipes"
guard let newEntity = NSEntityDescription.entity(forEntityName: entityName, in: context) else {
return
}
let newRecipe = NSManagedObject(entity: newEntity, insertInto: context)
let name = tf_one.text
let id = recipeId
let category = 1
let persons = 2
newRecipe.setValue(name, forKey: "name")
newRecipe.setValue(id, forKey: "id")
newRecipe.setValue(category, forKey: "category")
newRecipe.setValue(persons, forKey: "persons")
do {
try context.save()
print("Gespeichert!")
let vc: ViewController!
vc = ViewController()
vc.modalPresentationStyle = .fullScreen
self.present(vc, animated: false)
} catch {
print(error)
}*/
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
print(name_array.count)
return name_array.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifer, for: indexPath) as! IngredientCell
cell.nameLabel.text = name_array[indexPath.row]
cell.descriptionLabel.text = "text"
cell.personsLabel.text = "text"
return cell
}
func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCell.EditingStyle, forRowAt indexPath: IndexPath) {
if editingStyle == .delete {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
return
}
let context = appDelegate.persistentContainer.viewContext
let entityName = "/ENTRY/"
let request = NSFetchRequest<NSFetchRequestResult>(entityName: entityName)
do {
let results = try context.fetch(request)
guard results.count > 0 else {
return
}
if let deleteEntity = results[indexPath.row] as? NSManagedObject {
context.delete(deleteEntity) //Das Entity ist hier nur markiert als gelöscht, für evt arbeiten am Item
if context.hasChanges {
do {
try context.save()
print("Datensatz gelöscht!")
let vc: ViewController!
vc = ViewController()
vc.modalPresentationStyle = .fullScreen
self.present(vc, animated: false)
} catch {
print(error)
}
}
}
} catch {
print(error)
}
}
}
}
import UIKit
import CoreData
class AddNewIngredientViewController: UIViewController {
let viewExample = UIView()
let titleLabel = UILabel()
let tf_one = UITextField()
let unitTicker = UISegmentedControl()
let unitLabel = UILabel()
let slider = UISlider()
let submitButton = UIButton()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = UIColor.white.withAlphaComponent(0)
createViewControllerItems()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view.endEditing(true)
}
#objc func dismissKeyboard() {
view.endEditing(true)
}
func createViewControllerItems() {
// - MARK: View
viewExample.backgroundColor = .white
viewExample.layer.cornerRadius = 15
viewExample.clipsToBounds = true
view.addSubview(viewExample)
viewExample.translatesAutoresizingMaskIntoConstraints = false
viewExample.centerYAnchor.constraint(equalTo: view.centerYAnchor, constant: -200).isActive = true
viewExample.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
viewExample.widthAnchor.constraint(equalToConstant: 330).isActive = true
viewExample.heightAnchor.constraint(equalToConstant: 350).isActive = true
// - MARK: Titel
titleLabel.text = "Zutat hinzufügen"
titleLabel.textColor = .black
titleLabel.textAlignment = .center
titleLabel.font = UIFont(name: "Chalkduster", size: 24)
view.addSubview(titleLabel)
titleLabel.translatesAutoresizingMaskIntoConstraints = false
titleLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
titleLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 50).isActive = true
titleLabel.widthAnchor.constraint(equalToConstant: 250).isActive = true
titleLabel.heightAnchor.constraint(equalToConstant: 40).isActive = true
// - MARK: Überschrift
tf_one.placeholder = "Name"
tf_one.borderStyle = .roundedRect
tf_one.keyboardType = .default
tf_one.spellCheckingType = .yes
tf_one.smartInsertDeleteType = .yes
tf_one.autocorrectionType = .yes
tf_one.autocapitalizationType = .sentences
view.addSubview(tf_one)
tf_one.translatesAutoresizingMaskIntoConstraints = false
tf_one.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
tf_one.topAnchor.constraint(equalTo: view.topAnchor, constant: 100).isActive = true
tf_one.widthAnchor.constraint(equalToConstant: 310).isActive = true
tf_one.heightAnchor.constraint(equalToConstant: 34).isActive = true
// - MARK: Unit Ticker
unitTicker.insertSegment(withTitle: "ml", at: 0, animated: true)
unitTicker.insertSegment(withTitle: "mg", at: 1, animated: true)
unitTicker.insertSegment(withTitle: "unit", at: 2, animated: true)
unitTicker.addTarget(self, action: #selector(updateLabel), for: UIControl.Event.allEvents)
view.addSubview(unitTicker)
unitTicker.translatesAutoresizingMaskIntoConstraints = false
unitTicker.topAnchor.constraint(equalTo: view.topAnchor, constant: 150).isActive = true
unitTicker.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
// - MARK: Slider
slider.maximumValue = 10
slider.addTarget(self, action: #selector(updateLabel), for: UIControl.Event.allEvents)
view.addSubview(slider)
slider.translatesAutoresizingMaskIntoConstraints = false
slider.topAnchor.constraint(equalTo: view.topAnchor, constant: 200).isActive = true
slider.widthAnchor.constraint(equalToConstant: 310).isActive = true
slider.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
// - MARK: Bestätigen
submitButton.layer.cornerRadius = 20
submitButton.clipsToBounds = true
submitButton.backgroundColor = .lightGray
submitButton.setTitle("ok", for: UIControl.State.normal)
submitButton.titleLabel?.font = UIFont(name: "Chalkduster", size: 24)
submitButton.addTarget(self, action: #selector(save), for: .touchUpInside)
view.addSubview(submitButton)
submitButton.translatesAutoresizingMaskIntoConstraints = false
submitButton.centerXAnchor.constraint(equalTo: view.centerXAnchor, constant: 100).isActive = true
submitButton.topAnchor.constraint(equalTo: slider.bottomAnchor, constant: 50).isActive = true
submitButton.widthAnchor.constraint(equalToConstant: 40).isActive = true
submitButton.heightAnchor.constraint(equalToConstant: 40).isActive = true
}
#objc func updateLabel() {
unitLabel.textAlignment = .center
if unitTicker.selectedSegmentIndex == 0{
unitLabel.text = "\(Int(slider.value)) ml"
slider.maximumValue = 1000
}else if unitTicker.selectedSegmentIndex == 1{
unitLabel.text = "\(Int(slider.value)) mg"
slider.maximumValue = 1000
}else if unitTicker.selectedSegmentIndex == 2{
unitLabel.text = "\(Int(slider.value)) unit"
slider.maximumValue = 10
}
view.addSubview(unitLabel)
unitLabel.translatesAutoresizingMaskIntoConstraints = false
unitLabel.topAnchor.constraint(equalTo: view.topAnchor, constant: 230).isActive = true
unitLabel.widthAnchor.constraint(equalToConstant: 310).isActive = true
unitLabel.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
}
#objc func save() {
let viewController = AddNewRecipeViewController()
viewController.name_array.append(tf_one.text!)
print(viewController.name_array)
dismiss(animated: true, completion: nil)
}
}
Thanks!
Tom
You can pass data between two viewController by using the delegate method or NSNotificaton. For more info visit about NSNotification: https://developer.apple.com/documentation/foundation/nsnotification
For delegate method you can check https://medium.com/#jamesrochabrun/implementing-delegates-in-swift-step-by-step-d3211cbac3ef

Struggling to adjust cell height with increase in content

I have been struggling greatly almost regularly to be able to create a cell whose height adjusts with content while trying to do it programatically, some things i am trying are , image shows the problem
use below function
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
2)Use this in viewDidLoad
tableView.rowHeight = UITableView.automaticDimension
tableView.estimatedRowHeight = 100
Setting bottom and top constraints to equal rather then not equal
Below i paste some code to show my struggle or trying every thing to get the cell to expand with content, which it does. not, can any one please suggest some ways to achieve it
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
switch indexPath.row {
case 0:
let cell = restaurantMainTable.dequeueReusableCell(withIdentifier: String(describing: RestaurantMainViewCells.self), for: indexPath) as! RestaurantMainViewCells
cell.heightAnchor.constraint(greaterThanOrEqualToConstant: 60).isActive = true
view.addSubview(cell)
view.addSubview(cell.contentView)
view.addSubview(cell.restaurantName)
view.addSubview(cell.restaurantType)
view.addSubview(cell.restaurantLocation)
view.addSubview(cell.restaurantMiniImage)
view.addSubview(cell.restaurantHeartImage)
cell.restaurantHeartImage.translatesAutoresizingMaskIntoConstraints = false
cell.restaurantMiniImage.translatesAutoresizingMaskIntoConstraints = false
cell.restaurantName.translatesAutoresizingMaskIntoConstraints = false
cell.restaurantLocation.translatesAutoresizingMaskIntoConstraints = false
cell.restaurantType.translatesAutoresizingMaskIntoConstraints = false
//Fonts
let font = UIFont(name: "Rubik-Medium", size: 18)
let fontMetrics = UIFontMetrics(forTextStyle: .body)
let labels = [cell.restaurantName, cell.restaurantLocation, cell.restaurantType]
labels.forEach { label in
label.font = fontMetrics.scaledFont(for: font!)
}
let stackLabels = UIStackView()
view.addSubview(stackLabels)
stackLabels.alignment = .top
stackLabels.distribution = .fill
stackLabels.spacing = 5
stackLabels.axis = .vertical
stackLabels.addArrangedSubview(cell.restaurantName)
stackLabels.addArrangedSubview(cell.restaurantType)
stackLabels.addArrangedSubview(cell.restaurantLocation)
let stackImage = UIStackView()
view.addSubview(stackImage)
stackLabels.translatesAutoresizingMaskIntoConstraints = false
stackImage.alignment = .top
stackImage.distribution = .fill
stackImage.axis = .horizontal
stackImage.spacing = 5
cell.restaurantMiniImage.heightAnchor.constraint(equalToConstant: 60).isActive = true
cell.restaurantMiniImage.widthAnchor.constraint(equalToConstant: 60).isActive = true
cell.restaurantMiniImage.layer.cornerRadius = 30
cell.restaurantMiniImage.clipsToBounds = true
cell.restaurantHeartImage.heightAnchor.constraint(equalToConstant: 20).isActive = true
cell.restaurantHeartImage.widthAnchor.constraint(equalToConstant: 20).isActive = true
cell.restaurantHeartImage.trailingAnchor.constraint(equalTo: cell.trailingAnchor, constant: -10).isActive = true
cell.restaurantHeartImage.topAnchor.constraint(equalTo: cell.topAnchor, constant: 20).isActive = true
stackImage.addArrangedSubview(cell.restaurantMiniImage)
stackImage.addArrangedSubview(stackLabels)
view.addSubview(stackImage)
stackImage.translatesAutoresizingMaskIntoConstraints = false
stackImage.leadingAnchor.constraint(equalTo: cell.leadingAnchor, constant: 10).isActive = true
stackImage.topAnchor.constraint(greaterThanOrEqualTo: cell.topAnchor, constant: 10).isActive = true
// stackImage.topAnchor.constraint(equalTo: cell.topAnchor, constant: 10).isActive = true
stackImage.trailingAnchor.constraint(equalTo: cell.restaurantHeartImage.leadingAnchor, constant: -10).isActive = true
// stackImage.bottomAnchor.constraint(equalTo: cell.bottomAnchor, constant: -10).isActive = true
stackImage.bottomAnchor.constraint(greaterThanOrEqualTo: cell.bottomAnchor, constant: -10).isActive = true
cell.restaurantName.text = restaurants[indexPath.row].name
cell.restaurantType.text = restaurants[indexPath.row].type
cell.restaurantLocation.text = restaurants[indexPath.row].location
cell.restaurantHeartImage.image = UIImage(named: "heart-tick")
if let restaurantImage = restaurants[indexPath.row].image {
cell.restaurantMiniImage.image = UIImage(data: restaurantImage as Data)
}
return cell
default:
fatalError("no data found")
}
}
UPDATE - The whole class
//
// RestaurantMainController.swift
// LaVivaRepeat
//
//
import UIKit
import CoreData
class RestaurantMainController: UIViewController, UITableViewDelegate, UITableViewDataSource, NSFetchedResultsControllerDelegate {
var restaurants: [Restaurant] = []
var fetchResultController: NSFetchedResultsController<Restaurant>!
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return restaurants.count
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
let restaurantMainTable = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(restaurantMainTable)
//MARK:- add delegates as self, always, else no contact with model will take place
restaurantMainTable.rowHeight = UITableView.automaticDimension
restaurantMainTable.estimatedRowHeight = 60
self.restaurantMainTable.delegate = self
self.restaurantMainTable.dataSource = self
self.restaurantMainTable.separatorStyle = .singleLine
//MARK:- create a view to show when no records are there
let backGroundView = UIView()
view.addSubview(backGroundView)
backGroundView.heightAnchor.constraint(equalToConstant: 500).isActive = true
let backGroundImage = UIImageView()
backGroundImage.translatesAutoresizingMaskIntoConstraints = false
backGroundView.translatesAutoresizingMaskIntoConstraints = false
backGroundImage.heightAnchor.constraint(equalToConstant: 300).isActive = true
backGroundImage.widthAnchor.constraint(equalToConstant: 320).isActive = true
backGroundImage.image = UIImage(named: "empty")
backGroundView.addSubview(backGroundImage)
backGroundView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 30).isActive = true
backGroundView.topAnchor.constraint(equalTo: view.topAnchor, constant: 90).isActive = true
backGroundView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 20).isActive = true
restaurantMainTable.backgroundView = backGroundView
restaurantMainTable.backgroundView?.isHidden = true
//MARK:- Add constraints to table
self.restaurantMainTable.translatesAutoresizingMaskIntoConstraints = false
self.restaurantMainTable.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
self.restaurantMainTable.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
self.restaurantMainTable.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
self.restaurantMainTable.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
//MARK:- register RestaurantMainViewCells
self.restaurantMainTable.register(RestaurantMainViewCells.self, forCellReuseIdentifier: String(describing: RestaurantMainViewCells.self))
//MARK:- Get fetch request
let fetchRequest: NSFetchRequest<Restaurant> = Restaurant.fetchRequest()
let sortDescriptor = NSSortDescriptor(key: "name", ascending: true)
fetchRequest.sortDescriptors = [sortDescriptor]
if let appDelegate = (UIApplication.shared.delegate as? AppDelegate) {
let context = appDelegate.persistentContainer.viewContext
fetchResultController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
fetchResultController.delegate = self
do {
try fetchResultController.performFetch()
if let fetchObject = fetchResultController.fetchedObjects {
restaurants = fetchObject
}
}
catch {
print(error)
}
}
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
restaurantMainTable.rowHeight = UITableView.automaticDimension
switch indexPath.row {
case 0:
let cell = restaurantMainTable.dequeueReusableCell(withIdentifier: String(describing: RestaurantMainViewCells.self), for: indexPath) as! RestaurantMainViewCells
// cell.heightAnchor.constraint(greaterThanOrEqualToConstant: 60).isActive = true
view.addSubview(cell)
view.addSubview(cell.contentView)
view.addSubview(cell.restaurantName)
view.addSubview(cell.restaurantType)
view.addSubview(cell.restaurantLocation)
view.addSubview(cell.restaurantMiniImage)
view.addSubview(cell.restaurantHeartImage)
cell.restaurantHeartImage.translatesAutoresizingMaskIntoConstraints = false
cell.restaurantMiniImage.translatesAutoresizingMaskIntoConstraints = false
cell.restaurantName.translatesAutoresizingMaskIntoConstraints = false
cell.restaurantLocation.translatesAutoresizingMaskIntoConstraints = false
cell.restaurantType.translatesAutoresizingMaskIntoConstraints = false
//Fonts
let font = UIFont(name: "Rubik-Medium", size: 18)
let fontMetrics = UIFontMetrics(forTextStyle: .body)
let labels = [cell.restaurantName, cell.restaurantLocation, cell.restaurantType]
labels.forEach { label in
label.font = fontMetrics.scaledFont(for: font!)
}
let stackLabels = UIStackView()
view.addSubview(stackLabels)
stackLabels.alignment = .top
stackLabels.distribution = .fill
stackLabels.spacing = 5
stackLabels.axis = .vertical
stackLabels.addArrangedSubview(cell.restaurantName)
stackLabels.addArrangedSubview(cell.restaurantType)
stackLabels.addArrangedSubview(cell.restaurantLocation)
let stackImage = UIStackView()
view.addSubview(stackImage)
stackLabels.translatesAutoresizingMaskIntoConstraints = false
stackImage.alignment = .top
stackImage.distribution = .fill
stackImage.axis = .horizontal
stackImage.spacing = 5
cell.restaurantMiniImage.heightAnchor.constraint(equalToConstant: 60).isActive = true
cell.restaurantMiniImage.widthAnchor.constraint(equalToConstant: 60).isActive = true
cell.restaurantMiniImage.layer.cornerRadius = 30
cell.restaurantMiniImage.clipsToBounds = true
cell.restaurantHeartImage.heightAnchor.constraint(equalToConstant: 20).isActive = true
cell.restaurantHeartImage.widthAnchor.constraint(equalToConstant: 20).isActive = true
cell.restaurantHeartImage.trailingAnchor.constraint(equalTo: cell.trailingAnchor, constant: -10).isActive = true
cell.restaurantHeartImage.topAnchor.constraint(equalTo: cell.topAnchor, constant: 20).isActive = true
stackImage.addArrangedSubview(cell.restaurantMiniImage)
stackImage.addArrangedSubview(stackLabels)
view.addSubview(stackImage)
stackImage.translatesAutoresizingMaskIntoConstraints = false
stackImage.leadingAnchor.constraint(equalTo: cell.leadingAnchor, constant: 10).isActive = true
stackImage.topAnchor.constraint(greaterThanOrEqualTo: cell.topAnchor, constant: 10).isActive = true
// stackImage.topAnchor.constraint(equalTo: cell.topAnchor, constant: 10).isActive = true
stackImage.trailingAnchor.constraint(equalTo: cell.restaurantHeartImage.leadingAnchor, constant: -10).isActive = true
// stackImage.bottomAnchor.constraint(equalTo: cell.bottomAnchor, constant: -10).isActive = true
stackImage.bottomAnchor.constraint(greaterThanOrEqualTo: cell.bottomAnchor, constant: -10).isActive = true
cell.restaurantName.text = restaurants[indexPath.row].name
cell.restaurantType.text = restaurants[indexPath.row].type
cell.restaurantLocation.text = restaurants[indexPath.row].location
cell.restaurantHeartImage.image = UIImage(named: "heart-tick")
if let restaurantImage = restaurants[indexPath.row].image {
cell.restaurantMiniImage.image = UIImage(data: restaurantImage as Data)
}
return cell
default:
fatalError("no data found")
}
}
//MARK:- Make custom navigation bar large font size and use rubik fonts
override func viewWillAppear(_ animated: Bool) {
navigationController?.navigationBar.prefersLargeTitles = true
self.navigationController?.navigationBar.topItem?.title = "LaViva Hotel"
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.shadowImage = UIImage()
navigationController?.hidesBarsOnSwipe = true
if let customFont = UIFont(name: "Rubik-Medium", size: 40) {
navigationController?.navigationBar.largeTitleTextAttributes = [NSAttributedString.Key.foregroundColor: UIColor(red: 200/255, green: 70/255, blue: 70/255, alpha: 1), NSAttributedString.Key.font: customFont]
}
//MARK:- for empty table
if restaurants.count > 0 {
self.restaurantMainTable.backgroundView?.isHidden = true
self.restaurantMainTable.separatorStyle = .singleLine
}
else {
self.restaurantMainTable.backgroundView?.isHidden = false
self.restaurantMainTable.separatorStyle = .none
}
//MARK:- make an + button appear on top left
let addButton = UIBarButtonItem(image: UIImage(named: "plus"), style: .plain, target: self, action: #selector(addNewRestaurant))
//navigationController?.navigationItem.rightBarButtonItem = addButton
self.navigationItem.rightBarButtonItem = addButton
}
//MARK:- addNewRestaurant function
#objc func addNewRestaurant() {
let pushController = RestaurantAddController()
navigationController?.pushViewController(pushController, animated: true)
}
//MARK:- try and show cell and tower as default or dark done here
override var preferredStatusBarStyle: UIStatusBarStyle {
return .default
}
//add update delete
func controllerWillChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
restaurantMainTable.beginUpdates()
}
func controller(_ controller: NSFetchedResultsController<NSFetchRequestResult>, didChange anObject: Any, at indexPath: IndexPath?, for type: NSFetchedResultsChangeType, newIndexPath: IndexPath?) {
switch type {
case .insert:
if let newIndexPath = newIndexPath {
restaurantMainTable.insertRows(at: [newIndexPath], with: .fade)
}
case .delete:
if let indexPath = indexPath {
restaurantMainTable.deleteRows(at: [indexPath], with: .fade)
}
case .update:
if let indexPath = indexPath {
restaurantMainTable.reloadRows(at: [indexPath], with: .fade)
}
default:
restaurantMainTable.reloadData()
}
if let fetchedObjects = controller.fetchedObjects {
restaurants = fetchedObjects as! [Restaurant]
}
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
restaurantMainTable.endUpdates()
}
//MARK:- left swipr delete
func tableView(_ tableView: UITableView, trailingSwipeActionsConfigurationForRowAt indexPath: IndexPath) -> UISwipeActionsConfiguration? {
let deleteAction = UIContextualAction(style: .destructive, title: "Delete") { (action, view, completionHandler) in
if let appDelegate = (UIApplication.shared.delegate as? AppDelegate) {
let context = appDelegate.persistentContainer.viewContext
let restaurantsToDelete = self.fetchResultController.object(at: indexPath)
context.delete(restaurantsToDelete)
appDelegate.saveContext()
}
completionHandler(true)
}
let swipeConfiguration: UISwipeActionsConfiguration
swipeConfiguration = UISwipeActionsConfiguration(actions: [deleteAction])
return swipeConfiguration
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
}
UPDATE
import UIKit
class RestaurantMainViewCells: UITableViewCell {
var restaurantMiniImage = UIImageView()
var restaurantHeartImage = UIImageView()
var restaurantName = UILabel()
var restaurantType = UILabel()
var restaurantLocation = UILabel()
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
All of your cell setup - adding and constraining UI elements - should be done in your cell class. Absolutely NOT in cellForRowAt.
You would do well to go through a few tutorials on creating dynamic cells.
But, to give you an idea, here is your code modified so you can see what's happening:
struct Restaurant {
var name: String = ""
var type: String = ""
var location: String = ""
// however you have your image information stored
//var image
}
class RestaurantMainViewCells: UITableViewCell {
var restaurantMiniImage = UIImageView()
var restaurantHeartImage = UIImageView()
var restaurantName = UILabel()
var restaurantType = UILabel()
var restaurantLocation = UILabel()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
commonInit()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func commonInit() -> Void {
// so we can see the image view frames without actual images...
restaurantMiniImage.backgroundColor = .green
restaurantHeartImage.backgroundColor = .red
var font: UIFont = UIFont.systemFont(ofSize: 18)
if let f = UIFont(name: "Rubik-Medium", size: 18) {
font = f
}
let fontMetrics = UIFontMetrics(forTextStyle: .body)
let labels = [restaurantName, restaurantLocation, restaurantType]
labels.forEach { label in
label.font = fontMetrics.scaledFont(for: font)
// so we can see label frames...
label.backgroundColor = .yellow
}
let stackLabels = UIStackView()
stackLabels.alignment = .fill
stackLabels.distribution = .fill
stackLabels.spacing = 5
stackLabels.axis = .vertical
stackLabels.addArrangedSubview(restaurantName)
stackLabels.addArrangedSubview(restaurantType)
stackLabels.addArrangedSubview(restaurantLocation)
let stackImage = UIStackView()
stackImage.alignment = .top
stackImage.distribution = .fill
stackImage.axis = .horizontal
stackImage.spacing = 5
restaurantMiniImage.layer.cornerRadius = 30
restaurantMiniImage.clipsToBounds = true
stackImage.addArrangedSubview(restaurantMiniImage)
stackImage.addArrangedSubview(stackLabels)
contentView.addSubview(stackImage)
contentView.addSubview(restaurantHeartImage)
restaurantHeartImage.translatesAutoresizingMaskIntoConstraints = false
stackImage.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
// mini image 60x60
restaurantMiniImage.heightAnchor.constraint(equalToConstant: 60),
restaurantMiniImage.widthAnchor.constraint(equalToConstant: 60),
// heart image 20 x 20
restaurantHeartImage.heightAnchor.constraint(equalToConstant: 20),
restaurantHeartImage.widthAnchor.constraint(equalToConstant: 20),
// heart image top+20 trailing-10
restaurantHeartImage.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 20),
restaurantHeartImage.trailingAnchor.constraint(equalTo: contentView.trailingAnchor, constant: -10),
// horizontal stack top / leading / bottom and trailinh to heart image
// all with 10-pts "padding"
stackImage.topAnchor.constraint(equalTo: contentView.topAnchor, constant: 10),
stackImage.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 10),
stackImage.trailingAnchor.constraint(equalTo: restaurantHeartImage.leadingAnchor, constant: -10),
stackImage.bottomAnchor.constraint(equalTo: contentView.bottomAnchor, constant: -10),
])
}
}
class RestaurantMainController: UIViewController, UITableViewDelegate, UITableViewDataSource {
var restaurants: [Restaurant] = []
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return restaurants.count
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
let restaurantMainTable = UITableView()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(restaurantMainTable)
//MARK:- add delegates as self, always, else no contact with model will take place
restaurantMainTable.estimatedRowHeight = 60
self.restaurantMainTable.delegate = self
self.restaurantMainTable.dataSource = self
self.restaurantMainTable.separatorStyle = .singleLine
//MARK:- Add constraints to table
self.restaurantMainTable.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
restaurantMainTable.topAnchor.constraint(equalTo: view.topAnchor),
restaurantMainTable.bottomAnchor.constraint(equalTo: view.bottomAnchor),
restaurantMainTable.leadingAnchor.constraint(equalTo: view.leadingAnchor),
restaurantMainTable.trailingAnchor.constraint(equalTo: view.trailingAnchor),
])
//MARK:- register RestaurantMainViewCells
self.restaurantMainTable.register(RestaurantMainViewCells.self, forCellReuseIdentifier: String(describing: RestaurantMainViewCells.self))
//MARK:- Get fetch request
// I don't have your "fetch" data, so I'm just adding a couple restaurants here
restaurants.append(Restaurant(name: "Cafe De Loir", type: "Chinese Cousine", location: "Hong Kong"))
restaurants.append(Restaurant(name: "Bob's Cafe", type: "Japanese Cousine", location: "Tokyo"))
restaurants.append(Restaurant(name: "Mary's Restaurant", type: "Home Cooking", location: "Dallas, Texas"))
// let fetchRequest: NSFetchRequest<Restaurant> = Restaurant.fetchRequest()
// let sortDescriptor = NSSortDescriptor(key: "name", ascending: true)
// fetchRequest.sortDescriptors = [sortDescriptor]
//
// if let appDelegate = (UIApplication.shared.delegate as? AppDelegate) {
// let context = appDelegate.persistentContainer.viewContext
// fetchResultController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
// fetchResultController.delegate = self
//
// do {
// try fetchResultController.performFetch()
// if let fetchObject = fetchResultController.fetchedObjects {
// restaurants = fetchObject
// }
// }
//
// catch {
// print(error)
// }
// }
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: RestaurantMainViewCells.self), for: indexPath) as! RestaurantMainViewCells
let r = restaurants[indexPath.row]
cell.restaurantName.text = r.name
cell.restaurantType.text = r.type
cell.restaurantLocation.text = r.location
//if let restaurantImage = restaurants[indexPath.row].image {
// cell.restaurantMiniImage.image = UIImage(data: restaurantImage as Data)
//}
cell.restaurantHeartImage.image = UIImage(named: "heart-tick")
return cell
}
}
The result (I don't have your images so the image views have green or red background color):

Protocol and delegate pattern not calling the method

Implementing a protocol/delegate pattern as suggested by expert #DonMag, i am unable to get the code working...
I show a ratings window like below and when the user changes the ratings , i want the ratings emoji to update and the controller to pop, i also use animation, now for view i have a separate ratings class and for controller a separate class,
The problem is this function gets tapped , i can detect it but it does not reach the protocol method
#objc func ratingButtonTapped(_ sender: UIButton) {
// print(sender.titleLabel?.text)
guard let t = sender.titleLabel?.text else {
return
}
ratingDelegate?.defineTheratings(t)
}
Controller class
import UIKit
import CoreData
protocol RatingsPresentation: class {
func defineTheratings(_ ratings: String)
}
class RatingsViewController: UIViewController, RatingsPresentation {
func defineTheratings(_ ratings: String) {
print("ratings seleced\(ratings)")
self.restaurant.rating = ratings
if let appDelegate = (UIApplication.shared.delegate as? AppDelegate) {
appDelegate.saveContext()
}
if self.presentedViewController != nil {
self.dismiss(animated: true, completion: nil)
}
else {
self.navigationController?.popViewController(animated: true)
}
}
var restaurant: Restaurant!
var rates = RatingsView()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(rates.view)
//Delegates
let vc = RatingsView()
// set the rating delegate
vc.ratingDelegate = self
//
if let restaurantImage = restaurant.image {
rates.bkgImageView.image = UIImage(data: restaurantImage as Data)
}
rates.crossBtn.addTarget(self, action: #selector(closeRatings), for: .touchUpInside)
let animateCross = CGAffineTransform(translationX: 1000, y: 0)
rates.crossBtn.transform = animateCross
}
#objc func closeRatings() {
navigationController?.popViewController(animated: true)
}
}
View Class
import UIKit
class RatingsView: UIViewController {
var bkgImageView = UIImageView()
var crossBtn = UIButton()
var btnCollection: [UIButton] = []
weak var ratingDelegate: RatingsPresentation?
override func viewDidLoad() {
super.viewDidLoad()
let ratings: [String] = ["cool", "happy","love", "sad", "angry"]
let animationBlur = UIBlurEffect(style: .dark)
let visualBlurView = UIVisualEffectView(effect: animationBlur)
// add elements to self
view.addSubview(bkgImageView)
view.addSubview(visualBlurView)
bkgImageView.translatesAutoresizingMaskIntoConstraints = false
visualBlurView.translatesAutoresizingMaskIntoConstraints = false
bkgImageView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
bkgImageView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
bkgImageView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
bkgImageView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
// constrain visualBlurView to all 4 sides
visualBlurView.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
visualBlurView.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
visualBlurView.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
visualBlurView.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
bkgImageView.contentMode = .scaleAspectFill
// Do any additional setup after loading the view.
//Add stackView
let stackEmoji = UIStackView()
stackEmoji.translatesAutoresizingMaskIntoConstraints = false
stackEmoji.axis = .vertical
stackEmoji.spacing = 5
stackEmoji.distribution = .fill
stackEmoji.alignment = .top
let font = UIFont(name: "Rubik-Medium", size: 28)
let fontM = UIFontMetrics(forTextStyle: .body)
ratings.forEach { (btn) in
let b = UIButton()
b.setTitle(btn, for: .normal)
b.titleLabel?.font = fontM.scaledFont(for: font!)
b.setImage(UIImage(named: btn), for: .normal)
stackEmoji.addArrangedSubview(b)
btnCollection.append(b)
//btn animation
let sizeAnimation = CGAffineTransform(scaleX: 5, y: 5)
let positionAnimation = CGAffineTransform(translationX: 1000, y: 0)
let combinedAninaton = sizeAnimation.concatenating(positionAnimation)
b.transform = combinedAninaton
b.addTarget(self, action: #selector(ratingButtonTapped(_:)), for: .touchUpInside)
}
view.addSubview(stackEmoji)
stackEmoji.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
stackEmoji.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
// if let img = UIImage(named: "cross") {
// crossBtn.setImage(img, for: [])
// }
crossBtn.setTitle("X", for: [])
crossBtn.setTitleColor(.white, for: .normal)
crossBtn.setTitleColor(.gray, for: .highlighted)
crossBtn.titleLabel?.font = UIFont.systemFont(ofSize: 44, weight: .bold)
view.addSubview(crossBtn)
crossBtn.translatesAutoresizingMaskIntoConstraints = false
crossBtn.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -30).isActive = true
crossBtn.topAnchor.constraint(equalTo: view.topAnchor, constant: 150).isActive = true
}
#objc func ratingButtonTapped(_ sender: UIButton) {
// print(sender.titleLabel?.text)
guard let t = sender.titleLabel?.text else {
return
}
ratingDelegate?.defineTheratings(t)
}
}
Problem is here
var rates = RatingsView() //// shown 1
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(rates.view) /////// you add this as a subview
//Delegates
let vc = RatingsView() //////// this is useless - not shown 1
// set the rating delegate
vc.ratingDelegate = self ////// and set the delegate for this non-shown
So you need to remove let vc = RatingsView() and set the delegate for
rates.ratingDelegate = self

Resources