IOS UISegmentedControl doesn't not display in ios 10 - ios

I'm a beginner in IOS. I'm developping a Swift app and I am using a UISegmentedControl. It displays well in ios 11, but when I run my app on a IOS 10 device, the segmented control is not showing. Does anyone know why ?
Is the segmented control only available in IOS 11 ?
Here are the screenshots of my app (sorry I can't post images yet) :
IOS 11
IOS10
Here is my SegmentedViewController.swift :
import UIKit
import MMDrawerController
class SegmentedViewController: UIViewController {
#IBOutlet weak var viewContainer: UIView!
var segmentedController: UISegmentedControl!
var floorRequest:Int = 0
var segmentedControlIndex:Int = 0
lazy var travelViewController: TravelViewController = {
var viewController = self.initTravelViewController()
return viewController
}()
lazy var nearbyViewController: NearbyTableViewController = {
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
var viewController = storyboard.instantiateViewController(withIdentifier: "NearbyTableViewController") as! NearbyTableViewController
self.addViewControllerAsChildViewController(childViewController: viewController)
return viewController
}()
var views: [UIView]!
let appDelegate:AppDelegate = UIApplication.shared.delegate as! AppDelegate
func initTravelViewController() -> TravelViewController {
let storyboard = UIStoryboard(name: "Main", bundle: Bundle.main)
let viewController = storyboard.instantiateViewController(withIdentifier: "TravelViewController") as! TravelViewController
viewController.floorRequest = floorRequest
self.addViewControllerAsChildViewController(childViewController: viewController)
return viewController
}
override func viewDidLoad() {
super.viewDidLoad()
segmentedController = UISegmentedControl()
navigationItem.titleView = segmentedController
self.title = "TAB_BAR_MAP".localized()
}
override func viewWillAppear(_ animated: Bool) {
self.tabBarController?.navigationItem.title = "MENU_SECTION_TRAVEL".localized().uppercased()
// Navigation Bar
self.navigationController?.navigationBar.titleTextAttributes = [NSForegroundColorAttributeName : UIColor.white, NSFontAttributeName: UIFont(name: "Lato-Bold", size: 18)!]
self.navigationController?.navigationBar.tintColor = .white
self.navigationController?.navigationBar.barTintColor = appDelegate.colorAqaDark
self.navigationController?.navigationBar.isTranslucent = false
self.navigationItem.backBarButtonItem = UIBarButtonItem(title: "", style: .plain, target: nil, action: nil)
if (self.navigationController?.viewControllers.count)! < 2 {
let buttonLeft: UIButton = appDelegate.aqaBarButton(image: #imageLiteral(resourceName: "IconWhiteMenu"))
buttonLeft.addTarget(self, action: #selector(toggleMenu), for: .touchUpInside)
buttonLeft.frame = CGRect.init(x: 0, y: 0, width: 25, height: 25)
let buttonMenu = UIBarButtonItem(customView: buttonLeft)
self.navigationItem.setLeftBarButton(buttonMenu, animated: false);
}
setupView()
super.viewWillAppear(animated)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func toggleMenu() {
appDelegate.mainContainer!.toggle(MMDrawerSide.left, animated: true, completion: nil)
}
private func setupView(){
setupSegmentedControl()
updateView()
}
private func updateView(){
travelViewController.view.isHidden = !(segmentedController.selectedSegmentIndex == 0)
nearbyViewController.view.isHidden = (segmentedController.selectedSegmentIndex == 0)
segmentedControlIndex = segmentedController.selectedSegmentIndex
}
private func setupSegmentedControl(){
segmentedController.removeAllSegments()
segmentedController.insertSegment(withTitle: "TAB_BAR_MAP".localized(), at: 0, animated: false)
segmentedController.insertSegment(withTitle: "TAB_BAR_NEARBY".localized(), at: 1, animated: false)
segmentedController.addTarget(self, action: #selector(selectionDidChange(sender:)), for: .valueChanged)
segmentedController.selectedSegmentIndex = segmentedControlIndex
}
func selectionDidChange(sender: UISegmentedControl){
updateView()
}
private func addViewControllerAsChildViewController(childViewController: UIViewController){
addChildViewController(childViewController)
view.addSubview(childViewController.view)
childViewController.view.frame = view.bounds
childViewController.view.autoresizingMask = [.flexibleWidth, .flexibleHeight]
childViewController.didMove(toParentViewController: self)
}
}

The problem is that you are not giving the segmented control any size. In iOS 11 the title view is sized internally by autolayout, but not in iOS 10 or before. So you end up with a segmented control of zero size.

Related

Send TitleLabel from UIButton to a UILabel in a different UIView Controller, But it's not being sent

I have one UIViewController that I am trying to send the titleLabel of a UIButton to a UILabel held within a different UIView Controller.
I have followed the same steps and pattern as within a previous method that worked fine, but the Title Text is just not getting passed onto the next VC.
I have a Button class called MtsCardsButton, but this just sets the animation and appearance of the button.
Thank you for reviewing.
Here is my code for the Button in the first VC:
import UIKit
class MTSCardsPage: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
//This is to make mtsCardsSetArray available to this ViewController
let otherVC = MTSDiscriminators()
mtsCardsSetArray2 = otherVC.mtsCardsSetArray
let otherVC2 = MTSDiscriminators()
allMtsDescriminatorsArray2 = otherVC2.allMtsDescriminatorsArray
//Set Card Titles from Array
Card1ButtonOutlet.setTitle(mtsCardsSetArray2[0], for: .normal)
Card2ButtonOutlet.setTitle(mtsCardsSetArray2[1], for: .normal)
Card3ButtonOutlet.setTitle(mtsCardsSetArray2[2], for: .normal)
Card4ButtonOutlet.setTitle(mtsCardsSetArray2[3], for: .normal)
Card5ButtonOutlet.setTitle(mtsCardsSetArray2[4], for: .normal)
//Do any additional setup after loading the view.
}
var mtsCardsButton = MtsCardsButton()
func addActionToMtsCardsButton() {
mtsCardsButton.addTarget(self, action: #selector(CardButton), for: .touchUpInside)
}
//This is to TELL the Button to do something AND to goto
//the MTS Discriminators UIView.
var cardButtonPressed = ""
#IBAction func CardButton(_ sender: MtsCardsButton) {
let secondVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(identifier: "DiscrimUIViewCollection") as! DiscrimUIViewCollection
cardButtonPressed = sender.currentTitle!
secondVC.updateTheLabel2 = cardButtonPressed
////I'VE TRIED THIS SECTION INSTEAD OF ABOVE AND IT STILL DOESN'T WORK.
// func prepare(for segue: UIStoryboardSegue, sender: Any?)
// {
// if segue.destination is DiscrimUIViewCollection
// {
// let vc = segue.destination as? DiscrimUIViewCollection
// vc?.updateTheLabel2 = cardButtonPressed
// }
// }
//switch area to make button move when pressed
switch cardButtonPressed {
case mtsCardsSetArray2[0]:
Card1ButtonOutlet.shakeMtsCardsButton()
case mtsCardsSetArray2[1]:
Card2ButtonOutlet.shakeMtsCardsButton()
case mtsCardsSetArray2[2]:
Card3ButtonOutlet.shakeMtsCardsButton()
case mtsCardsSetArray2[3]:
Card4ButtonOutlet.shakeMtsCardsButton()
case mtsCardsSetArray2[4]:
Card5ButtonOutlet.shakeMtsCardsButton()
default:
print("Error, unrecognised button pressed!")
}
guard let destinationVC = storyboard?.instantiateViewController(withIdentifier: "DiscrimUIViewCollection") as? DiscrimUIViewCollection else {
return
}
present(destinationVC, animated: true, completion: nil)
}
//Outlet for sending anything to the MTS Card Button
#IBOutlet weak var Card1ButtonOutlet: MtsCardsButton!
#IBOutlet weak var Card2ButtonOutlet: MtsCardsButton!
#IBOutlet weak var Card3ButtonOutlet: MtsCardsButton!
#IBOutlet weak var Card4ButtonOutlet: MtsCardsButton!
#IBOutlet weak var Card5ButtonOutlet: MtsCardsButton!
}
Here is the code for the second receiving VC:
class DiscrimUIViewCollection: UIViewController, UICollectionViewDelegate, UICollectionViewDataSource {
#IBOutlet weak var discriminatorTitle: UILabel!
var updateTheLabel2: String?
#IBAction func discrimButtonPressed(_ sender: UIButton) {
//action here to name what discriminator means.
print(sender.currentTitle!)
}
#IBOutlet weak var collectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
Card1ButtonOutlet.setTitle(mtsCardsSetArray2[0], for: .normal)
Card2ButtonOutlet.setTitle(mtsCardsSetArray2[1], for: .normal)
Card3ButtonOutlet.setTitle(mtsCardsSetArray2[2], for: .normal)
Card4ButtonOutlet.setTitle(mtsCardsSetArray2[3], for: .normal)
Card5ButtonOutlet.setTitle(mtsCardsSetArray2[4], for: .normal)
collectionView.dataSource = self
collectionView.delegate = self
self.collectionView.backgroundColor = .black
discriminatorTitle.text = updateTheLabel2
discriminatorTitle.font = UIFont(name: "Mukta Mahee", size: 18)
discriminatorTitle.font = UIFont.boldSystemFont(ofSize: 18)
discriminatorTitle.numberOfLines = 2
discriminatorTitle.minimumScaleFactor = 0.1
discriminatorTitle.baselineAdjustment = .alignCenters
discriminatorTitle.textAlignment = NSTextAlignment.center
discriminatorTitle.clipsToBounds = true
discriminatorTitle.backgroundColor = colourYellow
discriminatorTitle.textColor = .black
discriminatorTitle.layer.borderColor = UIColor.black.cgColor
discriminatorTitle.layer.borderWidth = 2.0
discriminatorTitle.layer.cornerRadius = 7
discriminatorTitle.layer.shadowColor = UIColor.black.cgColor
discriminatorTitle.layer.shadowOffset = CGSize(width: 0.0, height: 6.0)
discriminatorTitle.layer.shadowRadius = 7
discriminatorTitle.layer.shadowOpacity = 0.5
discriminatorTitle.clipsToBounds = false
discriminatorTitle.layer.masksToBounds = true
let layout = self.collectionView.collectionViewLayout as! UICollectionViewFlowLayout
layout.sectionInset = UIEdgeInsets(top: 0, left: 5, bottom: 0, right: 5)
layout.minimumInteritemSpacing = 2
layout.itemSize = CGSize(width: (self.collectionView.frame.size.width - 0)/1, height:self.collectionView.frame.size.height/3)
//Do any additional setup after loading the view.
func numberOfSections(in collectionView: UICollectionView) -> Int {
// 1
return 1
}
}
So, after many hours of studying up various websites I found the answer. I needed to add code and re-position the code. I Changed the Storyboard ID to match the DiscrimUIViewCollection.swift file.
I place the following code at the bottom of the 'switch' statement in the MTSCardsPage.swift file.
//To capture the card title and store it for
//preparation for changing based on Label.
guard let DiscrimUIViewCollection : DiscrimUIViewCollection = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "DiscrimUIViewCollection") as? DiscrimUIViewCollection else {
return
}
DiscrimUIViewCollection.updateTheLabel = sender.currentTitle!
present(DiscrimUIViewCollection, animated: true, completion: nil)
}
And to my delight, it all works fine!
The website I used to help me the most was this one:
https://fluffy.es/3-ways-to-pass-data-between-view-controllers/
Thanks for your assistance guys, each little comment made me think.
It's big learning curve!

