Johan Enstam Johan Enstam - 2 months ago 40
Swift Question

Error "Optional type" when converting to Swift 3 syntax

When converting my project to the Swift 3 syntax I ran into several errors and was able to solve all but one.

The error message I'm getting is:

"Initializer for conditional binding must have Optional type, not 'UIView'"


Here is the code(I'm using Yalatis cocoapod ColorMatchTabs):

public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) {
self.transitionContext = transitionContext

guard let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to),
let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from),
let containerView = transitionContext.containerView else {
return
}
containerView.addSubview(toViewController.view)

let needShow = mode == .show
if !needShow {
containerView.addSubview(fromViewController.view)
}

let animatedViewController = needShow ? toViewController : fromViewController
let initialRect = CGRect(origin: startPoint, size: CGSize.zero)
let initialCircleMaskPath = UIBezierPath(ovalIn: initialRect)
let extremePoint = CGPoint(x: startPoint.x, y: animatedViewController.view.bounds.height)
let radius = hypot(extremePoint.x, extremePoint.y)
let finalCircleMaskPath = UIBezierPath(ovalIn: initialRect.insetBy(dx: -radius, dy: -radius))

let maskLayer = CAShapeLayer()
maskLayer.path = needShow ? finalCircleMaskPath.cgPath : initialCircleMaskPath.cgPath
animatedViewController.view.layer.mask = maskLayer

let maskLayerAnimation = CABasicAnimation(keyPath: "path")
maskLayerAnimation.fromValue = initialCircleMaskPath.cgPath
maskLayerAnimation.fromValue = needShow ? initialCircleMaskPath.cgPath : finalCircleMaskPath.cgPath
maskLayerAnimation.toValue = needShow ? finalCircleMaskPath.cgPath : initialCircleMaskPath.cgPath

maskLayerAnimation.duration = transitionDuration(using: transitionContext)
maskLayer.add(maskLayerAnimation, forKey: "path")
}


This is were it fails:

guard let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to),
let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from),
let containerView = transitionContext.containerView else {
return
}


And the error message appears here:

let containerView = transitionContext.containerView else {
return
}


I'm not very good at swift yet, obviously not good enough to solve this error. I'm grateful for all the help I can get!

Answer

transitionContext.containerView is not an optional, you don't need to put it inside a guard-let statement because it will always have a value

Replace this:

guard let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to),
let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from),
    let containerView = transitionContext.containerView else {
    return
}

with

guard let toViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.to),
let fromViewController = transitionContext.viewController(forKey: UITransitionContextViewControllerKey.from) else {
    return
}
let containerView = transitionContext.containerView