Shadow is not showing for UIStackView - ios

I am trying to give shadow to a UIStackView. My stackview is in a prototypecell having some labels and buttons.
Firstly, I have made a reference of stackview with name UIViewBank in a class that is binded to my custom cell:
class CustChatBankCell: UITableViewCell {
#IBOutlet weak var UIViewBank: UIStackView!
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 in my Controller I am using the extension in:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell:CustChatBankCell = self.tbChat.dequeueReusableCell(withIdentifier: "CustomBankCell") as! CustChatBankCell
cell.UIViewBank.dropShadow()
return cell
}
}
Extension code:
extension UIStackView {
func dropShadow(scale: Bool = true) {
self.layer.masksToBounds = false
self.layer.shadowColor = UIColor.black.cgColor
self.layer.shadowOpacity = 0.5
self.layer.shadowOffset = CGSize(width: -1, height: 501)
self.layer.shadowRadius = 1
self.layer.shadowPath = UIBezierPath(rect: self.bounds).cgPath
self.layer.shouldRasterize = true
self.layer.rasterizationScale = scale ? UIScreen.main.scale : 1
}
}
But shadow is not appearing.

You can't do this because UIStackView is a non-drawing view, meaning that drawRect() is never called and its background color is ignored. Consider placing the UIStackView inside another UIView and giving that view a background color.
From Apple Docs
The UIStackView is a nonrendering subclass of
UIView
; that is, it does not provide any user interface of its own. Instead, it just manages the position and size of its arranged views. As a result, some properties (like
backgroundColor
) have no effect on the stack view. Similarly, you cannot override
layerClass
,
draw(:)
, or draw(:in:).

Related

UIView gradient color not rendered properly in UICollectionView

I have a custom UICollectionViewCell and the problem that I'm facing is rendering the UI right after the cell is being loaded. You can see from the screenshot below, the first cell loads the dimView properly (it has a gradient background color) but any other cell does not.
Worth mentioning is that this view is visible once the user swipe the cell left or right (it creates a flip illusion where it hides an image and shows this view).
If the cell is reused, it's rendered properly, but not when it's initially loaded. Is there another method where I should call this function showDimViewAndCheckmark()??
#IBOutlet weak var backView: UIView!
override func awakeFromNib() {
super.awakeFromNib()
setUI()
}
override func layoutSubviews() {
super.layoutSubviews()
setUI()
}
override func prepareForReuse() {
super.prepareForReuse()
setUI()
}
func setUI() {
coverImageView.clipsToBounds = true
backView.setGradientBackground(colorOne: Colors.purpleDarker, colorTwo: Colors.purpleLight)
backView.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMaxXMaxYCorner]
layer.shadowColor = UIColor.lightGray.cgColor
layer.shadowOffset = CGSize(width:1, height: 1)
layer.shadowRadius = 2.0
layer.shadowOpacity = 1.0
layer.masksToBounds = false
contentView.clipsToBounds = true
contentView.layer.cornerRadius = 10
contentView.layer.maskedCorners = [.layerMaxXMinYCorner, .layerMaxXMaxYCorner]
}
draw(_ rect: CGRect)
Try this method.

Detecting UITableView scroll with viewDidLayoutSubviews causes excessive callbacks

