Button is not clickable in a child viewcontroller - ios

I am trying to make a side menu which reacts to a hamburger icon clicked.
I created another storyboard with a ViewConroller which contains the TableView in it.
I created a ViewController for this storyboard ViewController.
In the First ViewController (which is not a container), I have the following code:
var menuVC: UIViewController!
var isExpanded = false
#IBAction func MenuTapped(_ sender: UIButton) {
isExpanded = !isExpanded
showMenuVC(shouldExpand: isExpanded)
}
func showMenuVC(shouldExpand: Bool) {
if shouldExpand {
// show menu
if menuVC == nil {
print ("ONLY ONCE")
let storyboard = UIStoryboard(name: "Menu", bundle: .main)
menuVC = storyboard.instantiateViewController(withIdentifier: "MenuSB") as! MenuVC
menuVC.view.frame = self.view.frame.offsetBy(dx: view.frame.width, dy: 0)
menuVC.willMove(toParent: self)
self.view.insertSubview(menuVC.view, at: 0)
self.addChild(menuVC)
menuVC.didMove(toParent: self)
}
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .curveEaseInOut, animations: {
self.view.frame.origin.x = 80 - self.view.frame.width
}, completion: nil)
} else {
// hide menu
UIView.animate(withDuration: 0.5, delay: 0, usingSpringWithDamping: 0.8, initialSpringVelocity: 0, options: .curveEaseInOut, animations: {
self.view.frame.origin.x = 0
}, completion: nil)
}
}
The thing is, the TableView is not responding to anything. Not scrolling, not clicking. I also tried a UIButton and it is not clickable.
The problem is, that the first ViewController is active while the MenuVC is not.
It is important to have both of them active, since the hamburger icon in the first ViewController closes the menu, but I need the MenuVC to be active as well.
Any thoughts?

Try to replace this line:
self.view.insertSubview(menuVC.view, at: 0)
with this:
self.view.addSubview(menuVC.view)
since I have no idea about the subviews you have in self.view, because there might be some views on top of your menu which have isUserInteractionEnabled set to true

Related

How to present (popover) view controller without previous view controller moving back (stop weird animation)

When you present (popover) a view controller the previous view controller kind of backs out of the screen. Is there any way to stop that from happenening.
Here is an example of what is happening: https://imgur.com/a/DSKC6vF
And here is an example of what I want to happen: https://imgur.com/a/vyjA1Jv
The only code I'm using for presenting it
let viewController = UIStoryboard(name: "StoryboardName", bundle: nil).instantiateViewController(identifier: "IdentifierName")
self.present(viewController, animated: true, completion: nil)
If you want something like this:
First ViewController:
let sb = UIStoryboard.init(name: "Appointment", bundle: nil)
let popVC = sb.instantiateViewController(withIdentifier: "AppointConfirmationPopUpVC") as! AppointConfirmationPopUpVC
self.addChild(popVC)
popVC.view.frame = self.view.frame
self.view.addSubview(popVC.view)
popVC.didMove(toParent: self)
Second ViewController:
#IBOutlet weak var bottomView: UIView!
viewdidLoad()
{
self.view.backgroundColor = UIColor.black.withAlphaComponent(0.6)
showAnimate()
}
func showAnimate(){
UIView.animate(withDuration: 0.2, delay: 0, options: [.curveEaseIn],
animations: {
self.bottomView.center.y -= self.bottomView.bounds.height
self.bottomView.layoutIfNeeded()
}, completion: nil)
}
func hideAnimate()
{
self.tabBarController?.tabBar.isHidden = false
UIView.animate(withDuration: 0.2, delay: 0, options: [.curveLinear],
animations: {
self.bottomView.center.y += self.bottomView.bounds.height
self.bottomView.layoutIfNeeded()
self.view.center.y += self.view.bounds.height
self.view.layoutIfNeeded()
}, completion: {(_ completed: Bool) -> Void in
})
}

Setting ViewControllers on top of each other with opacity.

