Swift - UIButton in UICollectionViewCell not clickable - swift

I currently have a UICollectionViewController to display all my news articles. For my news items, I have created a custom UICollectionViewCell with a small button in the top right corner.
The problem is that it is only working when I set my feedCell to isUserInteractionEnabled = true. I only want the newsMenu button to be clickable, not have the whole cell to be selectable.
How do I achieve this?
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let feedCell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! FeedCell
feedCell.post = m_Collection?[(indexPath as NSIndexPath).item]
feedCell.newsMenu.addTarget(self, action: #selector(imageTapped), for: .touchUpInside)
return feedCell
}
func imageTapped(button: UIButton)
{
let newsAction = UIAlertController(title: "Message", message: "Do you want to edit or delete this news message?", preferredStyle: .actionSheet)
let editAction = UIAlertAction(title: "Edit news", style: .default, handler: menuEditNews)
let deleteAction = UIAlertAction(title: "Delete news", style: .destructive, handler: menuDeleteNews)
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
newsAction.addAction(editAction)
newsAction.addAction(deleteAction)
newsAction.addAction(cancelAction)
self.present(newsAction, animated: true, completion: nil)
}
My custom cell:
class FeedCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
let titleLabel: UILabel = {
let label = UILabel()
label.adjustsFontSizeToFitWidth = false
label.lineBreakMode = .byTruncatingTail
label.numberOfLines = 2
return label
}()
let profileImageView: UIImageView = {
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.image = UIImage(named: "")
imageView.layer.cornerRadius = 22
imageView.layer.masksToBounds = true
return imageView
}()
let newsTextView: UITextView = {
let textView = UITextView()
textView.isScrollEnabled = false
textView.font = UIFont (name: "Helvetica", size: 13)
return textView
}()
let newsMenu: UIButton = {
let newsMenu = UIButton()
newsMenu.isUserInteractionEnabled = true
newsMenu.setImage(UIImage(named: "news_menuitem"), for: UIControlState())
return newsMenu
}()
func setupViews() {
backgroundColor = UIColor.white
addSubview(titleLabel)
addSubview(profileImageView)
addSubview(newsTextView)
addSubview(newsMenu)
addConstraintsWithFormat("H:|-8-[v0(44)]-8-[v1]-10-[v2(25)]-8-|", views: profileImageView, titleLabel, newsMenu)
addConstraintsWithFormat("H:|-4-[v0]-4-|", views: newsTextView)
addConstraintsWithFormat("V:|-6-[v0]", views: newsMenu)
addConstraintsWithFormat("V:|-10-[v0]", views: titleLabel)
addConstraintsWithFormat("V:|-8-[v0(44)]-4-[v1]", views: profileImageView, newsTextView)
}
}

The reason why the keyboard appears when tapping the cell is most likely that you're in fact tapping on the UITextView, to prevent this behavior just set the isUserInteractionEnabled flag to false on the newsTextView object.

