Custom UIStoryboardSegue - UIViewController supportedInterfaceOrientations never call - ios

I have a problem creating a custom segue: I'm overriding the "perform()" method as follows
override func perform() {
if !isBack {
self.destinationViewController.view.frame = CGRectMake(self.sourceViewController.view.frame.width, 0, self.sourceViewController.view.frame.width, self.sourceViewController.view.frame.height)
self.sourceViewController.view.addSubview(self.destinationViewController.view)
self.sourceViewController.addChildViewController(self.destinationViewController)
print("Source: \(self.sourceViewController) ---> Destination: \(self.destinationViewController)")
UIView.animateWithDuration(0.5, animations: { () -> Void in
self.destinationViewController.view.frame = CGRectMake(0, 0, self.destinationViewController.view.frame.width, self.destinationViewController.view.frame.height)
}, completion: { (bolean) -> Void in
print("Animation Completed")
})
}else{
print("Source: \(self.sourceViewController) ---> Destination: \(self.destinationViewController)")
UIView.animateWithDuration(0.5, animations: { () -> Void in
self.sourceViewController.view.frame = CGRectMake(self.sourceViewController.view.frame.width, 0, self.sourceViewController.view.frame.width, self.sourceViewController.view.frame.height)
}, completion: { (bolean) -> Void in
print("Animation Completed")
self.sourceViewController.view.removeFromSuperview()
})
}
Everything runs fine but, at this point, the rotation method in "destinationViewController" are not being called. So, if I lock "sourceViewController" to portrait mode while leaving the "destinationViewController" unlocked the latter doesn't rotate.
Assuming the problem resides in this line:
self.sourceViewController.view.addSubview(self.destinationViewController.view)
how should I change the code to fix the rotation?

Ok guy i have find the solution like this.
override func perform() {
if !isBack {
self.destinationViewController.view.frame = CGRectMake(self.sourceViewController.view.frame.width, 0, self.sourceViewController.view.frame.width, self.sourceViewController.view.frame.height)
let window = UIApplication.sharedApplication().keyWindow
window?.insertSubview(self.destinationViewController.view, aboveSubview: self.sourceViewController.view)
print("Source: \(self.sourceViewController) ---> Destination: \(self.destinationViewController)")
UIView.animateWithDuration(0.5, animations: { () -> Void in
self.destinationViewController.view.frame = CGRectMake(0, 0, self.destinationViewController.view.frame.width, self.destinationViewController.view.frame.height)
}, completion: { (bolean) -> Void in
print("Animazione Terminata")
self.sourceViewController.presentViewController(self.destinationViewController, animated: false, completion: nil)
})
}else{
print("Indietro Source: \(self.sourceViewController) ---> Destination: \(self.destinationViewController)")
let snapshot = self.sourceViewController.view.snapshotViewAfterScreenUpdates(false)
snapshot.frame = CGRectMake(0, 0, snapshot.frame.size.width, snapshot.frame.size.height)
self.destinationViewController.view.addSubview(snapshot)
self.sourceViewController.dismissViewControllerAnimated(false, completion: nil)
dispatch_async(dispatch_get_main_queue(), { () -> Void in
UIView.animateWithDuration(0.5, animations: { () -> Void in
snapshot.frame = CGRectMake(self.destinationViewController.view.frame.width, 0, self.destinationViewController.view.frame.width, self.destinationViewController.view.frame.height)
}, completion: { (bolean) -> Void in
print("Animazione Terminata")
snapshot.removeFromSuperview()
})
})
}
}
i have understand that the UIStoryboar in the end doing the same operation like a presentation. So before you have to create the animation, then present. And when you need to dismiss before get a snapshot of screen dismiss source VC without animation (add snap in destination VC before dismiss) and in the end animate the snap.
tnx and buy.
sorry for my bad english but talk is chip i show the code.
Edit: There is a litle imprecision in my code. For prevent problem of animation simply set inside the present o dismiss complanion your animation.

Related

error after migration from swift 1.2 to swift 2

UIView.animateWithDuration(0.2, animations: { () -> Void in
self.layoutIfNeeded()
}) { (finished) -> Void in
.......
.......
}
this code throws this error:
Cannot convert value of type '(_) throws -> Void' to expected argument type '((Bool) -> Void)?'
It seem that you are not closing correctly the parentheses and missing the completion argument.
The most easy way to detect this kind of errors is try to rewrite the method.
Try this:
UIView.animateWithDuration(0.2, animations: { () -> Void in
self.layoutIfNeeded()
}, completion: { (finished) -> Void in
///
})
Write like below code, this will work bcz its working at my side,
UIView.animateWithDuration(0.2, animations: { () -> Void in
//your code here
self.layoutIfNeeded()
}) { (flag : Bool) -> Void in
///
}
This is the code that generates the same xcode, try this.
UIView.animateWithDuration(0.2, animations: {
// Code for animation
}) { (finished: Bool) in
// Code for completion
}

Custom Function's CompletionHandler for Dummies

I searched everywhere on the internet but couldn't really deal with the answers I found. So if someone could help me here, that'd be appreciated.
I wrote a function that looks like this:
func setImage(imageName: String, completion: ((String) -> Void)?) {
UIView.transitionWithView(self.myImageView, duration: 0.3, options: .CurveEaseOut, animations: {
self.lockImageView.image = UIImage(named: "\(imageName).png")
}, completion: { finished in
//execute the completionBlock that was passed
})
}
I call it like this:
setImage("lockCheck", completion: { finished in
print("done")
})
Now, how do I execute whatever was passed as completion?
In the function, in the transition's completion block, I tried something like
for x in completion {self.x}
but that didn't work.
Thanks in advance :)
You could for example execute the completion handler right away in the completionHandler of the animation block like so:
func setImage(imageName: String, completion: ((Bool) -> Void)?) {
UIView.transitionWithView(self.myImageView, duration: 0.3, options: .CurveEaseOut, animations: { () -> Void in
self.lockImageView.image = UIImage(named: "\(imageName).png")
}, completion: completion)
}
You can also run an completion handler with extra parameters like the following (I hope it is clear like this):
func setImage(imageName: String, completion: ((Bool, String) -> Void)?) {
UIView.transitionWithView(self.lockImageView, duration: 0.3, options: .CurveEaseOut, animations: { () -> Void in
self.lockImageView.image = UIImage(named: "\(imageName).png")
}) { (finished) -> Void in
// Do some things for example print
print("Hi, this is the animation completion handler")
// Notice the ? because the completion handler is an optional
completion?(finished, "some string")
}
}