I am a new Swift writer who is looking for an answer to a relatively specific question. Please forgive any novice mistakes.
I am trying to create a Pop Up on the screen programmatically that layers two view controllers so that one view controller is visible on the other, with a level of opacity that makes the background visible.
After a transition from my GameViewController see here:
let gameOverVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "gameOverID") as! GameOverViewController
self.addChildViewController(gameOverVC)
gameOverVC.view.frame = self.view.frame
self.view.addSubview(gameOverVC.view)
gameOverVC.didMove(toParentViewController: self)
}
... I instantiate a ViewController of GameOverViewController to fit over the GameViewController. After that I go to my GameOverViewController class and attempt to set the background color to be opaque with the following line of code:
self.view.backgroundColor = UIColor.black.withAlphaComponent(0.8)
The problem is that I end up with is a background that is not opaque, when in reality I would rather the GameViewController to layer on top of the GameViewController with an opaque background to still be able to see the Game.
I also animate with the following within my GameOverViewController:
func showAnimate()
{
self.view.transform = CGAffineTransform(scaleX: 1.3, y: 1.3)
self.view.alpha = 0.0
UIView.animate(withDuration: 0.25, animations: {
self.view.alpha = 1.0
self.view.transform = CGAffineTransform(scaleX: 1.0, y: 1.0)
})
}
func removeAnimate()
{
UIView.animate(withDuration: 0.25, animations: {
self.view.transform = CGAffineTransform(scaleX: 1.3, y: 1.3)
self.view.alpha = 0.0
}, completion: { (finished: Bool) in
if (finished)
{
self.view.removeFromSuperview()
}
})
}
I'm not sure what is the source of my problem is.
Thank you for your help.
change background color of game over view Controller in interface builder like this
Also , take note of that you remove the game viewController's view in this line in removeAnimate func
self.view.removeFromSuperview()
this may cause black background if you do it before showing game over VC
for the view that sits on top, use: overFullScreen and then simply present it.
let topVC = topVC()
topVC.modalPresentationStyle = .overFullScreen
self.present(VCTobePresented, animated: true, completion: nil)

Swift Switching To and FromTable ViewController Issue Using Custom Segue

I have run into an issue when using a custom segue. I have two tableviews that I'm an trying to switch back and forth from. When I click on a cell in tableview1 it should take me to tableview2. I have a button on tableview2 that connects to the exit of the storyboard. From there it should take me back to tableview1 but whenever I press the button, the application crashes with a BAD_ACCESS error.
Here is my custom segue class:
class TableViewSegue: UIStoryboardSegue {
override func perform() {
scale()
}
func scale () {
let toViewcontroller = self.destination
let fromViewcontroller = self.source
let containerView = fromViewcontroller.view.superview
let originalCenter = fromViewcontroller.view.center
toViewcontroller.view.transform = CGAffineTransform(scaleX: 0.05, y: 0.05)
toViewcontroller.view.center = originalCenter
containerView?.addSubview(toViewcontroller.view)
UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseInOut, animations: {
toViewcontroller.view.transform = CGAffineTransform.identity
}, completion: { success in
fromViewcontroller.present(toViewcontroller, animated: false, completion: nil) //The application crashes and highlights this line as the error.
})
}
}
I have implemented this method in my tableViewController1:
#IBAction func prepareForUnwind(segue: UIStoryboardSegue) {
}
Not sure why the tableview2 does not dismiss.
EDIT: The issue had to do with needing a navigation controller.
The problem is that you are presenting the toViewcontroller each time a segue is performed. So the app presents table2 over table1, and then tries again to present table1 over table2 on the unwind.
Modify your custom segue to check - essentially - which direction you're going:
class TableViewSegue: UIStoryboardSegue {
override func perform() {
scale()
}
func scale () {
let toViewcontroller = self.destination
let fromViewcontroller = self.source
let containerView = fromViewcontroller.view.superview
let originalCenter = fromViewcontroller.view.center
toViewcontroller.view.transform = CGAffineTransform(scaleX: 0.05, y: 0.05)
toViewcontroller.view.center = originalCenter
containerView?.addSubview(toViewcontroller.view)
let fromP = fromViewcontroller.presentingViewController
UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseInOut, animations: {
toViewcontroller.view.transform = CGAffineTransform.identity
}, completion: { success in
// if nil, we are presenting a new VC
if fromP == nil {
fromViewcontroller.present(toViewcontroller, animated: false, completion: nil)
} else {
fromViewcontroller.dismiss(animated: false, completion: nil)
}
})
}
}
Note: This is assuming:
you are not trying to push/pop within a UINavigationController ... you'd need to add some other checks to handle that.
you are only going one-level-in, that is, you are not presenting, presenting, presenting, etc. and then trying to unwind.

