I am trying to create a collectionView which slides up when the user swipes up. For now I am using a button instead of the scroll gesture to trigger the animation. When the animation Begins I want the collectionView to expand in height but the cells to stay where they are and then as the user scrolls slide up. How do I animate the collectionView without moving the cells? Is this possible to do? I would like for the collectionView to expand up and show the hidden cells that were covered up during the scroll not or show a blank space from the collectionView not just move all of the cells higher on the screen.
Function of Code in Question
var buttonPressed:Bool = true
#IBAction func changeView(_ sender: Any) {
if buttonPressed{
UIView.animate(withDuration: 0.05){
self.animateCollectionView.frame = CGRect(x: 0, y: 100, width: 600, height: 1000)
// self.animateCollectionView.transform = CGAffineTransform(translationX: 0, y: -20)
self.view.sendSubview(toBack: self.animateCollectionView)
self.buttonPressed = !self.buttonPressed
print("Ive been expanded")
}
}
else{
UIView.animate(withDuration: 0.05){
self.animateCollectionView.frame = CGRect(x: 0, y: 20, width: 600, height: 1000)
// self.animateCollectionView.transform = CGAffineTransform(translationX: 0, y: 20)
self.buttonPressed = !self.buttonPressed
}
}
}
Code as whole:
import UIKit
class ViewController: UIViewController,UICollectionViewDataSource,UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 200
}
var counter:Int = 0
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = self.animateCollectionView.dequeueReusableCell(withReuseIdentifier: "cell", for: indexPath) as! customCell
counter+=1
cell.cellLabel.text = "\(counter)"
cell.backgroundColor = UIColor.orange
return cell
}
#IBOutlet weak var animateCollectionView: UICollectionView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
animateCollectionView.dataSource = self
animateCollectionView.delegate = self
animateCollectionView.backgroundColor = UIColor.blue
animateCollectionView.frame = CGRect(x: 0, y: 100, width: 600, height: 1000)
self.view.sendSubview(toBack: self.animateCollectionView)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
var buttonPressed:Bool = true
#IBAction func changeView(_ sender: Any) {
if buttonPressed{
UIView.animate(withDuration: 0.05){
self.animateCollectionView.frame = CGRect(x: 0, y: 100, width: 600, height: 1000)
// self.animateCollectionView.transform = CGAffineTransform(translationX: 0, y: -20)
self.view.sendSubview(toBack: self.animateCollectionView)
self.buttonPressed = !self.buttonPressed
print("Ive been expanded")
}
}
else{
UIView.animate(withDuration: 0.05){
self.animateCollectionView.frame = CGRect(x: 0, y: 20, width: 600, height: 1000)
// self.animateCollectionView.transform = CGAffineTransform(translationX: 0, y: 20)
self.buttonPressed = !self.buttonPressed
}
}
}
}
class customCell :UICollectionViewCell{
#IBOutlet weak var cellLabel: UILabel!
}
Related
I am trying to implement a method to where I have a tableviewcontroll that has a header where it shows a head picture as well as another section with the User's information and Profile picture. Below the head I want there to be a segment control like twitter that will allow a user to switch between different tableviews. I want that segment control to be below the header view so when a user pulls down, the segment control moves down with the header view, when you scroll up the segment control moves up with the headerview but then sticks below the navigation bar similar to how twitter and instagram's UI works. I have implemented the code below but I am getting an issue to when I scroll up, the segment controller doesn't move but when I pull down on the screen the segment control moves down with the header view. Any Idea why it is doing this?
Here is the code
class RandomTableViewController: UITableViewController {
#IBOutlet weak var trackImage: UIImageView!
private let tableHeaderViewHeight: CGFloat = 320.0
private let tableHeaderViewCutAway: CGFloat = 0.1
var headerView: HeaderView!
var headerMaskLayer: CAShapeLayer!
override func viewDidLoad() {
super.viewDidLoad()
self.automaticallyAdjustsScrollViewInsets = false
tableView.estimatedSectionHeaderHeight = 40.0
navigationController?.navigationBar.setBackgroundImage(UIImage(), for: .default)
navigationController?.navigationBar.shadowImage = UIImage()
tableView.tableFooterView = UIView()
headerView = tableView.tableHeaderView as! HeaderView
// headerView.imageView = trackImage
tableView.tableHeaderView = nil
tableView.addSubview(headerView)
tableView.contentInset = UIEdgeInsets(top: tableHeaderViewHeight, left: 0, bottom: 0, right: 0)
tableView.contentOffset = CGPoint(x: 0, y: -tableHeaderViewHeight + 64)
//cut away header view
headerMaskLayer = CAShapeLayer()
headerMaskLayer.fillColor = UIColor.black.cgColor
headerView.layer.mask = headerMaskLayer
let effectiveHeight = tableHeaderViewHeight - tableHeaderViewCutAway/2
tableView.contentInset = UIEdgeInsets(top: effectiveHeight, left: 0, bottom: 0, right: 0)
tableView.contentOffset = CGPoint(x: 0, y: -effectiveHeight)
updateHeaderView()
}
func updateHeaderView() {
let effectiveHeight = tableHeaderViewHeight - tableHeaderViewCutAway/2
var headerRect = CGRect(x: 0, y: -effectiveHeight, width: tableView.bounds.width, height: tableHeaderViewHeight)
if tableView.contentOffset.y < -effectiveHeight {
headerRect.origin.y = tableView.contentOffset.y
headerRect.size.height = -tableView.contentOffset.y + tableHeaderViewCutAway/2
}
headerView.frame = headerRect
let path = UIBezierPath()
path.move(to: CGPoint(x: 0, y:0))
path.addLine(to: CGPoint(x: headerRect.width, y: 0))
path.addLine(to: CGPoint(x: headerRect.width, y: headerRect.height))
path.addLine(to: CGPoint(x: 0, y: headerRect.height - tableHeaderViewCutAway))
headerMaskLayer?.path = path.cgPath
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
self.tableView.decelerationRate = UIScrollView.DecelerationRate.fast
}
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
return UITableView.automaticDimension
}
#IBAction func backButton(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
}
extension RandomTableViewController {
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let v = UIView()
v.backgroundColor = .white
let segmentedControl = UISegmentedControl(frame: CGRect(x: 10, y: 5, width: tableView.frame.width - 20, height: 30))
segmentedControl.insertSegment(withTitle: "One", at: 0, animated: false)
segmentedControl.insertSegment(withTitle: "Two", at: 1, animated: false)
segmentedControl.insertSegment(withTitle: "Three", at: 2, animated: false)
v.addSubview(segmentedControl)
return v
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
100
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell: UITableViewCell! = tableView.dequeueReusableCell(withIdentifier: "CellID")
cell.textLabel?.text = "\(indexPath.row)"
return cell
}
}
extension RandomTableViewController {
override func scrollViewDidScroll(_ scrollView: UIScrollView) {
updateHeaderView()
}
}
I have custom HeaderView code which is
import UIKit
class HeaderView: UIView {
#IBOutlet weak var imageView: UIImageView!
#IBOutlet weak var trackImage: UIImageView!
#IBOutlet weak var backButton: UIButton!
}
Here is what it is doing
UPDATE:
I implemented the grouped tableview and setting the estimatedSectioHeaderHeight in the viewForSectionInHeader and now the segmented control moves up and down but it is not sticking below the navigation bar when scrolling up. Also there seems to be a formatting issue now. Here is how the simulator looks
change the table style to grouped and set height of the segment view in heightForHeaderInSection.
Check whether it works.
My scenario, I am trying to create UITableview with card effects and top banner. I have added It will work like stretchable tableview header. Everything I am done by using storyboard but I am stuck in showing half of tableview first index cell show on banner head. I tried multiple ideas but I didn’t completed. Provide some idea for achieve this design.
Current Output:
Expected Output:
From your demo project HERE I have made some changes to you existing code like your scrollViewDidScroll will be:
var lastContentOffset: CGFloat = 0
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
self.lastContentOffset = scrollView.contentOffset.y
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if self.lastContentOffset < scrollView.contentOffset.y {
//Up
let y = 220 - (scrollView.contentOffset.y + 220)
let height = min(max(y, 60), 220)
if height >= 128 {
imageView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: height + 70)
}
} else if self.lastContentOffset > scrollView.contentOffset.y {
//Down
let y = 300 - (scrollView.contentOffset.y + 300)
let height = min(max(y, 60), 400)
imageView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: height + 80)
}
}
With above code I have added different conditions for up and down as per your requirement and from storyboard I have change top constraint to 84 so that your table will not scroll to top.
So your full code will look like:
import UIKit
class ViewController: UIViewController {
#IBOutlet weak var tableView: UITableView!
let imageView = UIImageView()
var lastContentOffset: CGFloat = 0
override func viewDidLoad() {
super.viewDidLoad()
tableView.estimatedRowHeight = 50
tableView.contentInset = UIEdgeInsetsMake(220, 0, 0, 0)
tableView.backgroundColor = UIColor.darkGray
imageView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: 300)
imageView.image = UIImage.init(named: "poster")
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true
view.addSubview(imageView)
self.tableView.backgroundColor = .clear
self.view.bringSubview(toFront: tableView)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
extension ViewController: UITableViewDelegate, UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 20
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "customCell", for: indexPath) as! CustomTableViewCell
switch indexPath.row % 2 {
case 0:
cell.titleLabel.text = "Lorem Ipsum is simply dummy text ."
cell.contentView.backgroundColor = UIColor.darkGray
default:
cell.contentView.backgroundColor = UIColor.black
cell.titleLabel.text = "There is no one who loves pain itself, who seeks after it and wants to have it, simply because it is pain..."
cell.titleLabel.textColor = .white
}
return cell
}
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
self.lastContentOffset = scrollView.contentOffset.y
}
func scrollViewDidScroll(_ scrollView: UIScrollView) {
if self.lastContentOffset < scrollView.contentOffset.y {
let y = 220 - (scrollView.contentOffset.y + 220)
let height = min(max(y, 60), 220)
if height >= 128 {
imageView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: height + 70)
}
} else if self.lastContentOffset > scrollView.contentOffset.y {
let y = 300 - (scrollView.contentOffset.y + 300)
let height = min(max(y, 60), 400)
imageView.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: height + 80)
}
}
}
And result will be:
HERE is the link for your updated project.
I'm trying to create several UITableViews programmatically in the same scroll view. I'm correctly loading the tables' data into each array, but for some reason the table is populating every other cell. I added a print statement in cellForRowAt: to make sure it wasn't skipping data somehow and it doesn't seem to.
Also, didSelectRowAt: isn't being called when I click on a row, but didHighlightRowAt: is called correctly. And using that the table cells seem to load properly, it's just skipping every other cell when populating them.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
var cellIdentifier = ""
switch tableView {
case tableView1:
cellIdentifier = "AddOnTableViewCell1"
case tableView2:
cellIdentifier = "AddOnTableViewCell2"
case tableView3:
cellIdentifier = "AddOnTableViewCell3"
case tableView4:
cellIdentifier = "AddOnTableViewCell4"
default:
print("Too many tables")
}
guard let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as? AddOnTableViewCell else {
fatalError("Dequed cell error")
}
let titleLabel = UILabel(frame: CGRect(x: 16, y: cell.frame.minY + 10, width: view.frame.width - 30, height: 30))
titleLabel.textColor = .black
titleLabel.textAlignment = .left
switch tableView {
case tableView1:
titleLabel.text = addOnContents1[indexPath.row]
print("\(indexPath.row), \(addOnContents1[indexPath.row])")
case tableView2:
titleLabel.text = addOnContents2[indexPath.row]
print("\(indexPath.row), \(addOnContents2[indexPath.row])")
case tableView3:
titleLabel.text = addOnContents3[indexPath.row]
print("\(indexPath.row), \(addOnContents3[indexPath.row])")
case tableView4:
titleLabel.text = addOnContents4[indexPath.row]
print("\(indexPath.row), \(addOnContents4[indexPath.row])")
default:
print("Too many tables")
}
cell.addSubview(titleLabel)
return cell
}
The print statements above show that the data added correctly corresponds to the indexRow.path, i.e. 0 is item00, 1 is item01, 2 is item02, 3 is item03, ...
Then here are the other two methods mentioned.
func tableView(_ tableView: UITableView, didHighlightRowAt indexPath: IndexPath) {
switch tableView {
case tableView1:
print(addOnContents1[indexPath.row])
case tableView2:
print(addOnContents2[indexPath.row])
case tableView3:
print(addOnContents3[indexPath.row])
case tableView4:
print(addOnContents4[indexPath.row])
default:
print("Too many tables")
}
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
print("Pressed")
switch tableView {
case tableView1:
print(indexPath.row)
case tableView2:
print(indexPath.row)
case tableView3:
print(indexPath.row)
case tableView4:
print(indexPath.row)
default:
print("Too many tables")
}
}
Finally, here's my code for setting up the tableViews
func loadAddOnViews() {
var count = 1
for item in addOns {
var contentSize: CGFloat = 0
switch count {
case 1:
let label = UILabel(frame: CGRect(x: 16, y: yCoordinateForNewContent, width: scrollView.frame.width - 32, height: 50))
label.text = addOns[0].title
yCoordinateForNewContent += 50
scrollView.addSubview(label)
contentSize = CGFloat(addOnContents1.count)
print("content size: \(contentSize)")
contentSize = contentSize * cellSize
tableView1 = UITableView(frame: CGRect(x: 0, y: yCoordinateForNewContent, width: scrollView.frame.width, height: contentSize))
scrollView.addSubview(tableView1)
tableView1.delegate = self
tableView1.dataSource = self
self.tableView1.register(AddOnTableViewCell.self, forCellReuseIdentifier: "AddOnTableViewCell1")
yCoordinateForNewContent += contentSize + 20
tableView1.reloadData()
case 2:
let label = UILabel(frame: CGRect(x: 16, y: yCoordinateForNewContent, width: scrollView.frame.width - 32, height: 50))
label.text = addOns[1].title
yCoordinateForNewContent += 50
scrollView.addSubview(label)
contentSize = CGFloat(addOnContents2.count)
print("content size: \(contentSize)")
contentSize = contentSize * cellSize
tableView2 = UITableView(frame: CGRect(x: 0, y: yCoordinateForNewContent, width: scrollView.frame.width, height: contentSize))
scrollView.addSubview(tableView2)
tableView2.delegate = self
tableView2.dataSource = self
self.tableView2.register(AddOnTableViewCell.self, forCellReuseIdentifier: "AddOnTableViewCell2")
yCoordinateForNewContent += contentSize + 20
tableView2.reloadData()
case 3:
let label = UILabel(frame: CGRect(x: 16, y: yCoordinateForNewContent, width: scrollView.frame.width - 32, height: 50))
label.text = addOns[2].title
yCoordinateForNewContent += 50
scrollView.addSubview(label)
contentSize = CGFloat(addOnContents3.count)
print("content size: \(contentSize)")
contentSize = contentSize * cellSize
tableView3 = UITableView(frame: CGRect(x: 0, y: yCoordinateForNewContent, width: scrollView.frame.width, height: contentSize))
scrollView.addSubview(tableView3)
tableView3.delegate = self
tableView3.dataSource = self
self.tableView3.register(AddOnTableViewCell.self, forCellReuseIdentifier: "AddOnTableViewCell3")
yCoordinateForNewContent += contentSize + 20
tableView3.reloadData()
case 4:
let label = UILabel(frame: CGRect(x: 16, y: yCoordinateForNewContent, width: scrollView.frame.width - 32, height: 50))
label.text = addOns[3].title
yCoordinateForNewContent += 50
scrollView.addSubview(label)
contentSize = CGFloat(addOnContents4.count)
print("content size: \(contentSize)")
contentSize = contentSize * cellSize
tableView4 = UITableView(frame: CGRect(x: 0, y: yCoordinateForNewContent, width: scrollView.frame.width, height: contentSize))
scrollView.addSubview(tableView4)
tableView4.delegate = self
tableView4.dataSource = self
self.tableView4.register(AddOnTableViewCell.self, forCellReuseIdentifier: "AddOnTableViewCell4")
yCoordinateForNewContent += contentSize + 20
tableView4.reloadData()
default:
print("too many tables")
}
count += 1
}
}
And here's the screen with example data:
SimulatorScreen
Any help is greatly appreciated!
Thanks #Naresh for bringing my attention to this. I had declared the label in the AddOnTableViewCell class, but I was creating a label in the cellForRowAt: method, which I was adding as a subview to the cell. I simplified the tables to a single table with an array of arrays to hold the data. I made the following change to my AddOnTableViewCell class:
class AddOnTableViewCell: UITableViewCell {
var titleLabel: UILabel!
init(frame: CGRect, title:String) {
super.init(style: .default, reuseIdentifier: "AddOnTableViewCell")
titleLabel = UILabel(frame: CGRect(x: 16 , y: self.frame.minY + 10, width: self.frame.width - 32, height: 40))
titleLabel.textColor = UIColor.black
titleLabel.text = title
addSubview(titleLabel)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}}
and I simplified my cellForRowAt: method:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let title = tableContents[indexPath.section][indexPath.row]
let cell = AddOnTableViewCell(frame: CGRect(x: 0, y: 0, width: self.view.frame.width, height: cellSize), title: title)
return cell
}
Thanks!
I have a login screen and upon successful login, I'm passing the object details through a navigation controller to side bar menu controller (topView controller). In side bar menu, I have two options and upon switching from other view controller to top view controller, the values are removed(As per my understanding, I'm passing values from loginVC and it may not be holding those values).
As of now side bar menu transistion is working perfectly fine. But when I switch back from AnotherVC to HomeVC , it is not holding the values which are passed from LoginVC.
Can someone help me to solve this.
Below are my code snippets
StoryBoard:
Code Snippets:
On login button click: (LOGIN VC)
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "loginSuccessIdentifier" {
if let navController = segue.destination as? UINavigationController {
if let destinController = navController.topViewController as? HomeViewController {
destinController.loggedInUser = sender as! UserDetails!
}
}
}
}
HOME VC:
var loggedInUser:UserDetails! //UserDetails class is defined separately. Contains variables like id,firstname, lastname etc. I'm displaying those values on HomeVC
override func viewDidLoad() {
super.viewDidLoad()
addSlideMenuButton()
tokenLbl.adjustsFontSizeToFitWidth = true
nameLbl.adjustsFontSizeToFitWidth = true
idLbl.adjustsFontSizeToFitWidth = true
if(loggedInUser != nil)
{
firstLbl.text = loggedInUser.token
secondLbl.text = loggedInUser.lastname
idLbl.text = String(loggedInUser.agentId)
}
}
SIDEBARMENU VC:
protocol SlideMenuDelegate {
func slideMenuItemSelectedAtIndex(_ index : Int32)
}
class MenuViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
#IBOutlet var tblMenuOptions : UITableView!
#IBOutlet var btnCloseMenuOverlay : UIButton!
var arrayMenuOptions = [Dictionary<String,String>]()
var btnMenu : UIButton!
var delegate : SlideMenuDelegate?
override func viewDidLoad() {
super.viewDidLoad()
tblMenuOptions.tableFooterView = UIView()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
updateArrayMenuOptions()
}
func updateArrayMenuOptions(){
arrayMenuOptions.append(["title":"HOME VC", "icon":"Icon1"])
arrayMenuOptions.append(["title":"ANOTHER VC", "icon":"Icon2"])
tblMenuOptions.reloadData()
}
#IBAction func onCloseMenuClick(_ button:UIButton!){
btnMenu.tag = 0
if (self.delegate != nil) {
var index = Int32(button.tag)
if(button == self.btnCloseMenuOverlay){
index = -1
}
delegate?.slideMenuItemSelectedAtIndex(index)
}
UIView.animate(withDuration: 0.3, animations: { () -> Void in
self.view.frame = CGRect(x: -UIScreen.main.bounds.size.width, y: 0, width: UIScreen.main.bounds.size.width,height: UIScreen.main.bounds.size.height)
self.view.layoutIfNeeded()
self.view.backgroundColor = UIColor.clear
}, completion: { (finished) -> Void in
self.view.removeFromSuperview()
self.removeFromParentViewController()
})
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : UITableViewCell = tableView.dequeueReusableCell(withIdentifier: "cellMenu")!
cell.selectionStyle = UITableViewCellSelectionStyle.none
cell.layoutMargins = UIEdgeInsets.zero
cell.preservesSuperviewLayoutMargins = false
cell.backgroundColor = UIColor.clear
let lblTitle : UILabel = cell.contentView.viewWithTag(101) as! UILabel
let imgIcon : UIImageView = cell.contentView.viewWithTag(100) as! UIImageView
imgIcon.image = UIImage(named: arrayMenuOptions[indexPath.row]["icon"]!)
lblTitle.text = arrayMenuOptions[indexPath.row]["title"]!
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let btn = UIButton(type: UIButtonType.custom)
btn.tag = indexPath.row
self.onCloseMenuClick(btn)
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return arrayMenuOptions.count
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1;
}
}
BASE VC: (FOR SLIDE DELEGATE)
class BaseViewController: UIViewController, SlideMenuDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func slideMenuItemSelectedAtIndex(_ index: Int32) {
let topViewController : UIViewController = self.navigationController!.topViewController!
print("View Controller is : \(topViewController) \n", terminator: "")
switch(index){
case 0:
print("HomeVC\n", terminator: "")
self.openViewControllerBasedOnIdentifier("HomeVC")
break
case 1:
print("AnotherVC\n", terminator: "")
self.openViewControllerBasedOnIdentifier("AnotherVC")
break
default:
print("default\n", terminator: "")
}
}
func openViewControllerBasedOnIdentifier(_ strIdentifier:String){
let destViewController : UIViewController = self.storyboard!.instantiateViewController(withIdentifier: strIdentifier)
let topViewController : UIViewController = self.navigationController!.topViewController!
if (topViewController.restorationIdentifier! == destViewController.restorationIdentifier!){
print("Same VC")
} else {
self.navigationController!.pushViewController(destViewController, animated: true)
}
}
//to add slide option button
func addSlideMenuButton(){
let btnShowMenu = UIButton(type: UIButtonType.system)
btnShowMenu.setImage(self.defaultMenuImage(), for: UIControlState())
btnShowMenu.frame = CGRect(x: 0, y: 0, width: 25, height: 25)
btnShowMenu.addTarget(self, action: #selector(BaseViewController.onSlideMenuButtonPressed(_:)), for: UIControlEvents.touchUpInside)
let customBarItem = UIBarButtonItem(customView: btnShowMenu)
self.navigationItem.leftBarButtonItem = customBarItem;
}
func defaultMenuImage() -> UIImage {
var defaultMenuImage = UIImage()
UIGraphicsBeginImageContextWithOptions(CGSize(width: 30, height: 22), false, 0.0)
UIColor.black.setFill()
UIBezierPath(rect: CGRect(x: 0, y: 3, width: 30, height: 1)).fill()
UIBezierPath(rect: CGRect(x: 0, y: 10, width: 30, height: 1)).fill()
UIBezierPath(rect: CGRect(x: 0, y: 17, width: 30, height: 1)).fill()
UIColor.white.setFill()
UIBezierPath(rect: CGRect(x: 0, y: 4, width: 30, height: 1)).fill()
UIBezierPath(rect: CGRect(x: 0, y: 11, width: 30, height: 1)).fill()
UIBezierPath(rect: CGRect(x: 0, y: 18, width: 30, height: 1)).fill()
defaultMenuImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return defaultMenuImage;
}
func onSlideMenuButtonPressed(_ sender : UIButton){
if (sender.tag == 10)
{
// To Hide Menu If it already there
self.slideMenuItemSelectedAtIndex(-1);
sender.tag = 0;
let viewMenuBack : UIView = view.subviews.last!
UIView.animate(withDuration: 0.3, animations: { () -> Void in
var frameMenu : CGRect = viewMenuBack.frame
frameMenu.origin.x = -1 * UIScreen.main.bounds.size.width
viewMenuBack.frame = frameMenu
viewMenuBack.layoutIfNeeded()
viewMenuBack.backgroundColor = UIColor.clear
}, completion: { (finished) -> Void in
viewMenuBack.removeFromSuperview()
})
return
}
sender.isEnabled = false
sender.tag = 10
let menuVC : MenuViewController = self.storyboard!.instantiateViewController(withIdentifier: "MenuViewController") as! MenuViewController
menuVC.btnMenu = sender
menuVC.delegate = self
self.view.addSubview(menuVC.view)
self.addChildViewController(menuVC)
menuVC.view.layoutIfNeeded()
menuVC.view.frame=CGRect(x: 0 - UIScreen.main.bounds.size.width, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height);
UIView.animate(withDuration: 0.3, animations: { () -> Void in
menuVC.view.frame=CGRect(x: 0, y: 0, width: UIScreen.main.bounds.size.width, height: UIScreen.main.bounds.size.height);
sender.isEnabled = true
}, completion:nil)
}
}
For innocuous data that you only want to hold during a single session, you can store it as an instance property in your App Delegate. To read/write you would just create a new reference to the AppDelegate
let appDelegate = UIApplication.shared.delegate as! AppDelegate
appDelegate.yourProperty = "saveStuff"
If you want the data to persist, and it is not a large amount of data, try NSUserDefaults. You just have to make sure your objects conform to the NSCoder protocol.
https://developer.apple.com/reference/foundation/userdefaults
If you want the data to persist, and it is not a large amount of data, and the data should be secure, you should use the keychain services.
https://developer.apple.com/reference/security/1658642-keychain_services
My issue is that the last cell in my TableView is below the screen view and to see it you must scroll up and hold your position. At a neutral position where you dont scroll up, you cant see the last cell. Everything seemed fine until i changed the size of the cells. Here is my code:
class ViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
//MARK : Properties
var tableView = UITableView()
var items: [String] = ["Age", "Gender", "Smoking Hx", "Occup. -Ag", "Family Hx", "Chronic Lung Disease Radiology", "Chronic Lung Disease Hx", "Nodule Border", "Nodule Location", "Satellite Lesions", "Nodule Pattern Cavity", "Nodule Size"]
var navigationBar = NavigationBar()
var gender = GenderView()
override func viewDidLoad() {
super.viewDidLoad()
//Create TableView
tableView.frame = CGRectMake(0, self.view.bounds.height * 0.097, self.view.bounds.width, self.view.bounds.height);
tableView.delegate = self
tableView.dataSource = self
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")
self.view.addSubview(tableView)
//Create Navigation Bar with custom class
self.navigationBar = NavigationBar(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width, height: self.view.bounds.height * 0.097))
self.view.addSubview(navigationBar)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return self.items.count
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell = tableView.dequeueReusableCellWithIdentifier("cell")! as UITableViewCell
cell.textLabel?.text = self.items[indexPath.row]
//Cell wont turn grey when selected
cell.selectionStyle = UITableViewCellSelectionStyle.None
return cell
}
func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return self.view.bounds.height * 0.095
}
func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
print("You selected cell #\(indexPath.row)!")
}
}
The only thing i could think of causing this issue is that instead of me creating a navigation bar, i created a "navigationBar" using a custom UIView() class. I then start the table view at the bottom of the navigation bar. Any idea how to fix this?
Here is the NavigationBar.swift:
class NavigationBar: UIView {
var navigationBar = UIView()
var header = UILabel()
var lineBorder = UIView()
override init(frame: CGRect) {
super.init(frame: frame)
self.frame = frame
setUpView()
}
func setUpView(){
//Create Navigation Bar
navigationBar.frame = CGRectMake(0, 0, self.bounds.width, self.bounds.height)
navigationBar.backgroundColor = UIColor.whiteColor()
self.addSubview(navigationBar)
//Create Line Border
lineBorder.frame = CGRectMake(0, self.bounds.height, self.bounds.width, self.bounds.height * 0.005)
lineBorder.backgroundColor = UIColor.grayColor()
self.addSubview(lineBorder)
header.frame = CGRectMake(0, 0, 200, 200)
header.font = UIFont(name: "Helvetica", size: 17)
header.text = "Nodule Risk Calculator"
//header.backgroundColor = UIColor.blackColor()
self.addSubview(header)
header.translatesAutoresizingMaskIntoConstraints = false
header.centerHorizontallyTo(navigationBar, padding: 0)
header.centerVerticallyTo(navigationBar, padding: 9)
}
func hide(){
self.removeFromSuperview()
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
tableView.frame = CGRectMake(0, self.view.bounds.height * 0.097, self.view.bounds.width, self.view.bounds.height);
has problem. The origin.y is not 0, and you still feed the whole height. So the table view will have some area below the screen
Try this:
tableView.frame = CGRectMake(0, self.view.bounds.height * 0.097, self.view.bounds.width,
self.view.bounds.height - self.view.bounds.height * 0.097);
self.navigationBar = NavigationBar(frame: CGRect(x: 0, y: 0, width: self.view.bounds.width, height: self.view.bounds.height * 0.097))
self.view.addSubview(navigationBar)
var yAxis : Float = self.navigationBar.frame.height
var tblHeight : Float = self.view.bounds.height - yAxis
tableView.frame = CGRectMake(0, yAxis, self.view.bounds.width, tblHeight)
self.view.addSubview(tableView)
tableView.delegate = self
tableView.dataSource = self
tableView.registerClass(UITableViewCell.self, forCellReuseIdentifier: "cell")