UIView.animateWithDuration in Swift 2.0?

Before explain my problem, it is important to say that I already implemented the suggestion made in this question and I think my doubts about this animateWithDuration method are quite different, despite both questions having a very similar title.
So, I am a Swift newbie and I am doing some small projects in Swift, based on previous Objective C demos that I did before.
This is my Objective C code:
- (void)moveSideBarToXposition: (int) iXposition{
[UIView animateWithDuration:0.5f
delay:0.1
options: UIViewAnimationOptionTransitionNone
animations:^{ self.mainView.frame = CGRectMake(iXposition, 20, self.mainView.frame.size.width, self.mainView.frame.size.height); }
completion:^(BOOL finished){
if (self.isSidebarHidden==YES) {
self.isSidebarHidden = NO;
}
else{
self.isSidebarHidden = YES;
}
}];
}
And this is my Swift version:
func moveSideBarToXposition(iXposition: Float) {
UIView.animateWithDuration(0.5, delay: 1.0, options: UIViewAnimationTransition.None, animations: { () -> Void in
self.contentView.frame = CGRectMake(iXposition, 20, self.contentView.frame.size.width, self.contentView.frame.size.height)
}, completion: { (finished: Bool) -> Void in
if isMenuHidden == true {
isMenuHidden = false
} else {
isMenuHidden = true
}
})
}
And I get this error.
Cannot invoke 'animateWithDuration' with an argument list of type
'(Double, delay: Double, options: UIViewAnimationTransition,
animations: () -> Void, completion: (Bool) -> Void)'
I read the documentation but actually I am not sure what the problem is.
Btw, i am working on Xcode 7 and Swift 2.0
You are passing enum of type UIViewAnimationTransition to an argument which requires type UIViewAnimationOptions (options argument)
Here is the correct syntax with the correct enum value:
func moveSideBarToXposition(iXposition: Float) {
let convertedXposition = CGFloat(iXposition)
UIView.animateWithDuration(0.5, delay: 1.0, options: UIViewAnimationOptions.TransitionNone, animations: { () -> Void in
self.contentView.frame = CGRectMake(convertedXposition, 20, self.contentView.frame.size.width, self.contentView.frame.size.height)
}, completion: { (finished: Bool) -> Void in
// you can do this in a shorter, more concise way by setting the value to its opposite, NOT value
isMenuHidden = !isMenuHidden
})
}

How to pass (optional) completion handler closure to transitionFromViewController in Swift?

In a ViewController in my app I call transitionFromViewController but always get the following error when passing in a closure to the completion: argument.
Type '() -> Void' does not conform to protocol 'NilLiteralConvertible'
Here's the function call:
self.transitionFromViewController(
self.currentVC,
toViewController: newController,
duration: 0.2,
options: UIViewAnimationOptions.TransitionCrossDissolve,
nil,
completion: { finished in
fromViewController.removeFromParentViewController()
toViewController.didMoveToParentViewController(containerViewController)
toViewController.view.frame = containerViewController.view.bounds
})
According to code completion the method signature is as follows:
transitionFromViewController(fromViewController: UIViewController, toViewController: UIViewController, duration: NSTimeInterval, options: UIViewAnimationOptions, animations: () -> Void(), completion: ((Bool) -> Void)?)
You cannot pass nil to animations paramere () -> Void() declared as not optional
Pass empty closure if you want
self.transitionFromViewController(
self.currentVC,
toViewController: newController,
duration: 0.2,
options: UIViewAnimationOptions.TransitionCrossDissolve,
animations: { () -> Void in
},
completion: { finished in
fromViewController.removeFromParentViewController()
toViewController.didMoveToParentViewController(containerViewController)
toViewController.view.frame = containerViewController.view.bounds
})
I think following code should help you :
self.transitionFromViewController(fromViewController, toViewController: toViewController, duration: 0.1, options: UIViewAnimationOptions.CurveEaseInOut, animations: { () -> Void in
// code for animations
}) { (value: Bool) -> Void in
// code after completion
}
Where, // code for animations - code you want to execute during the block.
And, // code after completion - code you want to execute after the completion of the block.