animateWithDuration Completion block fires over and over again

I've got a little animation going, and when that animation ends I want the App to automatically push the next ViewController on. Well that ViewController gets pushed on like 8 times in a row! Its pretty crazy.
here's the code:
if CGRectIntersectsRect(whichButton.frame, targetZoneImgView.frame) {
panGesture.cancelsTouchesInView = true
let buttonSnapX = UIScreen.mainScreen().bounds.width / 2.0 - 35.0
let buttonSnapY = UIScreen.mainScreen().bounds.height - 122.0
UIView.animateWithDuration(0.75, delay: 0.0,
usingSpringWithDamping: 0.1,
initialSpringVelocity: 0.0,
options: UIViewAnimationOptions.CurveEaseOut,
animations: {
myButton.frame.origin.x = buttonSnapX
myButton.frame.origin.y = buttonSnapY
}, completion: { (finished: Bool) -> Void in
print("Animation done!")
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let coursesScreen = storyBoard.instantiateViewControllerWithIdentifier("coursesScreen") as! CoursesVC
self.navigationController!.pushViewController(coursesScreen, animated: true)
}
)
That print("Animation done!") statement also fires like 8-9 times in a row, so its really got nothing to do with the fact that I'm pushing a ViewController. I took out the ViewController code - and its still happening.
Basically, anything I put in completion is firing a whole bunch of times in a row.
What in the world is going on?
You may enter completion block with false value of finished variable. Just add a basic check:
UIView.animateWithDuration(0.75, delay: 0.0,
usingSpringWithDamping: 0.1,
initialSpringVelocity: 0.0,
options: UIViewAnimationOptions.CurveEaseOut,
animations: {
myButton.frame.origin.x = buttonSnapX
myButton.frame.origin.y = buttonSnapY
}, completion: { (finished: Bool) -> Void in
if finished {
print("Animation done!")
let storyBoard : UIStoryboard = UIStoryboard(name: "Main", bundle:nil)
let coursesScreen = storyBoard.instantiateViewControllerWithIdentifier("coursesScreen") as! CoursesVC
self.navigationController!.pushViewController(coursesScreen, animated: true)
} else {
print("Animating...")
}
}
)

Perform unwind-segue with custom-class

I do not want to use a NavigationController for this.
I have a Segue(Show(Push) with a custom class UIStoryboardSegue) between two ViewControllers. Now i want to "pop" the current ViewController, after some reading i think this is called "unwind segue".
I have a UIButton that is added with code during runtime. How to i add the unwind segue to this button?
How do i use my custom class for the unwind segue animation? :
override func perform()
{
let src = self.sourceViewController
let dst = self.destinationViewController
src.view.superview?.insertSubview(dst.view, belowSubview: src.view)
dst.view.transform = CGAffineTransformMakeTranslation(0, 0)
UIView.animateWithDuration(0.25,
delay: 0.0,
options: UIViewAnimationOptions.CurveEaseInOut,
animations: {
src.view.transform = CGAffineTransformMakeTranslation(src.view.frame.size.width * -1, 0)
},
completion: { finished in
src.presentViewController(dst, animated: false, completion: nil)
}
)
}

Resources