DatePicker goes under UINavigationBar on iPhone, works well on iPad

I have the following code for the DatePickerController:
import UIKit
#objc protocol DatePickerControllerDelegate: AnyObject {
func datePicker(controller: DatePickerController, didSelect date: Date)
func datepickerDidDismiss(controller: DatePickerController)
}
final class DatePickerController: UIViewController {
#objc weak var delegate: DatePickerControllerDelegate?
#objc public var date: Date {
get {
return datePicker.date
}
set(value) {
datePicker.setDate(value, animated: false)
}
}
#objc public lazy var datePicker: UIDatePicker = {
let v = UIDatePicker()
v.datePickerMode = .date
return v
}()
override var preferredContentSize: CGSize {
get {
return datePicker.frame.size
}
set(newValue) {
super.preferredContentSize = newValue
}
}
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(datePicker)
datePicker.autoresizingMask = [.flexibleTopMargin, .flexibleRightMargin, .flexibleLeftMargin, .flexibleBottomMargin]
view.backgroundColor = .white
navigationItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done,
target: self,
action: #selector(DatePickerController.doneButtonDidTap))
navigationItem.leftBarButtonItem = UIBarButtonItem(barButtonSystemItem: .cancel,
target: self,
action: #selector(DatePickerController.cancelButtonDidTap))
}
#objc private func doneButtonDidTap() {
delegate?.datePicker(controller: self, didSelect: date)
}
#objc private func cancelButtonDidTap() {
dismiss(animated: true, completion: nil)
delegate?.datepickerDidDismiss(controller: self)
}
}
It works well on iPad:
However, on iPhone the picker slides up under the UINavigationBar:
The code used to show the DatePickerController is absolutely the same, the style is UIModalPresentationStylePopover in both cases.
Update: code to present DatePickerController:
#objc func presentDatePicker() {
let picker = DatePickerController()
let navC = UINavigationController(rootViewController: picker)
present(navC, animated: true, completion: nil)
}
Fixed using AutoLayout:
private func configureLayout() {
datePicker.translatesAutoresizingMaskIntoConstraints = false
[datePicker.topAnchor.constraint(equalTo: view.layoutMarginsGuide.topAnchor),
datePicker.leadingAnchor.constraint(equalTo: view.leadingAnchor),
datePicker.trailingAnchor.constraint(equalTo: view.trailingAnchor),]
.forEach{$0.isActive = true}
}