Change your code to:
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let feedCell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! FeedCell
feedCell.post = m_Collection?[(indexPath as NSIndexPath).item]
feedCell.sourceController = self // assign controller
return feedCell
}
func imageTapped() // remove (button: UIButton)
{
let newsAction = UIAlertController(title: "Message", message: "Do you want to edit or delete this news message?", preferredStyle: .actionSheet)
let editAction = UIAlertAction(title: "Edit news", style: .default, handler: menuEditNews)
let deleteAction = UIAlertAction(title: "Delete news", style: .destructive, handler: menuDeleteNews)
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel)
newsAction.addAction(editAction)
newsAction.addAction(deleteAction)
newsAction.addAction(cancelAction)
self.present(newsAction, animated: true, completion: nil)
}
And your custom cell:
class FeedCell: UICollectionViewCell {
override init(frame: CGRect) {
super.init(frame: frame)
setupViews()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
weak var sourceController: YourController? // declare new variable
let titleLabel: UILabel = {
let label = UILabel()
label.adjustsFontSizeToFitWidth = false
label.lineBreakMode = .byTruncatingTail
label.numberOfLines = 2
return label
}()
let profileImageView: UIImageView = {
let imageView = UIImageView()
imageView.translatesAutoresizingMaskIntoConstraints = false
imageView.image = UIImage(named: "")
imageView.layer.cornerRadius = 22
imageView.layer.masksToBounds = true
return imageView
}()
let newsTextView: UITextView = {
let textView = UITextView()
textView.isScrollEnabled = false
textView.font = UIFont (name: "Helvetica", size: 13)
return textView
}()
lazy var newsMenu: UIButton = { // change `let` to `lazy var`
let newsMenu = UIButton()
newsMenu.isUserInteractionEnabled = true
newsMenu.setImage(UIImage(named: "news_menuitem"), for: UIControlState())
newsMenu.addTarget(self, action: #selector(actionTap), for: .touchUpInside) // add target to button
return newsMenu
}()
func setupViews() {
backgroundColor = UIColor.white
addSubview(titleLabel)
addSubview(profileImageView)
addSubview(newsTextView)
addSubview(newsMenu)
addConstraintsWithFormat("H:|-8-[v0(44)]-8-[v1]-10-[v2(25)]-8-|", views: profileImageView, titleLabel, newsMenu)
addConstraintsWithFormat("H:|-4-[v0]-4-|", views: newsTextView)
addConstraintsWithFormat("V:|-6-[v0]", views: newsMenu)
addConstraintsWithFormat("V:|-10-[v0]", views: titleLabel)
addConstraintsWithFormat("V:|-8-[v0(44)]-4-[v1]", views: profileImageView, newsTextView)
}
func actionTap() { // handle function
sourceController?. imageTapped()
}
}

imageTapped have param, so you must addtarget:
feedCell.newsMenu.addTarget(self, action: #selector(imageTapped(_:)), for: .touchUpInside)

Related

Swift Tab Bar goes Black instead of disappearing

When I go to my settings view controller, the tab bar is supposed to go away; however instead of going a way it turns black covering some of the settings page. Here is the image (I covered private info):
Here is my code for the settings controller:
private let reuseIdentifier = "SettingsCell"
class SettingsViewController: UIViewController {
// MARK: - Properties
override func viewDidAppear(_ animated: Bool) {
self.navigationController?.navigationBar.prefersLargeTitles = true
}
var tableView: UITableView!
var userInfoHeader: UserInfoHeader!
var user: User?
// MARK: - Init
override func viewDidLoad() {
super.viewDidLoad()
configureUI()
}
// MARK: - Helper Functions
func configureTableView() {
tableView = UITableView()
tableView.delegate = self
tableView.dataSource = self
tableView.rowHeight = 60
tableView.register(SettingsCell.self, forCellReuseIdentifier: reuseIdentifier)
view.addSubview(tableView)
tableView.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 800)
let frame = CGRect(x: 0, y: 0, width: view.frame.width, height: 85)
userInfoHeader = UserInfoHeader(frame: frame)
userInfoHeader.usernameLabel.text = "\(user?.firstName ?? "") \(user?.lastName ?? "")"
userInfoHeader.schoolLabel.text = user?.school
if let imageUrl = user?.imageUrl1, let url = URL(string: imageUrl) {
// Nuke.loadImage(with: url, into: self.image1Button)
SDWebImageManager().loadImage(with: url, options: .continueInBackground, progress: nil) { (image, _, _, _, _, _) in
self.userInfoHeader.profileImageView.image = image
}
}
let tapRecognizer = UITapGestureRecognizer(target: self, action: #selector(goToProfile))
userInfoHeader.addGestureRecognizer(tapRecognizer)
tableView.tableHeaderView = userInfoHeader
tableView.tableFooterView = UIView()
}
#objc fileprivate func goToProfile() {
let userDetailsController = CurrentUserDetailsNoReportController()
let myBackButton = UIBarButtonItem()
myBackButton.title = " "
navigationItem.backBarButtonItem = myBackButton
userDetailsController.cardViewModel = user?.toCardViewModel()
navigationController?.pushViewController(userDetailsController, animated: true)
}
func configureUI() {
configureTableView()
// navigationController?.navigationBar.isTranslucent = false
navigationItem.title = "Settings"
navigationItem.leftBarButtonItem = UIBarButtonItem(image: #imageLiteral(resourceName: "icons8-chevron-left-30").withRenderingMode(.alwaysOriginal), style: .plain, target: self, action: #selector(handleBack))
}
#objc fileprivate func handleBack() {
dismiss(animated: true)
}
#objc fileprivate func handleSwitchNotification(sender: UISwitch) {
if sender.isOn {
showSettingsAlert(sender: sender)
}
else {
showSettingsAlert(sender: sender)
}
}
#objc fileprivate func handleSwitchLocation(sender: UISwitch) {
if sender.isOn {
showSettingsAlert2(sender: sender)
}
else {
showSettingsAlert2(sender: sender)
}
}
private func showSettingsAlert(sender: UISwitch) {
let alert = UIAlertController(title: "Notifications Permissions", message: "Change your notifications permissions?", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Open Settings", style: .default) { action in
UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!)
})
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { action in
sender.isOn = false
return
})
present(alert, animated: true)
}
private func showSettingsAlert2(sender: UISwitch) {
let alert = UIAlertController(title: "Location Permissions", message: "Change your location permissions?", preferredStyle: .alert)
alert.addAction(UIAlertAction(title: "Open Settings", style: .default) { action in
UIApplication.shared.open(URL(string: UIApplication.openSettingsURLString)!)
})
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel) { action in
sender.isOn = false
return
})
present(alert, animated: true)
}
}
extension SettingsViewController: UITableViewDelegate, UITableViewDataSource {
func numberOfSections(in tableView: UITableView) -> Int {
return SettingsSection.allCases.count
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
guard let section = SettingsSection(rawValue: section) else {return 0}
switch section {
case .Social:
return SocialOptions.allCases.count
case .Communications:
return CommunicationOptions.allCases.count
case .About:
return AboutOptions.allCases.count
}
}
func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 40
}
func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let view = UIView()
view.backgroundColor = .white
let title = UILabel()
title.font = UIFont.boldSystemFont(ofSize: 22)
title.textColor = #colorLiteral(red: 0.2196078449, green: 0.007843137719, blue: 0.8549019694, alpha: 1)
title.text = SettingsSection(rawValue: section)?.description
view.addSubview(title)
title.anchor(top: view.topAnchor, leading: view.leadingAnchor, bottom: view.bottomAnchor, trailing: nil, padding: .init(top: 2, left: 10, bottom: 2, right: 0))
return view
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: reuseIdentifier, for: indexPath) as! SettingsCell
guard let section = SettingsSection(rawValue: indexPath.section) else {return UITableViewCell()}
switch section {
case .Social:
let social = SocialOptions(rawValue: indexPath.row)
cell.sectionType = social
case .Communications:
let communications = CommunicationOptions(rawValue: indexPath.row)
cell.sectionType = communications
switch communications {
case .location:
switch CLLocationManager.authorizationStatus() {
case .notDetermined, .restricted, .denied:
cell.switchControl.isOn = false
cell.switchControl.addTarget(self, action: #selector(handleSwitchLocation), for: .valueChanged)
default:
cell.switchControl.isOn = true
cell.switchControl.addTarget(self, action: #selector(handleSwitchLocation), for: .valueChanged)
}
default:
let isRegisteredForRemoteNotifications = UIApplication.shared.isRegisteredForRemoteNotifications
if isRegisteredForRemoteNotifications {
cell.switchControl.isOn = true
cell.switchControl.addTarget(self, action: #selector(handleSwitchNotification), for: .valueChanged)
} else {
cell.switchControl.isOn = false
cell.switchControl.addTarget(self, action: #selector(handleSwitchNotification), for: .valueChanged)
}
}
case .About:
let about = AboutOptions(rawValue: indexPath.row)
cell.sectionType = about
}
cell.selectionStyle = .none
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
guard let section = SettingsSection(rawValue: indexPath.section) else {return}
switch section {
case .Social:
let social = SocialOptions(rawValue: indexPath.row)
if social?.description == "Edit Profile" {
let settingsController = NiceEditProfile()
settingsController.user = user
let myBackButton = UIBarButtonItem()
myBackButton.title = " "
self.navigationItem.backBarButtonItem = myBackButton
self.navigationController?.pushViewController(settingsController, animated: true)
}
else if social?.description == "Logout" {
let firebaseAuth = Auth.auth()
let loginViewController = LoginViewController()
let navController = UINavigationController(rootViewController: loginViewController)
navController.modalPresentationStyle = .fullScreen
do {
try firebaseAuth.signOut()
} catch { }
present(navController, animated: true)
}
case .Communications:
let communications = CommunicationOptions(rawValue: indexPath.row)
case .About:
let about = AboutOptions(rawValue: indexPath.row)
if about?.description == "Privacy" {
let privacyCon = PrivacyController()
self.navigationController?.pushViewController(privacyCon, animated: true)
}
else if about?.description == "Terms of Use" {
let termsController = TermsViewController()
self.navigationController?.pushViewController(termsController, animated: true)
}
}
}
}
Here is my transition to the Settings Controller (this controller has a tab bar)
#objc func handleSettings() {
let settingsController = ViewController()
//settingsController.delegate = self
settingsController.user = user
let navController = UINavigationController(rootViewController: settingsController)
navController.modalPresentationStyle = .fullScreen
present(navController, animated: true)
}
Hiding the tab bar doesn't work. This seemed to only happen after like iOS 13.5 What could be going on?
Just select the hide bottom bar on push in your view controller in st:

How to display a PopoverViewController from a custom Navigation Bar Right Button?

I created a custom Navigation Bar class as illustrated below, which I used across multiple ViewControllers:
import UIKit
import ChameleonFramework
class CustomUINavigationBar: UINavigationBar {
let navigationBarRightButtonView = UIView()
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
convenience init(rightNavBarButtonTitleForNormalState: String, rightNavBarButtonImageForNormalState: String, rightNavBarButtonImageForHighlightedState: String, rightNavBarButtonTarget: Any?, rightNavBarButtonSelector: Selector, isNavBarTranslucent: Bool, navBarBackgroundColourHexCode: String, navBarBackgroundColourAlphaValue: CGFloat, navBarStyle: UIBarStyle, preferLargeTitles: Bool, navBarDelegate: UINavigationBarDelegate, navBarItemsHexColourCode: String, normalStateNavBarLeftButtonImage: String, highlightedStateNavBarLeftButtonImage: String, navBarLeftButtonTarget: Any?, navBarLeftButtonSelector: Selector, labelTitleText: String, titleLabelFontHexColourCode: String, labelTitleFontSize: CGFloat, labelTitleFontType: String) {
self.init()
addNavBarRightButton(rightNavBarButtonTitleForNormalState: rightNavBarButtonTitleForNormalState, rightNavBarButtonImageForNormalState: rightNavBarButtonImageForNormalState, rightNavBarButtonImageForHighlightedState: rightNavBarButtonImageForHighlightedState, rightNavBarButtonTarget: rightNavBarButtonTarget, rightNavBarButtonSelector: rightNavBarButtonSelector)
addNavBarLeftButton(normalStateNavBarLeftButtonImage: normalStateNavBarLeftButtonImage, highlightedStateNavBarLeftButtonImage: highlightedStateNavBarLeftButtonImage, navBarLeftButtonTarget: navBarLeftButtonTarget, navBarLeftButtonSelector: navBarLeftButtonSelector)
setupNavigationBarEssentials(isNavBarTranslucent: isNavBarTranslucent, navBarBackgroundColourHexCode: navBarBackgroundColourHexCode, navBarBackgroundColourAlphaValue: navBarBackgroundColourAlphaValue, navBarStyle: navBarStyle, preferLargeTitles: preferLargeTitles, navBarDelegate: navBarDelegate, navBarItemsHexColourCode: navBarItemsHexColourCode)
addTitleLabel(labelTitleText: labelTitleText, titleLabelFontHexColourCode: titleLabelFontHexColourCode, labelTitleFontSize: labelTitleFontSize, labelTitleFontType: labelTitleFontType)
}
let customNavigationBarItem = UINavigationItem()
func addTitleLabel(labelTitleText titleText: String, titleLabelFontHexColourCode hexCode: String, labelTitleFontSize fontSize: CGFloat, labelTitleFontType fontType: String) {
let navBarTitle = UILabel(frame: CGRect(x: 0, y: 0, width: frame.width, height: 44))
navBarTitle.text = titleText
navBarTitle.textColor = UIColor(hexString: hexCode)
navBarTitle.textAlignment = .center
navBarTitle.font = UIFont(name: fontType, size: fontSize)
navBarTitle.numberOfLines = 0
navBarTitle.lineBreakMode = .byWordWrapping
customNavigationBarItem.titleView = navBarTitle
}
func addNavBarLeftButton(normalStateNavBarLeftButtonImage: String, highlightedStateNavBarLeftButtonImage: String, navBarLeftButtonTarget: Any?, navBarLeftButtonSelector: Selector) {
let navBarLeftButton: UIButton = {
let button = UIButton()
let normalStateNavBarLeftButtonImage = UIImage(named: normalStateNavBarLeftButtonImage)
let highlightedStateNavBarLeftButtonImage = UIImage(named: highlightedStateNavBarLeftButtonImage)
button.setImage(normalStateNavBarLeftButtonImage, for: .normal)
button.setImage(highlightedStateNavBarLeftButtonImage, for: .highlighted)
button.addTarget(navBarLeftButtonTarget, action: navBarLeftButtonSelector, for: .touchUpInside)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
let navBarLeftView: UIView = {
let view = UIView()
view.addSubview(navBarLeftButton)
NSLayoutConstraint.activate([
navBarLeftButton.topAnchor.constraint(equalTo: view.topAnchor),
navBarLeftButton.rightAnchor.constraint(equalTo: view.rightAnchor),
navBarLeftButton.bottomAnchor.constraint(equalTo: view.bottomAnchor),
navBarLeftButton.leftAnchor.constraint(equalTo: view.leftAnchor)
])
return view
}()
let navBarLeftButtonItem = UIBarButtonItem(customView: navBarLeftView)
customNavigationBarItem.leftBarButtonItem = navBarLeftButtonItem
}
func addNavBarRightButton(rightNavBarButtonTitleForNormalState: String, rightNavBarButtonImageForNormalState: String, rightNavBarButtonImageForHighlightedState: String, rightNavBarButtonTarget: Any?, rightNavBarButtonSelector: Selector) {
rightNavigationBarDropDownButton.setTitle(rightNavBarButtonTitleForNormalState, for: .normal)
rightNavigationBarDropDownButton.setImage(UIImage(named: rightNavBarButtonImageForNormalState), for: .normal)
rightNavigationBarDropDownButton.setTitleColor(.black, for: .normal)
rightNavigationBarDropDownButton.setTitleColor(.blue, for: .highlighted)
rightNavigationBarDropDownButton.addTarget(rightNavBarButtonTarget, action: rightNavBarButtonSelector, for: .touchUpInside)
rightNavigationBarDropDownButton.translatesAutoresizingMaskIntoConstraints = false
navigationBarRightButtonView.addSubview(rightNavigationBarDropDownButton)
NSLayoutConstraint.activate([
rightNavigationBarDropDownButton.topAnchor.constraint(equalTo: navigationBarRightButtonView.topAnchor),
rightNavigationBarDropDownButton.rightAnchor.constraint(equalTo: navigationBarRightButtonView.rightAnchor),
rightNavigationBarDropDownButton.leftAnchor.constraint(equalTo: navigationBarRightButtonView.leftAnchor),
rightNavigationBarDropDownButton.bottomAnchor.constraint(equalTo: navigationBarRightButtonView.bottomAnchor)
])
let navigationBarRightViewitem = UIBarButtonItem(customView: navigationBarRightButtonView)
customNavigationBarItem.rightBarButtonItem = navigationBarRightViewitem
}
func setupNavigationBarEssentials(isNavBarTranslucent: Bool, navBarBackgroundColourHexCode: String, navBarBackgroundColourAlphaValue: CGFloat, navBarStyle: UIBarStyle, preferLargeTitles: Bool, navBarDelegate: UINavigationBarDelegate, navBarItemsHexColourCode: String) {
items = [customNavigationBarItem]
isTranslucent = isNavBarTranslucent
barTintColor = UIColor(hexString: navBarBackgroundColourHexCode, withAlpha: navBarBackgroundColourAlphaValue)
barStyle = navBarStyle
prefersLargeTitles = preferLargeTitles
delegate = navBarDelegate
tintColor = UIColor(hexString: navBarItemsHexColourCode)
translatesAutoresizingMaskIntoConstraints = false
}
}
I then created an instance from the above custom Navigation Bar class into the viewController where I would like the custom Navigation bar to show. Then I tried to present the PopoverViewController whenever the user taps on the NavBarRightButtonItem, however, nothing is showing up, could please someone help me figuring out where did I go wrong, thanks a lot?
import UIKit
class BlueBookUniversalBeamsVC: UIViewController, UINavigationBarDelegate, UIPopoverPresentationControllerDelegate {
lazy var navigationBar = CustomUINavigationBar(rightNavBarButtonTitleForNormalState: "Sort By:", rightNavBarButtonImageForNormalState: "pullDownButton", rightNavBarButtonImageForHighlightedState: "pullUpButton", rightNavBarButtonTarget: self, rightNavBarButtonSelector: #selector(navigationBarRightButtonPressed(sender:)), isNavBarTranslucent: false, navBarBackgroundColourHexCode: "#FFFFFF", navBarBackgroundColourAlphaValue: 1.0, navBarStyle: .black, preferLargeTitles: false, navBarDelegate: self, navBarItemsHexColourCode: "#FF4F40", normalStateNavBarLeftButtonImage: "normalStateBackButton", highlightedStateNavBarLeftButtonImage: "highlightedStateBackButton", navBarLeftButtonTarget: self, navBarLeftButtonSelector: #selector(navigationBarLeftButtonPressed(sender:)), labelTitleText: "Universal Beams (UB)", titleLabelFontHexColourCode: "#000000", labelTitleFontSize: 16, labelTitleFontType: "AppleSDGothicNeo-Light")
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(navigationBar)
}
}
override func viewDidLayoutSubviews() {
setupConstraints()
}
#objc func navigationBarLeftButtonPressed(sender : UIButton) {
let viewControllerToGoTo = BlueBookTabController()
present(viewControllerToGoTo, animated: true, completion: nil)
}
#objc func navigationBarRightButtonPressed(sender : UIButton) {
let button = sender as? UIButton
let buttonFrame = button?.frame ?? CGRect.zero
let popoverContentController = self.storyboard?.instantiateViewController(withIdentifier: "PopoverViewController") as? PopoverViewController
popoverContentController?.modalPresentationStyle = .popover
if let popoverPresentationController = popoverContentController?.popoverPresentationController {
popoverPresentationController.permittedArrowDirections = .up
popoverPresentationController.sourceView = self.view
popoverPresentationController.sourceRect = buttonFrame
popoverPresentationController.delegate = self
if let popoverController = popoverContentController {
present(popoverController, animated: true, completion: nil)
}
}
}
func adaptivePresentationStyle(for controller: UIPresentationController) -> UIModalPresentationStyle {
return .none
}
func popoverPresentationControllerDidDismissPopover(_ popoverPresentationController: UIPopoverPresentationController) {
}
func popoverPresentationControllerShouldDismissPopover(_ popoverPresentationController: UIPopoverPresentationController) -> Bool {
return true
}
func position(for bar: UIBarPositioning) -> UIBarPosition {
return UIBarPosition.topAttached
}
func setupConstraints() {
NSLayoutConstraint.activate([
navigationBar.leftAnchor.constraint(equalTo: view.leftAnchor),
navigationBar.rightAnchor.constraint(equalTo: view.rightAnchor),
navigationBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
])
}
}
I managed to sort out my problem using the below code, what confused me at the beginning is that I am using a Standalone NavigationBar rather than a NavigationBar Controller:
#objc func navigationBarRightButtonPressed(sender : UIButton) {
let storyboard : UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
let popOverViewController = storyboard.instantiateViewController(withIdentifier: "PopoverViewController")
popOverViewController.modalPresentationStyle = .popover
let popover = popOverViewController.popoverPresentationController!
popover.delegate = self
popover.permittedArrowDirections = .up
// The sourceView in the below code line represents the view containing the anchor rectangle for the popover:
popover.sourceView = navigationBar.navigationBarRightButtonView
// The sourceRect in the below code line represents The rectangle in the specified view in which to anchor the popover:
popover.sourceRect = navigationBar.navigationBarRightButtonView.bounds
present(popOverViewController, animated: true, completion:nil)
}

