Call function from UICollectionViewCell to use in UICollectionView - swift

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()
}

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 add swipe gesture or swipe function between two overlap container view using segmented control, like instagram profile?

I am new to iOS and trying to build an app to learn more. I'm stuck at the last stage of my application. I want to be able to swipe between two container views using segmented control. I want to add two overlapping container views (container views with an embed segue with child controller) of the same size on half screen in single controller like instagram profile. I want to add a tableview to both child controllers. When I run the app the data of the first child view should be seen but when I swipe left, the second child controller should be seen with same size and in the same position. I want this to be like an instagram profile.
Currently, when I swipe left the second child controller opens in full screen and hides everything else on that screen. I have tried various tutorials, but to no avail.
Can you help me to do this?
Thank You!
This is my view controller's code
// CODE //
{
//
// ViewController.swift
// BeautyParlor
//
// Created by Mohammad Affan Siddiqui on 20/11/2019.
// Copyright © 2019 Mohammad Affan Siddiqui. All rights reserved.
//
import UIKit
//import PinterestLayout
class ViewController: UIViewController {
#IBOutlet weak var SegmentedControl: UISegmentedControl!
#IBOutlet weak var thirdView: UIView!
#IBOutlet weak var collectionViewOutletPortfolio: UICollectionView!
#IBOutlet weak var collectionViewOutletAbout: UICollectionView!
#IBOutlet weak var secondView: UIView!
#IBOutlet weak var firstView: UIView!
#IBOutlet weak var collectionViewOutletStatic: UICollectionView!
// FOR STATIC DATA
var arrimgbackground = [UIImage]()
var arrimglogo = [UIImage]()
var arrimglocation = [UIImage]()
var arrimginsta = [UIImage]()
var arrlblname = ["ABC Saloon"]
var arrlblrating = ["Rating 4.5/5"]
var arrlbllocation = ["ABC,Street,karachi"]
var arrlblinsta = ["qqq"]
var arrlblservicename = ["We are serving you"]
var arrlblrs = ["Rs:200"]
// FOR ABOUT DATA
var arrlbldescription = ["Before you can begin to determine what the will grow. The whole process is an organic one—a natural progression from a seed to a full-blown "]
// FOR PORTFOLIO DATA
var arrimgportfolio = [UIImage]()
override func viewDidLoad() {
super.viewDidLoad()
//
//
//
//
// setupSegmentedContrl()
setupHorizontalBar()
// let swipright = UISwipeGestureRecognizer(target: self, action: #selector(self.swipGesture))
// swipright.direction = UISwipeGestureRecognizer.Direction.right
// self.thirdView?.addGestureRecognizer(swipright)
// let rightSwipe = UISwipeGestureRecognizer(target: SegmentCotroller, action: Selector("swiped:"))
// rightSwipe.direction = .Right
// self.SegmentCotroller.addGestureRecognizer(rightSwipe)
//
let rightSwipe = UISwipeGestureRecognizer(target: self, action: Selector(("swiped:")))
rightSwipe.direction = .right
self.secondView?.addGestureRecognizer(rightSwipe)
// let swipright = UISwipeGestureRecognizer(target: self, action: #selector(self.swipGesture))
// swipright.direction = UISwipeGestureRecognizer.Direction.right
// self.secondView?.addGestureRecognizer(swipright)
//
//
// let layout = PinterestLayout()
// collectionViewOutletPortfolio.collectionViewLayout = layout
//
// layout.delegate = self
// layout.cellPadding = 5
// layout.numberOfColumns = 2
//
//
//
// if let layout = collectionViewOutletPortfolio?.collectionViewLayout as? PinterestLayout {
// layout.delegate = self as! PinterestLayoutDelegate
// }
//
thirdView?.isHidden = true
arrimgbackground = [#imageLiteral(resourceName: "d.png")]
arrimglogo = [#imageLiteral(resourceName: "roundimage.png")]
arrimglocation = [#imageLiteral(resourceName: "location.jpeg")]
arrimginsta = [#imageLiteral(resourceName: "insta.png")]
arrimgportfolio = [#imageLiteral(resourceName: "c.png"), #imageLiteral(resourceName: "d.png"), #imageLiteral(resourceName: "down.png"), #imageLiteral(resourceName: "down.png"), #imageLiteral(resourceName: "c.png"), #imageLiteral(resourceName: "c.png"), #imageLiteral(resourceName: "c.png"), #imageLiteral(resourceName: "c.png"), #imageLiteral(resourceName: "d.png"), #imageLiteral(resourceName: "d.png"), #imageLiteral(resourceName: "d.png"), #imageLiteral(resourceName: "d.png"), #imageLiteral(resourceName: "down.png"), #imageLiteral(resourceName: "down.png"), #imageLiteral(resourceName: "down.png")]
// setupSegmentedControl().topAnchor.constraintEqualToAnchor(topLayoutGuide)
}
private func setupHorizontalBar(){
}
private func setupSegmentedControl(){
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
// SegmentedControl
}
// #objc func swipGesture(sender: UISwipeGestureRecognizer?){
// // #objc func swipeAction (swipe: UISwipeGestureRecognizer) {
// if let swipGesture = sender{
// switch swipGesture.direction {
// case UISwipeGestureRecognizer.Direction.right:
// print ("i just swip right")
// let redVC = UIViewController()
// redVC.view.backgroundColor = UIColor.red
// //self.navigationController?.popViewController(animated: true)
// //performSegue(withIdentifier: "goRight", sender: self)
// default:
// break
// }
// }
//
// }
// thirdView = uivi(frame: thirdView)
//self.collectionViewOutletPortfolio? = UICollectionView()
// ViewController.swipGesture(index: index)(index: index)
// case UISwipeGestureRecognizer.Direction.left:
// print ("i just swiped left")
////
// // arrlbl = UICollectionView()
// default:
// break
//
// }
// }
// FOR SWIPPING CHECK WORKING OR NOT
// #IBAction func swipBetweenViews(_ sender: UISwipeGestureRecognizer) {
// print ("HelowSwipped")
//
//}
#IBAction func switchViews(_ sender: UISegmentedControl) {
if sender.selectedSegmentIndex == 0{
firstView.isHidden = false
secondView?.isHidden = false
thirdView?.isHidden = true
// firstView.alpha = 0
// secondView.alpha = 1
// thirdView.alpha = 0
//
}else{
firstView.isHidden = false
secondView?.isHidden = true
thirdView?.isHidden = false
// firstView.alpha = 0
// secondView.alpha = 0
// thirdView.alpha = 1
}
}
}
extension ViewController: UICollectionViewDataSource , UICollectionViewDelegate{
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
if (collectionView == collectionViewOutletStatic){
let cell = collectionViewOutletStatic.dequeueReusableCell(withReuseIdentifier: "cellone", for: indexPath)as! CollectionViewCellStatic
cell.imgbackground.image = arrimgbackground[indexPath.row]
cell.imglogo.image = arrimglogo[indexPath.row]
cell.imglocation.image = arrimglocation[indexPath.row]
cell.imginsta.image = arrimginsta[indexPath.row]
cell.lblname.text = arrlblname[indexPath.row]
cell.lblrating.text = arrlblrating[indexPath.row]
cell.lbllocation.text = arrlbllocation[indexPath.row]
cell.lblinstaname.text = arrlblinsta[indexPath.row]
cell.lblservicename.text = arrlblservicename[indexPath.row]
cell.lblrs.text = arrlblrs[indexPath.row]
return cell
}else{
if (collectionView == collectionViewOutletAbout){
let cello = collectionViewOutletAbout.dequeueReusableCell(withReuseIdentifier: "celltwo", for: indexPath)as! CollectionViewCellAbout
cello.lbldescription.text = arrlbldescription[indexPath.row]
return cello
}else{
let cellt = collectionViewOutletPortfolio?.dequeueReusableCell(withReuseIdentifier: "cellthree", for: indexPath)as! CollectionViewCellPortfolio
cellt.imgPortfolio.image = arrimgportfolio[indexPath.row]
return cellt
// THIS CODE FOR 3 COLUMNS OF IMAGES COLLECTION LIKE PORFOLIO
// _ = UIScreen.main.bounds.width/2-2
// let layout = UICollectionViewFlowLayout()
//
// collectionViewOutletPortfolio?.collectionViewLayout = layout
//
// layout.sectionInset = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0)
// // layout.itemSize = CGSize(width: itemSize, height: itemSize)
////
//// layout.minimumInteritemSpacing = 0
//// layout.minimumLineSpacing = 0
}
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
// let x = CGFloat(indexPath.item) * frame.width
}
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
if (collectionView == collectionViewOutletStatic){
return arrimgbackground.count
}else{
if (collectionView == collectionViewOutletAbout){
return arrlbldescription.count
}else{
return arrimgportfolio.count
}
}
}
}
extension ViewController: UICollectionViewDelegateFlowLayout{
// THIS FOR 3 COLUMNS OF IMAGES IN CLLECTION VIEW CELL
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
let collectionwidth = collectionView.bounds.width
return CGSize(width: collectionwidth/3, height: collectionwidth/3)
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumInteritemSpacingForSectionAt section: Int) -> CGFloat {
return 0
}
}
//extension ViewController: PinterestLayoutDelegate{
// func collectionView(_ collectionView: UICollectionView, heightForItemAtIndexPath indexPath: IndexPath) -> CGSize {
// //return UIImage(named: row[indexPath.item].imageename)?.size
//
// }
//}
//
//extension ViewController: PinterestLayoutDelegate{
// func collectionView(_ collectionView: UICollectionView, heightForItemAtIndexPath indexPath: IndexPath) -> CGFloat {
// return 100
// }
//
//
//
// func collectionView(
// _ collectionView: UICollectionView,
// heightForPhotoAtIndexPath indexPath:IndexPath) -> CGFloat {
// return arrimgportfolio[indexPath.row]
// //return arrimgportfolio[indexPath.item].image.size.height
// }
This is the simple example that you want. This is design for full screen. I think you can get an idea and customize this for your requirement
class ContainerController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
if #available(iOS 13.0, *) {
view.backgroundColor = .systemBackground
} else {
view.backgroundColor = .white
}
navigationItem.titleView = sgControll
updateView()
sgControll.addTarget(self, action: #selector(segmentControllValueChanged (_:)), for:.valueChanged)
}
//MARK: Components
let sgControll:UISegmentedControl = {
let sg = UISegmentedControl()
sg.insertSegment(withTitle: "first Child", at: 0, animated: true)
sg.insertSegment(withTitle: "Second Child", at: 1, animated: true)
sg.selectedSegmentIndex = 0
return sg
}()
private lazy var secondView : SecondChildViewController = {
let vc = SecondChildViewController()
self.add(asChildViewController: vc)
return vc
}()
private lazy var firstView:FirstChildViewController = {
let vc = FirstChildViewwController()
self.add(asChildViewController: vc)
return vc
}()
}
//MARK: Functions
extension ContainerController {
#objc func segmentControllValueChanged(_ sender : UISegmentedControl){
print(sender.selectedSegmentIndex)
updateView()
}
private func add(asChildViewController viewController: UIViewController){
addChild(viewController)
view.addSubview(viewController.view)
viewController.view.translatesAutoresizingMaskIntoConstraints = false
viewController.view.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
viewController.view.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
viewController.view.trailingAnchor.constraint(equalTo: view.trailingAnchor).isActive = true
viewController.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true
viewController.didMove(toParent: self)
}
private func remove(asChildViewController viewController: UIViewController) {
viewController.willMove(toParent: nil)
viewController.view.removeFromSuperview()
viewController.removeFromParent()
}
private func updateView() {
if sgControll.selectedSegmentIndex == 0 {
remove(asChildViewController: firstView)
add(asChildViewController: secondView)
} else {
remove(asChildViewController: seconView)
add(asChildViewController: firstView)
}
}
}