Swift - Cannot pass value successfully to the ViewController that is presented next

I have an ItemsController and I want to pass a value to the RepostController when using self.navigationController?.pushViewController(destination, animated: true) to present the RepostController. I want to set the itemId of the RepostController to be cell.item!.getId(). But in the RepostController, I always get a value of 0 from the itemId. I have also tried to print the values. They are commented in the codes below.
I'm using Swift 4 with Xcode 10.1.
// ITEMS CONTROLLER
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor:UIColor(red:0.30, green:0.30, blue:0.30, alpha:1.0)]
self.navigationController?.navigationBar.tintColor = UIColor(red:0.30, green:0.30, blue:0.30, alpha:1.0)
self.navigationController?.navigationBar.shadowImage = UIImage()
tableView.estimatedRowHeight = 250
tableView.rowHeight = UITableView.automaticDimension
DispatchQueue.main.async() {
self.refresh(sender: self)
self.tableView.reloadData()
}
if #available(iOS 11.0, *) {
self.navigationController?.navigationBar.prefersLargeTitles = true
}
if ((profileId == iApp.sharedInstance.getId() && pageId == Constants.ITEMS_PROFILE_PAGE) || pageId == Constants.ITEMS_FEED_PAGE || pageId == Constants.ITEMS_STREAM_PAGE) {
let newItemButton = UIBarButtonItem(barButtonSystemItem: .add , target: self, action: #selector(newItem))
self.navigationItem.rightBarButtonItem = newItemButton
}
// add tableview delegate
tableView.delegate = self
tableView.dataSource = self
self.tableView.tableFooterView = UIView()
self.refreshControl.addTarget(self, action: #selector(refresh), for: UIControl.Event.valueChanged)
self.tableView.addSubview(refreshControl)
self.tableView.alwaysBounceVertical = true
// prepare for loading data
self.showLoadingScreen()
// start loading data
self.loadData()
}
func showRepostButton(cell: ItemCell) {
let storyboard = UIStoryboard(name: "Content", bundle: Bundle.main)
let destination = storyboard.instantiateViewController(withIdentifier: "RepostController") as! RepostController
destination.itemId = cell.item!.getId()
print (String(cell.item!.getId())) // Whatever the correct value is (such as 20)
self.navigationController?.pushViewController(destination, animated: true)
}
// REPOST CONTROLLER
override func viewDidLoad() {
super.viewDidLoad()
navigationController?.navigationBar.titleTextAttributes = [NSAttributedString.Key.foregroundColor:UIColor(red:0.30, green:0.30, blue:0.30, alpha:1.0)]
self.navigationController?.navigationBar.tintColor = UIColor(red:0.30, green:0.30, blue:0.30, alpha:1.0)
textView.delegate = self
textView.tintColor = UIColor(red:0.23, green:0.72, blue:0.65, alpha:1.0)
print ("itemID:" + String(self.itemId))
}
#IBAction func cancelTap(_ sender: Any) {
self.dismiss(animated: true, completion: nil)
}
#IBAction func repostTap(_ sender: Any) {
self.message = self.textView.text
send()
}
I need the value to be passed to the RepostController successfully.
What changes do I need to make? Thanks!
What I would do is create a PUSH segue in IB. Then in the prepare(forSegue:) method:
if let dest = segue.destination as? YourDestinationVC {
dest.itemId = someValue
}