I have a tableView which is a subclass of a Parallax table view I found on Github. Done all table view set up as normal (Deleted some of it since its irrelevant).
class EventDetailTableViewController: ParallaxTableViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Set the image:
self.imageView.image = eventImage
self.navigationController?.navigationBar.setBackgroundImage(UIImage(), forBarMetrics: .Default)
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.translucent = true
}
// MARK: - UITableViewDelegate
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
override
func tableView(tableView: UITableView, estimatedHeightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return UITableViewAutomaticDimension
}
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 4
}
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return 1
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
// SET UP CELL
}
#IBAction func backButtonPressed(sender: AnyObject) {
print("backButtonPressed")
self.navigationController?.navigationBar.translucent = false
self.navigationController?.navigationBar.barTintColor = UIColor(red: 227/255, green: 38/255, blue: 54/255, alpha: 1.0)
self.navigationController?.popViewControllerAnimated(true)
}
} // END OF VIEWCONTROLLER CLASS
Important things to note here is I have made the navigationBar transparent. When backButtonPressed is called, I wish to change back the navigationBar.Color to the color of the previous View Controller (Red). So I have coded that in the backButtonPressed()
Here is the Parallax code I have. Please view the last func moveImage(). I have the simple effect of when the tableview scrolls down far enough to the description the navigationBar appears with the title "Event Description"
class ParallaxTableViewController: UITableViewController {
// Create the UIView
//var bottomFloatingView = UIView()
// Create the UIImageView
let imageView = UIImageView()
// Set the factor for the parallaxEffect. This is overwritable.
var parallaxFactor:CGFloat = 2
// Set the default height for the image on the top.
var imageHeight:CGFloat = 320 {
didSet {
moveImage()
}
}
// Initialize the scrollOffset varaible.
var scrollOffset:CGFloat = 0 {
didSet {
moveImage()
}
}
override func viewDidLoad() {
super.viewDidLoad()
// Set the contentInset to make room for the image.
self.tableView.contentInset = UIEdgeInsets(top: imageHeight, left: 0, bottom: 0, right: 0)
// Change the contentMode for the ImageView.
imageView.contentMode = UIViewContentMode.ScaleAspectFill
// Add the imageView to the TableView and send it to the back.
view.addSubview(imageView)
view.sendSubviewToBack(imageView)
}
override func viewDidLayoutSubviews() {
// Update the image position after layout changes.
moveImage()
}
// Define method for image location changes.
func moveImage() {
let imageOffset = (scrollOffset >= 0) ? scrollOffset / parallaxFactor : 0
let imageHeight = (scrollOffset >= 0) ? self.imageHeight : self.imageHeight - scrollOffset
imageView.frame = CGRect(x: 0, y: -imageHeight + imageOffset, width: view.bounds.width, height: imageHeight)
if imageOffset > 150 {
print("imageOffSet")
self.navigationItem.title = "Event Description"
self.navigationController?.navigationBar.translucent = false
self.navigationController?.navigationBar.barTintColor = UIColor.whiteColor()
self.navigationController?.navigationBar.shadowImage = nil
} else {
print("else")
self.navigationItem.title = ""
self.navigationController?.navigationBar.shadowImage = UIImage()
self.navigationController?.navigationBar.translucent = true
// This is being called after the back button is being pressed. Which means this else function overrides my backButtonPressed() therefore making my navigation bar in the new VC not the correct color.
}
}
}
As you can see in my notes, this else function is being called again after the backButtonPressed() is called. Therefore it does not give me the desired red in the new VC but it leaves it translucent instead. How can I stop this else function being called when the backButtonPressed is being called?
viewDidLayoutSubviews should never be involved in responding to user events. It is an internal lifecycle method that is rarely used unless you're adding or modifying programmatic NSLayoutConstraints to those already added in Storyboard. It is called quite frequently and apparent redundancy.
Use table delegate methods instead. In particular UITableViewDelegate inherits from UIScrollViewDelegate so reference:
UITableView Scroll event
Then query the tableView itself for visibility information e.g. indexPathsForVisibleRows:
https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableView_Class/#//apple_ref/occ/instp/UITableView/indexPathsForVisibleRows
You should not use viewDidLayoutSubviews() like this as BaseZen has explained in his answer.
You can use scrollViewDidScroll to achieve what you want.
Replace this
#IBAction func backButtonPressed(sender: AnyObject) {
print("backButtonPressed")
self.navigationController?.navigationBar.translucent = false
self.navigationController?.navigationBar.barTintColor = UIColor(red: 227/255, green: 38/255, blue: 54/255, alpha: 1.0)
self.navigationController?.popViewControllerAnimated(true)
}
With this
var backButtonWasPressed = false
#IBAction func backPressed(sender: AnyObject) {
print("backButtonPressed")
backButtonWasPressed = true
self.navigationController?.navigationBar.translucent = false
self.navigationController?.navigationBar.barTintColor = UIColor(red: 227/255, green: 38/255, blue: 54/255, alpha: 1.0)
self.navigationController?.popViewControllerAnimated(true)
}
And replace this
override func viewDidLayoutSubviews() {
// Update the image position after layout changes.
moveImage()
}
With this
override func scrollViewDidScroll(scrollView: UIScrollView) {
if !backButtonWasPressed {
moveImage()
}
}
And put backButtonWasPressed = false in your viewDidLoad()