Call function from UICollectionViewCell to use in UICollectionView

I have a UICollectionViewCell that creates a bunch of text fields and a function (handleNewJob) that looks at all the textfields created in the cell and writes them to firebase.
However, what I want is for a button that I have created in my UICollectionView to call the function (handleNewJob) from the UICollectionViewCell.
Is this possible? I have tried having the function inside the UICollectionView but I can't seem to reference all the textfields.text?
Here is my function inside UICollectionViewCell (I haven't included all the textfield generation as it's quite long):
// HANDLE NEW JOB
func handleNewJob(){
let newJobBrand = jobBrand.text!
let newJobName = jobName.text!
let newDirectorName = directorName.text!
let newAgencyName = agencyName.text!
let newProdCoName = prodCoName.text!
// WHERE TO PUT IN DATABASE
let reference = Database.database().reference().child("jobInfo")
let childRef = reference.childByAutoId()
// REFERENCING DICTIONARY
let jobBrandValue = ["jobBrand": newJobBrand]
let jobNameValue = ["jobName": newJobName]
let jobDirectorValue = ["directorName": newDirectorName]
let jobAgencyNameValue = ["agencyName": newAgencyName]
let jobProdCoValue = ["prodCoName": newProdCoName]
// WRITE TO DATABASE
childRef.updateChildValues(jobBrandValue)
childRef.updateChildValues(jobNameValue)
childRef.updateChildValues(jobDirectorValue)
childRef.updateChildValues(jobAgencyNameValue)
childRef.updateChildValues(jobProdCoValue)
}
Here is my code for the UICollectionView - I want to call the function under the handleNext button:
import UIKit
import Firebase
class page_newJobSwipingController : UICollectionViewController, UICollectionViewDelegateFlowLayout, UIImagePickerControllerDelegate, UINavigationControllerDelegate {
// VARIABLES
var ref:DatabaseReference?
// BOTTOM BUTTONS
private let previousButton: UIButton = {
let button = UIButton(type: .system)
button.setTitle("Previous", for: .normal)
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 14)
button.setTitleColor(.gray, for: .normal)
button.addTarget(self, action: #selector(handlePrev), for: .touchUpInside)
button.translatesAutoresizingMaskIntoConstraints = false
return button
}()
private let nextButton: UIButton = {
let button = UIButton(type: .system)
button.setTitle("Next", for: .normal)
button.titleLabel?.font = UIFont.boldSystemFont(ofSize: 14)
let pinkColour = UIColor(red: 232/255, green: 68/266, blue: 133/255, alpha: 1)
button.setTitleColor(.mainPink, for: .normal)
button.translatesAutoresizingMaskIntoConstraints = false
button.addTarget(self, action: #selector(handleNext), for: .touchUpInside)
return button
}()
// SET UP NEXT AND PREVIOUS BUTTONS TO HAVE A FUNCTION
#IBAction func handlePrev(sender : UIButton) {
let prevIndex = max(pageControl.currentPage - 1, 0)
pageControl.currentPage = prevIndex
let indexPath = IndexPath(item: prevIndex, section: 0)
collectionView?.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
}
#IBAction func handleNext(sender : UIButton) {
let nextIndex = pageControl.currentPage + 1
pageControl.currentPage = nextIndex
if nextIndex == 1 {
print ("move to page 2")
} else {
print ("send alert message")
newJobCellGeneral.handleNewJob()
storyboardAlert()
}
let indexPath = IndexPath(item: 1, section: 0)
collectionView?.scrollToItem(at: indexPath, at: .centeredHorizontally, animated: true)
}
// HANDLE UPLOAD STORYBOARD OPTIONS
#IBAction func storyboardAlert() {
let imagePickerController = UIImagePickerController()
imagePickerController.delegate = self
// ACTION SHEET FOR ADDING NEW ATTACHMENT
let alert = UIAlertController(title: "Job Created", message: "Do you want to upload storyboard cells now?", preferredStyle: .actionSheet)
alert.addAction(UIAlertAction(title: "Now", style: .default, handler: { (action:UIAlertAction) in
let storyboardUpload = page_newJobStoryboardUpload()
self.show(storyboardUpload, sender: self)
}))
alert.addAction(UIAlertAction(title: "Later", style: .default, handler: { (action:UIAlertAction) in
let jobList = page_jobList()
self.show(jobList, sender: self)
}))
alert.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
self.present(alert, animated: true, completion: nil)
}
// PAGE CONTROL
private let pageControl: UIPageControl = {
let pc = UIPageControl()
pc.numberOfPages = 2
pc.currentPageIndicatorTintColor = .mainPink
pc.pageIndicatorTintColor = UIColor(red: 249/255, green: 207/266, blue: 224/255, alpha: 1)
return pc
}()
override func scrollViewWillEndDragging(_ scrollView: UIScrollView, withVelocity velocity: CGPoint, targetContentOffset: UnsafeMutablePointer<CGPoint>) {
let x = targetContentOffset.pointee.x
pageControl.currentPage = Int(x / view.frame.width)
}
// CONSTRAINTS OF BOTTOM CONTROLS
fileprivate func setupBottomControls(){
let bottomControlsStackView = UIStackView(arrangedSubviews: [previousButton, pageControl, nextButton])
bottomControlsStackView.translatesAutoresizingMaskIntoConstraints = false
bottomControlsStackView.distribution = .fillEqually
view.addSubview(bottomControlsStackView)
NSLayoutConstraint.activate([
bottomControlsStackView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor),
bottomControlsStackView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
bottomControlsStackView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
bottomControlsStackView.heightAnchor.constraint(equalToConstant: 50)
])
}
// SUPER VIEW DID LOAD
override func viewDidLoad() {
super.viewDidLoad()
collectionView?.backgroundColor = .white
collectionView?.register(newJobCellGeneral.self, forCellWithReuseIdentifier: "newJobCellGeneral")
collectionView?.register(newJobCellTechnical.self, forCellWithReuseIdentifier: "newJobCellTechnical")
collectionView?.isPagingEnabled = true
setupBottomControls()
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 2
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if indexPath.item == 0 {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "newJobCellGeneral", for: indexPath) as! newJobCellGeneral
navigationItem.title = "General Info"
return cell
} else {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "newJobCellTechnical", for: indexPath) as! newJobCellTechnical
navigationItem.title = "Technical Specs"
return cell
}
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
return CGSize(width: view.frame.width, height: view.frame.height)
}
}
The flow is inversed but yes, the easiest way is via notifications
in you collection view
Put this in your collectionView button pressed method
NotificationCenter.default.post(name: Notification.Name("handleNewJob"), object: nil)
Add observer in you collection view cell (init or awakeFromNib depends)
NotificationCenter.default.addObserver(self, selector: #selector(handleNewJob, name: NSNotification.Name(rawValue: "handleNewJob"), object: nil)
Notification Center is one solution, but the easier way is to be able to call a function on your collection view controller directly from the cell.
To do that, you need to be able to reference your parent view controller. so add this UIView extension:
Create a swift file named UIView.swift and paste this:
import UIKit
extension UIView {
var parentViewController: UIViewController? {
var parentResponder: UIResponder? = self
while parentResponder != nil {
parentResponder = parentResponder!.next
if parentResponder is UIViewController {
return parentResponder as! UIViewController!
}
}
return nil
}
}
then from your cell, for example when a button is clicked:
#IBAction func someButtonAction(sender : UIButton) {
let parent = self.parentViewController as! page_newJobSwipingController
parent.whateverFunction()
}