Long press gesture action sheet delete cell

I trying to code long press gesture on the cell in collection view but I haven't found about similar... I suppose I do to code something in the 'didSelectItemAt'.
Now works only if I tap in the first cell...
And then I have found on web to different solution based on swift 3.
Every one help me please? Thank you so much!
The image show when tap long on the first cell the action sheet. But don't work when I tap to other cell...
import UIKit
class RecipeCollViewController: UICollectionViewController, UITextFieldDelegate
{
struct Storyboard
{
static let leftAndRightPaddings: CGFloat = 2.0
static let numberOfItemsPerRow: CGFloat = 2.0
}
override func viewDidLoad() {
super.viewDidLoad()
RecipeDataManager.shared.recipeController = self
title = loc("TITLE_RECIPECOLL")
navigationController?.navigationBar.prefersLargeTitles = true
let collectionViewWidth = collectionView?.frame.width
let itemWidth = (collectionViewWidth! - Storyboard.leftAndRightPaddings) / Storyboard.numberOfItemsPerRow
let layout = collectionViewLayout as! UICollectionViewFlowLayout
layout.itemSize = CGSize(width: itemWidth, height: 250)
}
override func numberOfSections(in collectionView: UICollectionView) -> Int
{
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int
{
return RecipeDataManager.shared.recipes.count
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
{
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "RecipeCell", for: indexPath) as! RecipeViewCell
let recipe = RecipeDataManager.shared.recipes[indexPath.item]
cell.labelNameRecipe.text = recipe.titleRecipe
cell.imageViewRecipe.image = recipe.imageRecipe
cell.labelPrepareTime.text = String(recipe.recipeTimeInt)
cell.labelPeopleFor.text = recipe.peopleRecipe
return cell
}
override func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath)
{
}
// MARK: - NAVIGAZIONE
// Metodo che scatta quando l'utente tocca una delle celle della collectionView e apre il dettaglio
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
{
if segue.identifier == "RecipeDetail"
{
if let indexPath = self.collectionView!.indexPathsForSelectedItems?.first
{
let recipeDetailVC = segue.destination as! DetailRecipeViewController
recipeDetailVC.recipe = RecipeDataManager.shared.recipes[indexPath.item]
}
}
}
// MARK: - UILongPressGestureRecognizer function for the cell recipe
#IBAction func popUpActionCell(longPressGesture : UILongPressGestureRecognizer)
{
let alertActionCell = UIAlertController(title: "Action Recipe Cell", message: "Choose an action for the selected recipe", preferredStyle: .actionSheet)
// Configure Remove Item Action
let deleteAction = UIAlertAction(title: "Delete", style: .destructive, handler: { action in
// Delete selected Cell
let deleteRecipe: [RecipeDataManager] = []
if let indexPath = self.collectionView?.indexPathsForSelectedItems?.first
{
RecipeDataManager.shared.recipes.remove(at: indexPath.item)
RecipeDataManager.shared.salva()
self.collectionView?.deleteItems(at: [indexPath])
}
print("Cell Removed")
})
// Configure Cancel Action Sheet
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: { acion in
print("Cancel actionsheet")
})
alertActionCell.addAction(deleteAction)
alertActionCell.addAction(cancelAction)
self.present(alertActionCell, animated: true, completion: nil)
self.collectionView!.reloadData()
}
}
With my pleausure, I have found the finally solution at my problem.
Post the code for other new developer needs help!
// MARK: - Long Press Gesture Action Sheet
#IBAction func popUpActionCell(longPressGesture : UILongPressGestureRecognizer)
{
// Delete selected Cell
let point = longPressGesture.location(in: self.collectionView)
let indexPath = self.collectionView?.indexPathForItem(at: point)
// let cell = self.collectionView?.cellForItem(at: indexPath!)
if indexPath != nil
{
let alertActionCell = UIAlertController(title: "Action Recipe Cell", message: "Choose an action for the selected recipe", preferredStyle: .actionSheet)
// Configure Remove Item Action
let deleteAction = UIAlertAction(title: "Delete", style: .destructive, handler: { action in
RecipeDataManager.shared.recipes.remove(at: indexPath!.row)
print("Cell Removed")
self.collectionView!.reloadData()
})
// Configure Cancel Action Sheet
let cancelAction = UIAlertAction(title: "Cancel", style: .cancel, handler: { acion in
print("Cancel actionsheet")
})
alertActionCell.addAction(deleteAction)
alertActionCell.addAction(cancelAction)
self.present(alertActionCell, animated: true, completion: nil)
}
}