UIImageView and ScrollView weird behaviour

I'm trying to create a imageView Carousel with a PageControl in the titleView. Everything seem to work now, beside the alignment of the images. What am i doing wrong here? Look at the bottom image where it does not seem to fit it all?
Cell
class ImageViewCell: UITableViewCell, UIScrollViewDelegate {
#IBOutlet var imageScroll:UIScrollView?
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
//scrollView
imageScroll!.backgroundColor = UIColor.blackColor()
imageScroll!.autoresizingMask = [UIViewAutoresizing.FlexibleWidth, UIViewAutoresizing.FlexibleHeight]
imageScroll!.showsHorizontalScrollIndicator = false
imageScroll!.showsVerticalScrollIndicator = false
imageScroll!.pagingEnabled = true
imageScroll!.contentMode = UIViewContentMode.Center
imageScroll!.bounces = false
}
override func setSelected(selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
CellForRowAtIndexPath in viewController
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("ImageCell", forIndexPath: indexPath) as! ImageViewCell
cell.imageScroll!.contentSize = CGSizeMake(self.view.frame.width * CGFloat(pageImages.count), 200)
cell.imageScroll!.delegate = self
for (index, element) in pageImages.enumerate() {
let newImage = UIImageView(frame: CGRectMake(CGFloat(index) * self.view.frame.width + 4, 0, self.view.frame.width, 200))
newImage.image = element
cell.imageScroll!.addSubview(newImage)
}
return cell
}
You have to set the clipsToBounds property of the UIImageView to true, this property determines whether subviews are confined to the bounds of the view. You need to set too the contentMode to specify how a view adjusts its content when its size changes to any you want, something like this:
newImage.contentMode = .ScaleAspectFill
newImage.clipsToBounds = true
I hope this help you.

How Do I Initialize Two Instances of NSObject in the same ViewController - Swift