Blocks on Swift (animateWithDuration:animations:completion:)

I'm having trouble making the blocks work on Swift. Here's an example that worked (without completion block):
UIView.animateWithDuration(0.07) {
self.someButton.alpha = 1
}
or alternatively without the trailing closure:
UIView.animateWithDuration(0.2, animations: {
self.someButton.alpha = 1
})
but once I try to add the completion block it just won't work:
UIView.animateWithDuration(0.2, animations: {
self.blurBg.alpha = 1
}, completion: {
self.blurBg.hidden = true
})
The autocomplete gives me completion: ((Bool) -> Void)? but not sure how to make it work. Also tried with trailing closure but got the same error:
! Could not find an overload for 'animateWithDuration that accepts the supplied arguments
Update for Swift 3 / 4:
// This is how I do regular animation blocks
UIView.animate(withDuration: 0.2) {
<#code#>
}
// Or with a completion block
UIView.animate(withDuration: 0.2, animations: {
<#code#>
}, completion: { _ in
<#code#>
})
I don't use the trailing closure for the completion block because I think it lacks clarity, but if you like it then you can see Trevor's answer below.
The completion parameter in animateWithDuration takes a block which takes one boolean parameter. In Swift, like in Obj-C blocks, you must specify the parameters that a closure takes:
UIView.animateWithDuration(0.2, animations: {
self.blurBg.alpha = 1
}, completion: {
(value: Bool) in
self.blurBg.hidden = true
})
The important part here is the (value: Bool) in. That tells the compiler that this closure takes a Bool labeled 'value' and returns Void.
For reference, if you wanted to write a closure that returned a Bool, the syntax would be
{(value: Bool) -> bool in
//your stuff
}
The completion is correct, the closure must accept a Bool parameter: (Bool) -> (). Try
UIView.animate(withDuration: 0.2, animations: {
self.blurBg.alpha = 1
}, completion: { finished in
self.blurBg.hidden = true
})
Underscore by itself alongside the in keyword will ignore the input
Swift 2
UIView.animateWithDuration(0.2, animations: {
self.blurBg.alpha = 1
}, completion: { _ in
self.blurBg.hidden = true
})
Swift 3, 4, 5
UIView.animate(withDuration: 0.2, animations: {
self.blurBg.alpha = 1
}, completion: { _ in
self.blurBg.isHidden = true
})
There is my solution above based on accepted answer above. It fades out a view and hiddes it once almost invisible.
Swift 2
func animateOut(view:UIView) {
UIView.animateWithDuration (0.25, delay: 0.0, options: UIViewAnimationOptions.CurveLinear ,animations: {
view.layer.opacity = 0.1
}, completion: { _ in
view.hidden = true
})
}
Swift 3, 4, 5
func animateOut(view: UIView) {
UIView.animate(withDuration: 0.25, delay: 0.0, options: UIView.AnimationOptions.curveLinear ,animations: {
view.layer.opacity = 0.1
}, completion: { _ in
view.isHidden = true
})
}
Here you go, this will compile
Swift 2
UIView.animateWithDuration(0.3, animations: {
self.blurBg.alpha = 1
}, completion: {(_) -> Void in
self.blurBg.hidden = true
})
Swift 3, 4, 5
UIView.animate(withDuration: 0.3, animations: {
self.blurBg.alpha = 1
}, completion: {(_) -> Void in
self.blurBg.isHidden = true
})
The reason I made the Bool area an underscore is because you not using that value, if you need it you can replace the (_) with (value : Bool)
Sometimes you want to throw this in a variable to animate in different ways depending on the situation. For that you need
let completionBlock : (Bool) -> () = { _ in
}
Or you could use the equally verbose:
let completionBlock = { (_:Bool) in
}
But in any case, you have have to indicate the Bool somewhere.
SWIFT 3.x + 4.x
I'd like to make an update and simplify the things.
Example below is implemented in any view it is hiding slowly and when it is completely transparent; removes it self from parent view
ok variable will always returns true with animation termination.
alpha = 1
UIView.animate(withDuration: 0.5, animations: {
self.alpha = 0
}) { (ok) in
print("Ended \(ok)")
self.removeFromSuperview()
}

Resources