UIpageViewController And Timer

i have a UIPageViewController in one of My UICollectionViewCell at the top of my screen(height = frame.height/3) it contains a number of images
and it is working good but i need it to be scrolled to the next image automattically every 3 seconds what should i do?
import UIKit
class PageViewController: UIPageViewController , UIPageViewControllerDataSource{
var scrollingTimer = Timer()
let imageNames = ["Apple_Watch_Main" , "Pic2" , "Pic3"]
override func viewDidLoad() {
super.viewDidLoad()
dataSource = self
let frameViewController = FrameViewController()
frameViewController.imageName = imageNames.first
let viewControllers = [frameViewController]
setViewControllers(viewControllers, direction: .forward, animated: true, completion: nil)
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
let currentImageName = (viewController as! FrameViewController).imageName
let currentIndex = imageNames.index(of: currentImageName!)
if currentIndex! > 0 {
let frameViewController = FrameViewController()
frameViewController.imageName = imageNames[currentIndex! - 1]
return frameViewController
}
return nil
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
let currentImageName = (viewController as! FrameViewController).imageName
let currentIndex = imageNames.index(of: currentImageName!)
if currentIndex! < imageNames.count - 1 {
let frameViewController = FrameViewController()
frameViewController.imageName = imageNames[currentIndex! + 1]
return frameViewController
}
return nil
}
}
and i added to my cell here
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
switch indexPath.item {
case 0 :
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as!ImageCell
let pagecontroller = PageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal, options: nil)
self.addChildViewController(pagecontroller)
cell.addSubview(pagecontroller.view)
pagecontroller.view.frame = CGRect(x: 0, y: 0, width: view.frame.width, height: view.frame.height/3)
return cell
case 1 :
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "filterandorganize", for: indexPath) as! FilterAndOrganize
return cell
case 2 :
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Offers", for: indexPath) as! Offers
return cell
case 3 :
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "OfferedProducts", for: indexPath) as! OfferedProducts
cell.firstViewController = self
return cell
default:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "Offers", for: indexPath) as! Offers
return cell
}
}
in case 0
I searched a lot and i found some questions like this but without any complete and correct answer
HERE IS THE ANSWER I FOUND but it still have one bug and that is when the user swipes it self the autoscroll is not perfect and maybe jump of one pic to another
class PageViewController: UIPageViewController , UIPageViewControllerDataSource{
var index = 0
let imageNames = ["Apple_Watch_Main" , "Pic2" , "Pic3"]
override func viewDidLoad() {
super.viewDidLoad()
dataSource = self
let frameViewController = FrameViewController()
frameViewController.imageName = imageNames[index]
index += 1
let viewControllers = [frameViewController]
setViewControllers(viewControllers, direction: .forward, animated: true, completion: nil)
Timer.scheduledTimer(timeInterval: 6.0 ,
target: self,
selector: #selector(myFunc(_:)),
userInfo: index,
repeats: true)
}
//FIXME: needs some fixes
func myFunc(_ timer: Timer) {
if index == imageNames.count {
index = 0
}
else {
self.changePIC(index)
index += 1
}
}
func changePIC(_ i: Int) {
let frameViewController = FrameViewController()
frameViewController.imageName = imageNames[i]
let viewControllers = [frameViewController]
setViewControllers(viewControllers, direction: .forward, animated: true, completion: nil)
}
First crate a Timer with timeInterval and option repeats seat to true.
Example:
Timer.scheduledTimer(timeInterval: 3, target: self, selector: #selector(scrollToNextItem), userInfo: nil, repeats: true)
Now you have Timer that will trigger scrollToNextItem method every 3 seconds.
Now read about setViewControllers(_:direction:animated:completion:) to know how to set view controllers to be displayed.
Than implement scrollToNextItem method with required logic.

Swift - UIButton in UICollectionViewCell not clickable

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)