Please bear with me. I'm new to programming and new to StackOverflow. I hope that my question will grant me a warm response for entering the programming community. An acquaintance, whose opinion I trust, told me to post this email to him on StackOverflow.
What do I have to do to get two instances of NSObject to work in the same ViewController? I've initialized an NSObject subclass called SideBar and RightSideBar. They both draw from NSObject. The cells in the menu are called created by a TableViewController I created programatically. I followed a tutorial that did everything programmatically because I didn't know that Storyboard is better for building things.
Below is the code base.
EDITED: Sorry for being long winded. I don't know how to make this any shorter and as complete
===========
****Note the SideBar subclass is the left menu. The RightSideBar class has the same initializer setup and is the right menu. I want to be able to make them both appear on the same ViewController in the same instance of the same ViewController if possible.****
This is the left TableViewController:
import UIKit
//this protocol of the sidebar delegate manages the selection of the item in the row.
protocol SidebarTableViewControllerDelegate {
func sidebarControlDidSelectRow(indexPath: NSIndexPath)
}
class SidebarTableViewController: UITableViewController {
//setting up the delegate and array of menu items.
var delegate:SidebarTableViewControllerDelegate?
var tableData:Array <String> = []
var imageData:[UIImage] = []
// MARK: - Table view data source
//Setting up the number of sections in the menu
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
//Setting up the number of items in the menu
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return tableData.count
}
//Setting up the menu look for the main screen after login.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell? = tableView.dequeueReusableCellWithIdentifier("Cell") as? UITableViewCell
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
//configure the cell...
cell!.backgroundColor = UIColor.clearColor()
cell!.textLabel?.textColor = UIColor.darkTextColor()
let selectedView:UIView = UIView(frame: CGRect(x: 0, y: 0, width: cell!.frame.size.width, height: cell!.frame.size.height))
selectedView.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(0.3)
cell!.selectedBackgroundView = selectedView
}
cell!.textLabel!.text = tableData[indexPath.row]
cell!.imageView!.image = imageData[indexPath.row]
return cell!
}
//Setting up the height for each cell of the table
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 45.0
}
//Setting up the selection of the item in the cell.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
delegate?.sidebarControlDidSelectRow(indexPath)
}
override func viewDidLoad() {
}
override func didReceiveMemoryWarning() {
}
}
This is the right table view controller:
//setting up the RightSidebarControllerDelegate
protocol RightSidebarTableViewControllerDelegate {
func rightSidebarControlDidSelectRow(indexPath: NSIndexPath)
}
class RightSidebarTableViewController: UITableViewController {
//setting up the delegate and array of menu items.
var delegate:RightSidebarTableViewControllerDelegate?
var rightTableData:Array <String> = []
var rightImageData:[UIImage] = []
// MARK: - Table view data source
//Setting up the number of sections in the menu
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 1
}
//Setting up the number of items in the menu
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return rightTableData.count
}
//Setting up the menu look for the main screen after login.
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
var cell:UITableViewCell? = tableView.dequeueReusableCellWithIdentifier("Cell") as? UITableViewCell
if cell == nil {
cell = UITableViewCell(style: UITableViewCellStyle.Default, reuseIdentifier: "Cell")
//configure the cell...
cell!.backgroundColor = UIColor.clearColor()
cell!.textLabel?.textColor = UIColor.darkTextColor()
let selectedView:UIView = UIView(frame: CGRect(x: 0, y: 0, width: cell!.frame.size.width, height: cell!.frame.size.height))
selectedView.backgroundColor = UIColor.blackColor().colorWithAlphaComponent(0.3)
cell!.selectedBackgroundView = selectedView
}
cell!.textLabel!.text = rightTableData[indexPath.row]
cell!.imageView!.image = rightImageData[indexPath.row]
return cell!
}
//Setting up the height for each cell of the table
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
return 45.0
}
//Setting up the selection of the item in the cell.
override func tableView(tableView: UITableView, didSelectRowAtIndexPath indexPath: NSIndexPath) {
delegate?.rightSidebarControlDidSelectRow(indexPath)
}
override func viewDidLoad() {
}
override func didReceiveMemoryWarning() {
}
}
Here is where my problems may start with SideBar:NSObject. This is the left SideBar to be initialized:
import UIKit
#objc protocol SideBarDelegate {
func sideBarDidSelectButtonAtIndex (index: Int)
optional func sideBarWillClose()
optional func sideBarWillOpen()
optional func sideBarWillDeinitialize()
}
//this class sets up the actual sidebar.
class SideBar: NSObject, SidebarTableViewControllerDelegate {
//width of the bar, tableview setup, and views for the sidebar
let barWidth:CGFloat = 175.0
let sideBarTableViewTopInset:CGFloat = 25.0
let sideBarContainerView:UIView = UIView()
let sideBarTableViewController:SidebarTableViewController = SidebarTableViewController()
var originView:UIView!
//var for dynamic effect and controlling the sidebar
var animator:UIDynamicAnimator!
var delegate:SideBarDelegate?
var isSideBarOpen:Bool = false
//initializer for the "SideBar" class.
override init() {
super.init()
}
//initializer for the tableView of menu items.
init(sourceView: UIView, menuItems: Array<String>, menuImages: [UIImage]){
super.init()
//initializing the views and animation for the menu.
originView = sourceView
sideBarTableViewController.tableData = menuItems
sideBarTableViewController.imageData = menuImages
setupSideBar()
animator = UIDynamicAnimator(referenceView: originView)
}
//function for setting up the sidebar.
func setupSideBar () {
//setting up the frame/outline of the side bar.
sideBarContainerView.frame = CGRectMake(-barWidth, originView.frame.origin.y + 45, barWidth, originView.frame.size.height)
//setting up the color of the sidebar.
sideBarContainerView.backgroundColor = UIColor.clearColor()
//disables subviews from being confined to the sidebar.
sideBarContainerView.clipsToBounds = false
//placing the sidebar in the UIView
originView.addSubview(sideBarContainerView)
//adding blur to the menu.
let blurView:UIVisualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: UIBlurEffectStyle.Light))
blurView.frame = sideBarContainerView.bounds
sideBarContainerView.addSubview(blurView)
//setting up controls for the sidebar
sideBarTableViewController.delegate = self
sideBarTableViewController.tableView.frame = sideBarContainerView.bounds
sideBarTableViewController.tableView.clipsToBounds = false
//disabling the scroll feature. Delete to keep the scroll feature.
sideBarTableViewController.tableView.scrollsToTop = false
//This will remove separators in the UITableCell. Delete to keep separators.
sideBarTableViewController.tableView.separatorStyle = UITableViewCellSeparatorStyle.None
//This sets the background color of the sidebar and creates the inset.
sideBarTableViewController.tableView.backgroundColor = UIColor.clearColor()
sideBarTableViewController.tableView.contentInset = UIEdgeInsets(top: sideBarTableViewTopInset, left: 0, bottom: 0, right: 0)
//reloads the sidebar and adds the container view to the sideBarTableViewController.
sideBarTableViewController.tableView.reloadData()
sideBarContainerView.addSubview(sideBarTableViewController.tableView)
}
func showSideBar(shouldOpen: Bool){
animator.removeAllBehaviors()
isSideBarOpen = shouldOpen
//simple if and else statements to define the direction of animation and intensity of animation
let gravityX:CGFloat = (shouldOpen) ? 0.5 : -0.5
let magnitude:CGFloat = (shouldOpen) ? 20 : -20
let boundaryX:CGFloat = (shouldOpen) ? barWidth : -barWidth
//controls the behavior of the animation.
let gravityBehavior: UIGravityBehavior = UIGravityBehavior(items: [sideBarContainerView])
gravityBehavior.gravityDirection = CGVectorMake(gravityX, 0)
animator.addBehavior(gravityBehavior)
let collisionBehavior: UICollisionBehavior = UICollisionBehavior(items: [sideBarContainerView])
collisionBehavior.addBoundaryWithIdentifier("sideBarBoundary", fromPoint: CGPointMake(boundaryX, 20), toPoint: CGPointMake(boundaryX, originView.frame.size.height))
animator.addBehavior(collisionBehavior)
let pushBehavior:UIPushBehavior = UIPushBehavior(items: [sideBarContainerView], mode: UIPushBehaviorMode.Instantaneous)
pushBehavior.magnitude = magnitude
animator.addBehavior(pushBehavior)
let sideBarBehavior:UIDynamicItemBehavior = UIDynamicItemBehavior(items: [sideBarContainerView])
sideBarBehavior.elasticity = 0.3
animator.addBehavior(sideBarBehavior)
}
func sidebarControlDidSelectRow(indexPath: NSIndexPath) {
delegate?.sideBarDidSelectButtonAtIndex(indexPath.row)
}
}
This is the right SideBar:NSObject that will eventually initialize the right menu.
import UIKit
#objc protocol RightSideBarDelegate {
func rightSideBarDidSelectButtonAtIndex (index: Int)
optional func sideBarWillClose()
optional func sideBarWillOpen()
}
class RightSideBar: NSObject, RightSidebarTableViewControllerDelegate {
//width of the bar, tableview setup, and views for the sidebar
let barWidth:CGFloat = 175.0
let rightSideBarTableViewTopInset:CGFloat = 25.0
let rightSideBarContainerView:UIView = UIView()
let rightSideBarTableViewController:RightSidebarTableViewController = RightSidebarTableViewController()
var rightOriginView:UIView!
//var for dynamic effect and controlling the sidebar
var animator:UIDynamicAnimator!
var delegate:RightSideBarDelegate?
var isSideBarOpen:Bool = false
//initializer for the "SideBar" class.
override init() {
super.init()
}
//initializer for the tableView of menu items.
init(rightSourceView: UIView, rightMenuItems: Array<String>, rightMenuImages: [UIImage]){
super.init()
//initializing the views and animation for the menu.
rightOriginView = rightSourceView
rightSideBarTableViewController.rightTableData = rightMenuItems
rightSideBarTableViewController.rightImageData = rightMenuImages
setupSideBar()
animator = UIDynamicAnimator(referenceView: rightOriginView)
}
//function for setting up the sidebar.
func setupSideBar () {
//setting up the frame/outline of the side bar.
rightSideBarContainerView.frame = CGRectMake(rightOriginView.frame.size.width + barWidth , rightOriginView.frame.origin.y + 45, barWidth, rightOriginView.frame.size.height)
//setting up the color of the sidebar.
rightSideBarContainerView.backgroundColor = UIColor.clearColor()
//disables subviews from being confined to the sidebar.
rightSideBarContainerView.clipsToBounds = false
//placing the sidebar in the UIView
rightOriginView.addSubview(rightSideBarContainerView)
//adding blur to the menu.
let blurView:UIVisualEffectView = UIVisualEffectView(effect: UIBlurEffect(style: UIBlurEffectStyle.Light))
blurView.frame = rightSideBarContainerView.bounds
rightSideBarContainerView.addSubview(blurView)
//setting up controls for the sidebar
rightSideBarTableViewController.delegate = self
rightSideBarTableViewController.tableView.frame = rightSideBarContainerView.bounds
rightSideBarTableViewController.tableView.clipsToBounds = false
//disabling the scroll feature. Delete to keep the scroll feature.
rightSideBarTableViewController.tableView.scrollsToTop = false
//This will remove separators in the UITableCell. Delete to keep separators.
rightSideBarTableViewController.tableView.separatorStyle = UITableViewCellSeparatorStyle.None
//This sets the background color of the sidebar and creates the inset.
rightSideBarTableViewController.tableView.backgroundColor = UIColor.clearColor()
rightSideBarTableViewController.tableView.contentInset = UIEdgeInsets(top: rightSideBarTableViewTopInset, left: 0, bottom: 0, right: 0)
//reloads the sidebar and adds the container view to the rightSideBarTableViewController.
rightSideBarTableViewController.tableView.reloadData()
rightSideBarContainerView.addSubview(rightSideBarTableViewController.tableView)
}
func showSideBar(shouldOpen: Bool){
animator.removeAllBehaviors()
isSideBarOpen = shouldOpen
//simple if and else statements to define the direction of animation and intensity of animation
let gravityX:CGFloat = (shouldOpen) ? -0.5 : 0.5
let magnitude:CGFloat = (shouldOpen) ? -20 : 20
let boundaryX:CGFloat = (shouldOpen) ? -barWidth : barWidth
//controls the behavior of the animation.
let gravityBehavior: UIGravityBehavior = UIGravityBehavior(items: [rightSideBarContainerView])
gravityBehavior.gravityDirection = CGVectorMake(gravityX, 0)
animator.addBehavior(gravityBehavior)
let collisionBehavior: UICollisionBehavior = UICollisionBehavior(items: [rightSideBarContainerView])
collisionBehavior.addBoundaryWithIdentifier("sideBarBoundary", fromPoint: CGPointMake(boundaryX, 20), toPoint: CGPointMake(boundaryX, rightOriginView.frame.size.height))
animator.addBehavior(collisionBehavior)
let pushBehavior:UIPushBehavior = UIPushBehavior(items: [rightSideBarContainerView], mode: UIPushBehaviorMode.Instantaneous)
pushBehavior.magnitude = magnitude
animator.addBehavior(pushBehavior)
let sideBarBehavior:UIDynamicItemBehavior = UIDynamicItemBehavior(items: [rightSideBarContainerView])
sideBarBehavior.elasticity = 0.3
animator.addBehavior(sideBarBehavior)
}
func rightSidebarControlDidSelectRow(indexPath: NSIndexPath) {
delegate?.rightSideBarDidSelectButtonAtIndex(indexPath.row)
}
}
Finally this is my current code for the DoubleMenuViewController. Something happens when I segue to the DoubleMenuViewController to break the menus. The menus won't even load. However, if I'm in a SingleMenuViewController that only calls SideBar:NSObject then the code will work so long as I'm only calling one menu. In this DoubleMenuViewController, I have the initialization section commented out for the RightSideBar class because I'm working on a solution. I know this code for this ViewController is garbled. I'm trying everything I can think of. See my remarks after the code to see what I've tried:
import UIKit
class DoubleMenuViewController: UIViewController, SideBarDelegate, RightSideBarDelegate {
var sideBar:SideBar?
var ondemandSideBar:SideBar {
get {
if sideBar == nil {
//setting up the menu items for the sidebar.
sideBar = SideBar(sourceView: self.view, menuItems: ["Home", "Share", "About", "Help"], menuImages: [homeImage!, shareImage!, aboutImage!, helpImage!])
sideBar!.delegate = self
SideBar.new()
}
return sideBar!
}
}
//initializes the "RightSideBar"
var rightSideBar:RightSideBar?
var ondemandRightSideBar:RightSideBar {
get {
if rightSideBar == nil {
rightSideBar = RightSideBar(rightSourceView: self.view, rightMenuItems: [//Other items], rightMenuImages: [//Other Items])
rightSideBar!.delegate = self
RightSideBar.new()
}
return rightSideBar!
}
}
var homeImage = UIImage(named: "Home")
var shareImage = UIImage(named: "Share")
var aboutImage = UIImage(named: "About")
var helpImage = UIImage(named: "Help")
#IBOutlet weak var currentMenuControl: UIBarButtonItem!
#IBAction func currentMenuDisplay(sender: AnyObject) {
if currentMenuControl.tag == 1 {
ondemandSideBar.showSideBar(true)
currentMenuControl.tag = 0
} else {
ondemandSideBar.showSideBar(false)
currentMenuControl.tag = 1
}
}
#IBOutlet weak var progressionMenuControl: UIBarButtonItem!
#IBAction func progressionMenuDisplay(sender: AnyObject) {
if progressionMenuControl.tag == 1 {
ondemandRightSideBar.showSideBar(true)
progressionMenuControl.tag = 0
} else {
ondemandRightSideBar.showSideBar(false)
progressionMenuControl.tag = 1
}
}
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 sideBarDidSelectButtonAtIndex(index: Int) {
switch index {
//segues
}
}
func rightSideBarDidSelectButtonAtIndex(index: Int) {
switch index {
//segues
}
}
}
Here's what I've tried:
I've tried altering the positioning of CGFloats since SubViews seem
to come from the left.
I've renamed all the RightSideBar variables and class names
everything to overcome a runtime confusion in instance variables and
class names. This includes renaming the initializers that you saw in
the NSObject SubClass and the target view controller.
I've tried using control flow in the viewDidLoad method with a
button tag. I took away the swipe features to show the menu and
added buttons because I thought system was struggling to deal with
the Swipes.
I've tried deinitializing in the SideBar subclass file of NSObject.
All that got me was an infinite loop that crashed the application
after login.
Then I tried ondemand initialization in the
targetViewController.....DoubleMenuViewController and
SingleMenuViewController. I returned to a working menu with buttons
in the SingleMenuViewController but it still won't show the left and
right menu in the DoubleMenuViewController.
Last I tried deinitializing the SideBar (left SideBar) and the RightSideBar in the DoubleMenuViewController. However, when I add println() functions to all my sections the debugger doesn't run the print function for me to get values of objects or even show typed states like "This". I added the print functions because I wasn't sure if I would know when deinitialization and reinitialization occurred.
It seems that my menu is initialized from the SideBar: NSObject file and the RightSideBar:NSObject file. What I mean is that my menu is being created before I hit the target view controller. This isn't a problem for me so long as I can get the compiler to initialize the SideBar and the RightSideBar in the same View Controller, but it won't do that.
I just need to be able to control both menus with swipes or button taps.
I think I have a problem with my initializers overriding each other.
However, I don't know how to fix that problem. I've read through the Swift manual and read articles on the internet. I've also searched StackOverflow.
You ask:
How do I Initialize two instances of NSObject in the same view controller?
Setting aside why you're dealing with NSObject at all (in Objective-C all classes have to subclass from NSObject ultimately, in Swift that's no longer the case), if you want to instantiate two objects, you simply have to have one property for each.
If these are lazily instantiated, as your code snippet suggests, then you have to identify where that lazily instantiated property is referenced (e.g. you might trigger it from a "swipe from edge" gesture) or what have you. Set a breakpoint in the code that references that lazily instantiated property and make sure you're getting there at all.
--
I had some observations on one of your code snippets. You say that you're instantiating your side bar like so:
var sideBar : SideBar?
var ondemandSideBar : SideBar {
get {
if sideBar == nil {
sideBar = SideBar(sourceView, menuItems, menuImage etc.)
sideBar!.delegate
SideBar.new()
}
}
}
I don't think that's what you're really doing because you're not setting the delegate, you're both instantiating the SideBar as well as calling new (which you shouldn't be doing from Swift), you're not returning a value, etc.
Also, that pattern of having a stored property that is instantiated by some computed property has a certain Objective-C je ne sais quoi. I'm inferring that you want a lazily instantiated property. If that's the case, I'd be inclined to use a single lazy stored property. And I'd then set that property lazily using a closure:
I'd expect something like this pattern
protocol SideBarDelegate : class { // specify class so we can use `weak` reference
func didChooseMenuItem(sender: SideBar, item: Int)
}
class SideBar {
weak var delegate: SideBarDelegate? // make sure this is weak to avoid strong reference cycle
}
class ViewController: UIViewController, SideBarDelegate {
lazy var sideBar: SideBar = {
let _sideBar = SideBar(sourceView, menuItems, menuImage, etc.)
_sideBar.delegate = self
return _sideBar
}()
func didChooseMenuItem(sender: SideBar, item: Int) {
// handle it here
}
// etc.
}
This way, the sideBar won't be instantiated until you reference sideBar somewhere in your code, but when you do, it will be instantiated with the code inside that closure.