Delete/remove displayed controller inside Page View Controller on clicking delete button, Swift

I am displaying images in a collection view controller. When the cell is tapped, I am passing those images to page view controller, where the user is given an option to delete or add image description as you can see in the below images.
When the user clicks delete button, I would the page (or view controller) to be deleted (just like the behaviour seen, when delete button is clicked in in Apple iOS photos app).
I tried to achieve it, by passing an array of empty view controller to pageViewController (See Code A), which resulted in a error
The number of view controllers provided (0) doesn't match the number required (1) for the requested transition which makes sense.
Am I on the right track, if yes, how can I fix the issue ?
If not, Is there a better approach to achieve the same ?
Code A: Taken from Code B
pageVC.setViewControllers([], direction: .forward, animated: true, completion: nil)
Code B: Taken from UserPickedImageVC
func deleteCurrentImageObject(){
guard let controllers = self.navigationController?.viewControllers else{
return
}
for viewController in controllers {
if viewController.className == "UserPickedImagesVC"{
let vc = viewController as! UserPickedImagesVC
let objectCount = vc.imageObjectsArray.count
guard objectCount > 0 && objectCount >= itemIndex else {
return
}
vc.imageObjectsArray.remove(at: itemIndex) // Removing imageObject from the array
if let pageVC = vc.childViewControllers[0] as? UIPageViewController {
pageVC.setViewControllers([], direction: .forward, animated: true, completion: nil)
}
}
}
}
Storyboard
Here is the complete code (except some custom UICollectionViewCell):
UserPickedImagesCVC.swift
import UIKit
import ImagePicker
import Lightbox
private let imageCellId = "imageCell"
private let addCellId = "addImagesCell"
class UserPickedImagesCVC: UICollectionViewController, ImagePickerDelegate, UserPickedImagesVCProtocol {
let imagePickerController = ImagePickerController()
//var userPickedImages = [UIImage]()
var userPickedImages = [ImageObject]()
override func viewDidLoad() {
super.viewDidLoad()
imagePickerController.delegate = self as ImagePickerDelegate
// Uncomment the following line to preserve selection between presentations
// self.clearsSelectionOnViewWillAppear = false
// Register cell classes
self.collectionView!.register(ImageCVCell .self, forCellWithReuseIdentifier: imageCellId)
self.collectionView!.register(ImagePickerButtonCVCell.self, forCellWithReuseIdentifier: addCellId)
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using [segue destinationViewController].
// Pass the selected object to the new view controller.
}
*/
// MARK: UICollectionViewDataSource
override func numberOfSections(in collectionView: UICollectionView) -> Int {
// #warning Incomplete implementation, return the number of sections
return 1
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
// #warning Incomplete implementation, return the number of items
return userPickedImages.count + 1
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let item = indexPath.item
print("item: \(item)")
if item < userPickedImages.count {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: imageCellId, for: indexPath) as! ImageCVCell
let userPickedImageObject = userPickedImages[item]
//cell.showImagesButton.setImage(userPickedImage, for: .normal)
cell.showImagesButton.setImage(userPickedImageObject.image, for: .normal)
cell.showImagesButton.addTarget(self, action: #selector(showAlreadyPickedImages), for: .touchUpInside)
//cell.addButton.addTarget(self, action: #selector(showAlreadyPickedImages), for: .touchUpInside)
return cell
}
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: addCellId, for: indexPath) as! ImagePickerButtonCVCell
cell.addButton.addTarget(self, action: #selector(showImagePickerController), for: .touchUpInside)
return cell
// Configure the cell
}
//Function shows imagePicker that helps in picking images and capturing images with camera
func showImagePickerController(){
print("showImagePickerController func called")
//self.present(imagePickerController, animated: true, completion: nil)
self.navigationController?.pushViewController(imagePickerController, animated: true)
}
func showAlreadyPickedImages(){
let vc = self.storyboard?.instantiateViewController(withIdentifier: "userPickedImagesVC") as! UserPickedImagesVC
//vc.contentImages = userPickedImages
vc.imageObjectsArray = userPickedImages
vc.showingAlreadySavedImages = true
self.navigationController?.pushViewController(vc, animated: true)
}
func setImagesInCells(imageObjects : [ImageObject]){
print("setImagesInCells func called in CVC")
userPickedImages += imageObjects
collectionView?.reloadData()
}
// MARK: - ImagePickerDelegate
func cancelButtonDidPress(_ imagePicker: ImagePickerController) {
imagePicker.dismiss(animated: true, completion: nil)
}
func wrapperDidPress(_ imagePicker: ImagePickerController, images: [UIImage]) {
guard images.count > 0 else { return }
let lightboxImages = images.map {
return LightboxImage(image: $0)
}
let lightbox = LightboxController(images: lightboxImages, startIndex: 0)
imagePicker.present(lightbox, animated: true, completion: nil)
}
func doneButtonDidPress(_ imagePicker: ImagePickerController, images: [UIImage]) {
imagePicker.dismiss(animated: true, completion: nil)
let vc = storyboard?.instantiateViewController(withIdentifier: "userPickedImagesVC") as! UserPickedImagesVC
//vc.contentImages = images
vc.imageObjectsArray = convertImagesToImageObjects(images)
//self.present(vc, animated: true, completion: nil)
self.navigationController?.pushViewController(vc, animated: true)
}
func convertImagesToImageObjects(_ imagesArray : [UIImage]) -> [ImageObject]{
var imageObjects = [ImageObject]()
for image in imagesArray{
var imageObject = ImageObject()
imageObject.image = image
imageObject.imageDescription = ""
imageObjects.append(imageObject)
}
return imageObjects
}
}
UserPickedImagesVC.swift
import UIKit
protocol UserPickedImagesVCProtocol{
func setImagesInCells(imageObjects : [ImageObject])
}
class ImageObject : NSObject{
var imageDescription : String?
var image : UIImage?
}
class UserPickedImagesVC: UIViewController, UIPageViewControllerDataSource {
var pageViewController : UIPageViewController?
let placeholderText = "Image description.."
var imageObjectsArray = [ImageObject]()
var delegate : UserPickedImagesVCProtocol!
var showingAlreadySavedImages = false
override func viewDidLoad() {
super.viewDidLoad()
edgesForExtendedLayout = [] // To avoid view going below nav bar
//self.delegate = self.navigationController?.viewControllers
// Do any additional setup after loading the view, typically from a nib.
if showingAlreadySavedImages{
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Done", style: .plain, target: self, action: #selector(doneTapped))
}else{
navigationItem.rightBarButtonItem = UIBarButtonItem(title: "Save", style: .plain, target: self, action: #selector(saveTapped))
}
// createImageAndDescriptionDict()
createPageViewController()
setupPageControl()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func createPageViewController(){
print("createPageViewController func called")
let pageController = self.storyboard?.instantiateViewController(withIdentifier: "userPickedImagesPageController") as! UIPageViewController
pageController.dataSource = self
if imageObjectsArray.count > 0 {
let firstController = getItemController(0)
let startingViewControllers = [firstController]
pageController.setViewControllers(startingViewControllers as! [UIViewController], direction: .forward, animated: false, completion: nil)
}
pageViewController = pageController
addChildViewController(pageViewController!)
self.view.addSubview((pageViewController?.view)!)
pageViewController?.didMove(toParentViewController: self)
}
// Creata the appearance of pagecontrol
func setupPageControl(){
let appearance = UIPageControl.appearance()
appearance.pageIndicatorTintColor = UIColor.gray
appearance.currentPageIndicatorTintColor = UIColor.white
appearance.backgroundColor = UIColor.darkGray
}
//MARK: Delagate methods
func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
let itemController = viewController as! UserPickedImageVC
if itemController.itemIndex > 0 {
return self.getItemController(itemController.itemIndex-1)
}
return nil
}
func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
let itemController = viewController as! UserPickedImageVC
if itemController.itemIndex + 1 < imageObjectsArray.count{
return getItemController(itemController.itemIndex+1)
}
return nil
}
func presentationCount(for pageViewController: UIPageViewController) -> Int {
return imageObjectsArray.count
}
func presentationIndex(for pageViewController: UIPageViewController) -> Int {
return 0
}
func currentControllerIndex() -> Int{
let pageItemController = self.currentControllerIndex()
if let controller = pageItemController as? UserPickedImageVC{
return controller.itemIndex
}
return -1
}
func currentController() -> UIViewController?{
if(self.pageViewController?.viewControllers?.count)! > 0{
return self.pageViewController?.viewControllers?[0]
}
return nil
}
func getItemController(_ itemIndex:Int) -> UserPickedImageVC?{
if itemIndex < imageObjectsArray.count{
let pageItemController = self.storyboard?.instantiateViewController(withIdentifier: "userPickedImageVC") as! UserPickedImageVC
pageItemController.itemIndex = itemIndex
//pageItemController.imageName = imageObjectsArray[itemIndex]
//pageItemController.imageToShow = imageObjectsArray[itemIndex]
//pageItemController.imageToShow = getImageFromImageDescriptionArray(itemIndex, imagesAndDescriptionArray)
pageItemController.imageObject = imageObjectsArray[itemIndex]
pageItemController.itemIndex = itemIndex
pageItemController.showingAlreadySavedImage = showingAlreadySavedImages
print("Image Name from VC: \(imageObjectsArray[itemIndex])")
return pageItemController
}
return nil
}
// Passing images back to Collection View Controller when save button is tapped
func saveTapped(){
let viewControllers = self.navigationController?.viewControllers
//print("viewControllers: \(viewControllers)")
if let destinationVC = viewControllers?[0]{
self.delegate = destinationVC as! UserPickedImagesVCProtocol
//self.delegate.setImagesInCells(images : imageObjectsArray)
self.delegate.setImagesInCells(imageObjects : imageObjectsArray)
self.navigationController?.popToViewController(destinationVC, animated: true)
}
}
func doneTapped(){
let viewControllers = self.navigationController?.viewControllers
if let destinationVC = viewControllers?[0] {
self.navigationController?.popToViewController(destinationVC, animated: true)
}
}
}
UserPickedImageVC.swift
import UIKit
import ImageScrollView
extension UIViewController {
var className: String {
return NSStringFromClass(self.classForCoder).components(separatedBy: ".").last!;
}
}
class UserPickedImageVC: UIViewController, UITextViewDelegate {
var itemIndex : Int = 0
var imageDescription : String = ""
var imageScrollView = ImageScrollView()
var imageDescriptionTextView : UITextView!
var imageToShow : UIImage!
var imageObject : ImageObject?
var deleteButton = UIButton(type: .system)
var showingAlreadySavedImage = false
var pageViewController : UIPageViewController!
override func viewDidLoad() {
super.viewDidLoad()
edgesForExtendedLayout = [] // To avoid images going below the navigation bars
pageViewController = self.parent as! UIPageViewController
setConstraints()
setImageAndDescription()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//MARK: TextView delegate methods
func textViewDidBeginEditing(_ textView: UITextView)
{
if (imageDescriptionTextView.text == "Image description..")
{
imageDescriptionTextView.text = ""
imageDescriptionTextView.textColor = .black
}
imageDescriptionTextView.becomeFirstResponder() //Optional
}
func textViewDidEndEditing(_ textView: UITextView)
{
let imageDescription = imageDescriptionTextView.text
if (imageDescription == "")
{
imageDescriptionTextView.text = "Image description.."
imageDescriptionTextView.textColor = .lightGray
}
imageObject?.imageDescription = imageDescription
updateImageObject(imageObject!)
imageDescriptionTextView.resignFirstResponder()
}
//MARK: Private Methods
func setImageAndDescription(){
if let imageToDisplay = imageObject?.image{
imageScrollView.display(image: imageToDisplay) // Setting Image
}
imageDescriptionTextView.text = imageObject?.imageDescription // Setting Description
}
// Function to update imageObject in UserPickedImagesVC
func updateImageObject(_ imageObject: ImageObject){
guard let controllers = self.navigationController?.viewControllers else{
return
}
for viewController in controllers {
if viewController.className == "UserPickedImagesVC" {
let vc = viewController as! UserPickedImagesVC
vc.imageObjectsArray[itemIndex] = imageObject
}
}
}
// Function to delete imageObject from UserPickedImagesVC
func deleteCurrentImageObject(){
guard let controllers = self.navigationController?.viewControllers else{
return
}
for viewController in controllers {
if viewController.className == "UserPickedImagesVC"{
let vc = viewController as! UserPickedImagesVC
let objectCount = vc.imageObjectsArray.count
guard objectCount > 0 && objectCount >= itemIndex else {
return
}
vc.imageObjectsArray.remove(at: itemIndex) // Removing imageObject from the array
if let pageVC = vc.childViewControllers[0] as? UIPageViewController {
pageVC.setViewControllers([], direction: .forward, animated: true, completion: nil)
}
}
}
}
func showOrHideDeleteButton(){
if showingAlreadySavedImage{
print("deleteButton.isNotHidden")
deleteButton.isHidden = false
}else{
print("deleteButton.isHidden")
deleteButton.isHidden = true
}
}
func setConstraints(){
let viewSize = self.view.frame.size
let viewWidth = viewSize.width
let viewHeight = viewSize.height
print("viewWidth: \(viewWidth), viewHeight: \(viewHeight)")
view.addSubview(imageScrollView)
imageScrollView.frame = CGRect(x: 0, y: 0, width: viewWidth, height: viewHeight)
deleteButton.tintColor = Colors.iOSBlue
deleteButton.setImage(#imageLiteral(resourceName: "delete"), for: .normal)
deleteButton.backgroundColor = Colors.white
deleteButton.layer.cornerRadius = 25
deleteButton.imageEdgeInsets = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
//deleteButton.currentImage.
deleteButton.imageView?.tintColor = Colors.iOSBlue
deleteButton.addTarget(self, action: #selector(deleteCurrentImageObject), for: .touchUpInside)
deleteButton.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(deleteButton)
showOrHideDeleteButton()
imageDescriptionTextView = UITextView()
imageDescriptionTextView.delegate = self as! UITextViewDelegate
imageDescriptionTextView.text = "Image description.."
imageDescriptionTextView.textColor = .lightGray
//imageScrollView.clipsToBounds = true
imageDescriptionTextView.translatesAutoresizingMaskIntoConstraints = false
//imageDescriptionTextView.backgroundColor = UIColor.white.withAlphaComponent(0.8)
imageDescriptionTextView.backgroundColor = UIColor.white
imageDescriptionTextView.layer.cornerRadius = 5
imageDescriptionTextView.layer.borderColor = UIColor.lightGray.cgColor
imageDescriptionTextView.layer.borderWidth = 0.5
view.addSubview(imageDescriptionTextView)
let viewsDict = [
"imageDescriptionTextView" : imageDescriptionTextView,
"deleteButton" : deleteButton
] as [String:Any]
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|-5-[imageDescriptionTextView]-70-|", options: [], metrics: nil, views: viewsDict))
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[imageDescriptionTextView(50)]-5-|", options: [], metrics: nil, views: viewsDict))
imageDescriptionTextView.sizeThatFits(CGSize(width: imageDescriptionTextView.frame.size.width, height: imageDescriptionTextView.frame.size.height))
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:[deleteButton(50)]-5-|", options: [], metrics: nil, views: viewsDict))
view.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:[deleteButton(50)]-5-|", options: [], metrics: nil, views: viewsDict))
}
}
create a call back property in UserPickedImageVC.swift
typealias DeleteCallBack = (int) -> Void
...
var itemIndex : Int = 0
var deleteCallBack:DeleteCallBack?
...
func deleteCurrentImageObject(){
self.deleteCallBack?(self.itemIndex)
}
in UserPickedImagesVC.swift
func getItemController(_ itemIndex:Int) -> UserPickedImageVC?{
if itemIndex < imageObjectsArray.count{
let pageItemController = self.storyboard?.instantiateViewController(withIdentifier: "userPickedImageVC") as! UserPickedImageVC
pageItemController.itemIndex = itemIndex
pageItemController.imageObject = imageObjectsArray[itemIndex]
pageItemController.itemIndex = itemIndex
pageItemController.showingAlreadySavedImage = showingAlreadySavedImages
print("Image Name from VC: \(imageObjectsArray[itemIndex])")
pageItemController.deleteCallBack = {
[weak self] (index) -> Void in
self?.deleteItemAt(index: index)
}
return pageItemController
}
return nil
}
func deleteItemAt(index: Int) {
if (imageObjectsArray.count > 1) {
imageObjectsArray.remove(at: itemIndex)
self.pageViewController.dataSource = nil;
self.pageViewController.dataSource = self;
let firstController = getItemController(0)
let startingViewControllers = [firstController]
pageViewController.setViewControllers(startingViewControllers as! [UIViewController], direction: .forward, animated: false, completion: nil)
} else {
//redirect here
_ = navigationController?.popViewController(animated: true)
}
}

Xcode Swift: Cannot close popup Image

I created a ViewController that displays three images and other info via JSON parsing through three separate UIImageViews. When you click any of the images, it takes you to another ViewController that pop-ups a UIScrollView in the background, one UIImageView which is linked to all three images and a Button that would close the pop-up ViewController and bring it back to the previous one. Here is a screenshot. The problem I am having is that I added this code:
func removeZoom()
{
UIView.animateWithDuration(0.25, animations: {
self.view.transform = CGAffineTransformMakeScale(1.3, 1.3)
self.view.alpha = 0.0;
}, completion:{(finished : Bool) in
if (finished)
{
self.view.removeFromSuperview()
}
});
}
#IBAction func closeZoom(sender: AnyObject) {
self.navigationController?.popToRootViewControllerAnimated(true)
}
And when I try to click on the close button, nothing happens. Don't know what I am missing. Any guidance would be helpful.
Here i'll put the code for both controllers:
JnsDetail.swift
import Foundation
import UIKit
class JnsDetail: UIViewController {
#IBOutlet var tituloLabel : UILabel!
#IBOutlet var marcaLabel : UILabel!
#IBOutlet var colorLabel : UILabel!
#IBOutlet var tipoLabel : UILabel!
#IBOutlet var refLabel : UILabel!
#IBOutlet var imageView : UIImageView!
#IBOutlet var imageView2 : UIImageView!
#IBOutlet var imageView3 : UIImageView!
#IBOutlet var backbutton : UIButton!
var jsonextrct : JsonExtrct!
var photos : [String]!
var transitionOperator = TransitionOperator()
override func viewDidLoad() {
super.viewDidLoad()
//titulo = jsonextrct.titulo
tituloLabel.font = UIFont(name: mTheme.fontName, size: 21)
tituloLabel.textColor = UIColor.blackColor()
tituloLabel.text = jsonextrct.titulo
//marca = jsonextrct.marca
marcaLabel.font = UIFont(name: mTheme.fontName, size: 21)
marcaLabel.textColor = UIColor.blackColor()
marcaLabel.text = jsonextrct.marca
//color = jsonextrct.color
colorLabel.font = UIFont(name: mTheme.fontName, size: 21)
colorLabel.textColor = UIColor.blackColor()
colorLabel.text = jsonextrct.color
//tipo = jsonextrct.tipo
tipoLabel.font = UIFont(name: mTheme.fontName, size: 21)
tipoLabel.textColor = UIColor.blackColor()
tipoLabel.text = jsonextrct.tipo
//ref = jsonextrct.ref
refLabel.font = UIFont(name: mTheme.fontName, size: 21)
refLabel.textColor = UIColor.blackColor()
refLabel.text = "\(jsonextrct.ref)"
if let imageData = jsonextrct.imageData {
imageView.image = UIImage(data: imageData)
}else{
Utils.asyncLoadJsonImage(jsonextrct, imageView: imageView)
}
//topImageViewHeightConstraint.constant = 240
imageView.layer.borderColor = UIColor(white: 0.2, alpha: 1.0).CGColor
imageView.layer.borderWidth = 0.5
if let imageData2 = jsonextrct.imageData2 {
imageView2.image = UIImage(data: imageData2)
}else{
Utils.asyncLoadJsonImage(jsonextrct, imageView2: imageView2)
}
imageView2.layer.borderColor = UIColor(white: 0.2, alpha: 1.0).CGColor
imageView2.layer.borderWidth = 0.5
if let imageData3 = jsonextrct.imageData3 {
imageView3.image = UIImage(data: imageData3)
}else{
Utils.asyncLoadJsonImage(jsonextrct, imageView3: imageView3)
}
imageView3.layer.borderColor = UIColor(white: 0.2, alpha: 1.0).CGColor
imageView3.layer.borderWidth = 0.5
var tapGestureZoom = UITapGestureRecognizer(target: self, action: "zoomJns:")
tapGestureZoom.numberOfTapsRequired = 1
tapGestureZoom.numberOfTouchesRequired = 1
imageView.userInteractionEnabled = true
imageView.addGestureRecognizer(tapGestureZoom)
var tapGestureZoom2 = UITapGestureRecognizer(target: self, action: "zoomJns2:")
tapGestureZoom2.numberOfTapsRequired = 1
tapGestureZoom2.numberOfTouchesRequired = 1
imageView2.userInteractionEnabled = true
imageView2.addGestureRecognizer(tapGestureZoom2)
var tapGestureZoom3 = UITapGestureRecognizer(target: self, action: "zoomJns3:")
tapGestureZoom3.numberOfTapsRequired = 1
tapGestureZoom3.numberOfTouchesRequired = 1
imageView3.userInteractionEnabled = true
imageView3.addGestureRecognizer(tapGestureZoom3)
}
override func preferredStatusBarStyle() -> UIStatusBarStyle {
return UIStatusBarStyle.Default
}
func backTapped(sender: AnyObject?){
dismissViewControllerAnimated(true, completion: nil)
}
#IBAction func zoomJns(sender: AnyObject?){
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewControllerWithIdentifier("JnsZoomController") as! JnsZoomController
self.modalPresentationStyle = UIModalPresentationStyle.Custom
controller.transitioningDelegate = transitionOperator
controller.jsonextrct = jsonextrct
presentViewController(controller, animated: true, completion: nil)
}
#IBAction func zoomJns2(sender: AnyObject?){
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewControllerWithIdentifier("JnsZoomController") as! JnsZoomController
self.modalPresentationStyle = UIModalPresentationStyle.Custom
controller.transitioningDelegate = transitionOperator
controller.jsonextrct = jsonextrct
presentViewController(controller, animated: true, completion: nil)
}
#IBAction func zoomJns3(sender: AnyObject?){
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let controller = storyboard.instantiateViewControllerWithIdentifier("JnsZoomController") as! JnsZoomController
self.modalPresentationStyle = UIModalPresentationStyle.Custom
controller.transitioningDelegate = transitionOperator
controller.jsonextrct = jsonextrct
presentViewController(controller, animated: true, completion: nil)
}
}
JnsZoomController.swift
import Foundation
import UIKit
class JnsZoomController : UIViewController {
#IBOutlet var scrollView : UIScrollView!
#IBOutlet var jnsImageView : UIImageView!
#IBOutlet var jnsImageView2 : UIImageView!
#IBOutlet var jnsImageView3 : UIImageView!
var jsonextrct : JsonExtrct!
override func viewDidLoad() {
super.viewDidLoad()
if let imageData = jsonextrct.imageData {
let image = UIImage(data: imageData)
jnsImageView.image = UIImage(data: imageData)
//jnsImageView.bounds = CGRectMake(0, 0, image?.size.width, image?.size.height);
}
if let imageData2 = jsonextrct.imageData2 {
let image2 = UIImage(data: imageData2)
jnsImageView2.image = UIImage(data: imageData2)
//jnsImageView2.bounds = CGRectMake(0, 0, image?.size.width, image?.size.height);
}
if let imageData3 = jsonextrct.imageData3 {
let image3 = UIImage(data: imageData3)
jnsImageView3.image = UIImage(data: imageData3)
//jnsImageView3.bounds = CGRectMake(0, 0, image?.size.width, image?.size.height);
}
scrollView.contentSize = jnsImageView.frame.size
scrollView.contentSize = jnsImageView2.frame.size
scrollView.contentSize = jnsImageView3.frame.size
}
func removeZoom()
{
UIView.animateWithDuration(0.25, animations: {
self.view.transform = CGAffineTransformMakeScale(1.3, 1.3)
self.view.alpha = 0.0;
}, completion:{(finished : Bool) in
if (finished)
{
self.view.removeFromSuperview()
}
});
}
#IBAction func closeZoom(sender: AnyObject) {
self.navigationController?.popToRootViewControllerAnimated(true)
}
}
Here's the problem as I see it, if you are "popping" to root view controller this means that you must have PUSHED a view controller onto the navigation controller's stack and I don't see you pushing anything onto a navigation stack. Unless of course for some reason Apple decided to kill off Pushing view controllers, but I doubt this is the case. So, there's another problem with what I'm seeing in your code. You are PRESENTING view controllers by just presenting a view controller, I don't see where you are presenting a view controller by using a navigation controller to present the view controller SOOO, if you call
self.navigationController?.popToRootViewControllerAnimated(true)
then there's nothing on the stack that the navigation controller is to remove from the stack since you presented the viewcontroller modally over another viewcontroller without presenting the modal in the view controller's navigation controller.
Solution, maybe, but this isn't 100% becuase I don't have your code in front of me.
change this:
self.navigationController?.popToRootViewControllerAnimated(true)
to something like this
self.dismissViewControllerAnimated(animated: true, completion:nil)
I don't do swift so my solution is pseudo code, feel free to add the questions marks and what not that Apple decided has value for some reason.
You could also just change your presentations to this:
self.navigationController?.presentViewController(controller, animated: true, completion: nil)
Again, the above is psuedo code but I think I place the question mark in just the right spot for so that it does what it's suppose to do
Also, you can refer to this, although Apple doesn't really do a very thoroughly job of telling you how an advanced navigaiton stack works:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UINavigationController_Class/#//apple_ref/occ/instm/UINavigationController/pushViewController:animated:
Sometimes you will need to have maybe 4-10 navigation controllers running at one time, so make sure you understand how they interact with view controllers and make sure you understand what POPs, PUSHes, and PRESENTs do. And good luck, have a good day.
In the closeZoom I think you should use only
#IBAction func closeZoom(sender: AnyObject) {
dismissViewControllerAnimated(true, completion: nil)
}
Because you presented that View Controller, that popToRootViewControllerAnimated(true) is used when you push it

Resources