fetch data from Firebase using autoID - Xcode

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

how to use ViewWithTag in Swift?

I'm new to Swift, however I work in Objective-C before. I'm having issue in checkin if the cell is being reused in UITableView or not.
let cell = tableView.dequeueReusableCellWithIdentifier(strCellId, forIndexPath:indexPath) as! MGSwipeTableCell
cell.backgroundColor = UIColor.clearColor()
let SMSObj = self.arraySMSContent[indexPath.row] as! SMSModel
let lblMessage = UILabel(frame: CGRectMake(15, 10, Constants.SCREEN_WIDTH/1.4, Constants.SCREEN_HEIGHT/11))
lblMessage.text = SMSObj.strSMSContent
lblMessage.textAlignment = NSTextAlignment.Left
lblMessage.numberOfLines = 2
lblMessage.textColor = UIColor.whiteColor()
cell.contentView.addSubview(lblMessage)
I have used MGSwipebleCell. While scrolling lblMessage overlaps. Even we can not check if cell is nil or not. So how to use viewWithTag in this situation? Thnaks
Rather than using viewWithTag, you can register a custom class with the cell reuse identifier. Then you can access the label using a property of that subclass:
override func viewDidLoad() {
super.viewDidLoad()
tableView.registerClass(CustomCell.self, forCellReuseIdentifier: "CustomCell")
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("CustomCell", forIndexPath: indexPath) as! CustomCell
cell.smsLabel.text = ...
return cell
}
Where:
class CustomCell: MGSwipeTableCell {
var smsLabel: UILabel = {
let label = UILabel()
label.translatesAutoresizingMaskIntoConstraints = false
label.textAlignment = .Left
label.numberOfLines = 2
label.textColor = .whiteColor()
return label
}()
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
backgroundColor = .blueColor()
contentView.addSubview(smsLabel)
NSLayoutConstraint.activateConstraints([
smsLabel.topAnchor.constraintEqualToAnchor(contentView.topAnchor, constant: 5),
smsLabel.bottomAnchor.constraintEqualToAnchor(contentView.bottomAnchor, constant: -5),
smsLabel.leadingAnchor.constraintEqualToAnchor(contentView.leadingAnchor, constant: 5),
smsLabel.trailingAnchor.constraintEqualToAnchor(contentView.trailingAnchor, constant: -5)
])
leftButtons = [MGSwipeButton(title: "Red", backgroundColor: .redColor())]
leftSwipeSettings.transition = .Rotate3D;
rightButtons = [MGSwipeButton(title: "Green", backgroundColor: .greenColor())]
rightSwipeSettings.transition = .Rotate3D;
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
fatalError("not needed")
}
}
There're many ways to solve your problem. Please try:
if let lblMessage = cell.contentView.viewWithTag(9999) as? UILabel { //Tag
lblMessage.text = SMSObj.strSMSContent
}else{
let lblMessage = UILabel(frame: CGRectMake(15, 10, Constants.SCREEN_WIDTH/1.4, Constants.SCREEN_HEIGHT/11))
lblMessage.text = SMSObj.strSMSContent
lblMessage.textAlignment = NSTextAlignment.Left
lblMessage.numberOfLines = 2
lblMessage.textColor = UIColor.whiteColor()
lblMessage.tag = 9999 //Tag
cell.contentView.addSubview(lblMessage)
}