Animate objects in Swift?

In swift, I am transitioning an object in to the view, and I need it to slide in, or fade in. How can I obtain this type of animation in my program?
I have all my view elements made programmatically without IB (Interface Builder)
Is there documentation I can look at for reference? I could not find any.
I'm used to using [UIView animateWithDuration ...], but I found it a bit tricky switching the block syntax over to Swift at first. Here's a quick lazy code:
view.alpha = 0.0
UIView.animateWithDuration(0.25, animations: {
view.alpha = 1.0
}, completion: {
(value: Bool) in
println(">>> Animation done.")
})
Or to animate the position appearing from the left of the screen:
// some variables for the UIView
let width = 200
let height = 100
let yPosition = 10
// create view and position it offscreen to the left
let view = UIView()
// you could have also used the new more verbose Swift way of making a CGRect:
// CGRect(x: xValue, y: yValue, width: widthValue, height: heightValue)
view.frame = CGRectMake(-width, yPosition, width, height)
view.backgroundColor = UIColor.blueColor() // etc...
// animation position over 1.0 second duration
UIView.animateWithDuration(1.0, animations: {
view.frame = CGRectMake(0, yPosition, width, height)
})
If you're completely new to the UIView animation APIs I wrote post that covers a bunch of animation options in swift here: http://mathewsanders.com/prototyping-iOS-iPhone-iPad-animations-in-swift/
Swift 3 & 4
Please Add necessary objects like tableView
import UIKit
class SecondViewController: UIViewController,UITableViewDelegate,UITableViewDataSource {
#IBOutlet var tabl: UITableView!
var name = ["tony","abu"]
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return name.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = UITableViewCell()
cell.textLabel?.text = name[indexPath.row]
return cell
}
override func viewWillAppear(_ animated: Bool) {
tabl.center.x = self.view.frame.width/5
UIView.animate(withDuration: 1.0, delay: 0, usingSpringWithDamping: 1.0, initialSpringVelocity:0.45, options: [], animations: ({
self.tabl.center.x = self.view.frame.width/3
//self.buttonAction.center.x = self.view.frame.width/2
}), completion: nil)
}
}
Apples Core animation seen here https://developer.apple.com/library/Mac/DOCUMENTATION/Cocoa/Conceptual/CoreAnimation_guide/Introduction/Introduction.html
its very fun. youtube it

Resources