Xcode 8.3.2 playground live view rendering doesn't work - ios

This code worked perfectly in previous version of Xcode, but now it doesn't show anything. It is only showing activity indicator that says "Running project"
import UIKit
import PlaygroundSupport
let container = UIView()
container.frame.size = CGSize(width: 215.0, height: 215.0)
var view = UIView()
view.frame.size = CGSize(width: 185.0, height: 185.0)
view.center = container.center
view.layer.cornerRadius = view.frame.size.height/2
view.backgroundColor = UIColor.white
container.addSubview(view)
let scaleAnimation = CABasicAnimation(keyPath: "transform.scale")
scaleAnimation.fromValue = CGFloat(0.6)
scaleAnimation.toValue = CGFloat(1.15)
scaleAnimation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut)
scaleAnimation.isRemovedOnCompletion = false
let opacityAnimation = CABasicAnimation(keyPath: "opacity")
opacityAnimation.fromValue = CGFloat(0.0)
opacityAnimation.toValue = CGFloat(0.1)
opacityAnimation.duration = 1
opacityAnimation.isRemovedOnCompletion = false
opacityAnimation.autoreverses = true;
let circleAnimations: CAAnimationGroup = CAAnimationGroup()
circleAnimations.duration = 2
circleAnimations.repeatCount = HUGE;
circleAnimations.animations = [scaleAnimation, opacityAnimation];
view.layer .add(circleAnimations, forKey: "circleAnimations")
PlaygroundPage.current.liveView = container
PlaygroundPage.current.needsIndefiniteExecution = true
What is wrong with it ?

You need to enable the assistant editor to see the results.
View > Assistant Editor > Show Assistant Editor
Also see here:
iOS Playground doesn't show UI preview

Sometimes closing the playground and restarting Xcode resolves the problem

Related

Swift Scale Animation is not animating view

I would simply like to have a pulsating UIView. For that I have set up this:
let highlightView: UIView = {
let v = UIView()
v.translatesAutoresizingMaskIntoConstraints = false
v.backgroundColor = .lightBlueCustom
v.alpha = 0.9
return v
}()
let scaleAnimation: CABasicAnimation = {
let v = CABasicAnimation(keyPath: "transform.scale")
v.duration = 0.5
v.repeatCount = .infinity
v.autoreverses = true
v.fromValue = 1.0
v.toValue = 1.4
return v
}()
And this is how I call it:
func showHighlightView(viewToHighlight: UIView, height: CGFloat) {
self.view.addSubview(highlightView)
highlightView.heightAnchor.constraint(equalTo: viewToHighlight.heightAnchor).isActive = true
highlightView.widthAnchor.constraint(equalTo: highlightView.heightAnchor).isActive = true
highlightView.centerXAnchor.constraint(equalTo: viewToHighlight.centerXAnchor).isActive = true
highlightView.centerYAnchor.constraint(equalTo: viewToHighlight.centerYAnchor).isActive = true
highlightView.layer.cornerRadius = height/2
highlightView.layer.add(self.scaleAnimation, forKey: "scale")
self.view.bringSubviewToFront(viewToHighlight)
self.view.bringSubviewToFront(highlightView)
}
func showWishIntro() {
showHighlightView(viewToHighlight: self.addWishButton, height: 60)
}
But this is not working. It shows the highlightView correctly but there is no animation. What am I missing here?
ok so I fixed it... it was just a lucky guess but I am calling showWishIntro now in viewDidLayoutSubviews and not it is working as expected. I have no idea why, so if anyone would care to explain just let me know :D I'm happy that it works.

Property “bounds” not found in tableviewCell Class

i need to set top and bottom border in my textField . i am sorry to my lack of knowledge . so any one help me how can i doing workable bounds property this code i set in the tableviewCell class to crated a TextField .
class NewAdressForGustCell : UITableViewCell{
var areaTextField : RightPaddingTextField = {
var textField = RightPaddingTextField()
let topBorder = CALayer()
topBorder.frame = CGRect(0, 0, bounds.size.width, 1)
topBorder.backgroundColor = UIColor.gray.cgColor
textField.layer.addSublayer(topBorder)
let bottomBorder = CALayer()
bottomBorder.frame = CGRect(0, bounds.size.height-1, bounds.size.width, 1)
bottomBorder.backgroundColor = UIColor.gray.cgColor
textField.layer.addSublayer(bottomBorder)
textField.translatesAutoresizingMaskIntoConstraints = false
return textField
}()
}
The problem is that bounds implicitly means self.bounds, and you cannot refer to self (even implicitly) in code where you are in the middle of initializing a property of self, as you are doing here. This makes sense, because at this time self is exactly what does not yet exist: we are still in the middle of initializing it.
One simple workaround is to mark this var areaTextField as lazy. This works because it guarantees that the code will not run until after self has been fully initialized. (Note that you must still refer explicitly to self.)
class NewAdressForGustCell : UITableViewCell{
lazy var areaTextField : RightPaddingTextField = {
var textField = RightPaddingTextField()
let topBorder = CALayer()
topBorder.frame = CGRect(x:0, y:0, width:self.bounds.size.width, height:1)
topBorder.backgroundColor = UIColor.gray.cgColor
textField.layer.addSublayer(topBorder)
let bottomBorder = CALayer()
bottomBorder.frame = CGRect(x:0, y:self.bounds.size.height-1, width:self.bounds.size.width, height:1)
bottomBorder.backgroundColor = UIColor.gray.cgColor
textField.layer.addSublayer(bottomBorder)
textField.translatesAutoresizingMaskIntoConstraints = false
return textField
}()
}

Turn rectangular UIImageView into a circle

My ViewController has an UIImageView (lets name it img) as atribute, and in the beginning, it shows img in full screen, that is, its size is a rectangle similar to the ViewController bounds.
I'd like to do an animation with img, making it become a little circle (not just a rectangle with circular corners) and then move it to some corner of the ViewController.
How can I achieve this? I prefer not to send any code cos Im pretty sure I did it the wrong way (I tried to turn it into a square and then set a cornerRadius (with radius width/2), then making scale and translating position at once, but its a mess and works wrongly, so lets forget it)
Your solution sounds fine to me, but what might be going wrong, is the fact that animating corner radius is not supported by UIView.animateWithDuration as seen in the View Programming Guide for iOS. Therefor, the results are sometimes not whats expected.
You can try out the following code.
func animate() {
//Some properties that needs to be set on UIImageView
self.imageView.clipsToBounds = true
self.imageView.contentMode = .ScaleAspectFill
//Create animations
let cornerRadiusAnim = changeCornerRadiusAnimation()
let squareAnim = makeSquareAnimation()
let boundsAnim = changeBoundsAnimation()
let positionAnim = changePositionAnimation(CGPointMake(300,480))
//Use group for sequenced execution of animations
let animationGroup = CAAnimationGroup()
animationGroup.animations = [cornerRadiusAnim, squareAnim, boundsAnim, positionAnim]
animationGroup.fillMode = kCAFillModeForwards
animationGroup.removedOnCompletion = false
animationGroup.duration = positionAnim.beginTime + positionAnim.duration
imageView.layer.addAnimation(animationGroup, forKey: nil)
}
func makeSquareAnimation() -> CABasicAnimation {
let center = imageView.center
let animation = CABasicAnimation(keyPath:"bounds")
animation.duration = 0.1;
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
animation.fromValue = NSValue(CGRect: imageView.frame)
animation.toValue = NSValue(CGRect: CGRectMake(center.x,center.y,imageView.frame.width,imageView.frame.width))
animation.fillMode = kCAFillModeForwards
animation.removedOnCompletion = false
return animation
}
func changeBoundsAnimation() -> CABasicAnimation {
let animation = CABasicAnimation(keyPath:"transform.scale")
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
animation.fromValue = imageView.layer.mask?.valueForKeyPath("transform.scale")
animation.toValue = 0.1
animation.duration = 0.5
animation.beginTime = 0.1
animation.fillMode = kCAFillModeForwards
animation.removedOnCompletion = false
return animation
}
func changeCornerRadiusAnimation() -> CABasicAnimation {
let animation = CABasicAnimation(keyPath:"cornerRadius")
animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
animation.fromValue = 0
animation.toValue = imageView.frame.size.width * 0.5
animation.duration = 0.1
animation.fillMode = kCAFillModeForwards
animation.removedOnCompletion = false
return animation
}
func changePositionAnimation(newPosition: CGPoint) -> CABasicAnimation {
let animation = CABasicAnimation(keyPath: "position")
animation.fromValue = NSValue(CGPoint: imageView.layer.position)
animation.toValue = NSValue(CGPoint: newPosition)
animation.duration = 0.3
animation.beginTime = 0.6
animation.fillMode = kCAFillModeForwards
animation.removedOnCompletion = false
return animation
}
// try like this, i hope it will work for you.
UIView.animateWithDuration(3, delay: 0.0, options: UIViewAnimationOptions.CurveEaseIn, animations: { () -> Void in
img.layer.masksToBounds = true
img.layer.cornerRadius = img.frame.size.height / 2 // here img must be in square shape (height == width)
}) { (finished : Bool) -> Void in
}
option 1 call below method from code
// UIimageView Circle
class func roundImageView(imageView:UIImageView){
imageView.layer.borderWidth = 1.0
imageView.layer.masksToBounds = false
//imageView.layer.borderColor = UIColor.whiteColor().CGColor
imageView.layer.cornerRadius = imageView.frame.size.width/2
imageView.clipsToBounds = true
}
option 2 make user defined run time attributes from storyboard
view.layer.cornerRadius = 5.0f;
view.layer.masksToBounds = NO;

Animations not working in ios playground

This is my animation method (PreloaderView.swift)
public func performAction(action: PreloaderAction)
{
let highOpacity = CABasicAnimation.init(keyPath: "opacity")
let middleOpacity = CABasicAnimation.init(keyPath: "opacity")
let lowOpacity = CABasicAnimation.init(keyPath: "opacity")
if action == .PreloaderActionNone {
self.thirdShape.removeAllAnimations()
self.firstShape.opacity = 0.3;
self.secondShape.opacity = 0.5
self.thirdShape.opacity = 1.0
} else if action == .PreloaderActionFailure {
UIView.animateWithDuration(2, animations: {
self.thirdShape.strokeColor = UIColor.redColor().CGColor
}) {(completed : Bool) in
self.thirdShape.strokeColor = self.ringColor.CGColor
}
}
if action == .PreloaderActionStart {
highOpacity.fromValue = 0.0
highOpacity.toValue = 1.0
highOpacity.duration = animationDuration
highOpacity.autoreverses = true
highOpacity.repeatCount = .infinity
self.secondShape.addAnimation(highOpacity, forKey: "highOpacity")
middleOpacity.fromValue = 0.0
middleOpacity.toValue = 1.0
middleOpacity.duration = animationDuration
middleOpacity.autoreverses = true
middleOpacity.repeatCount = .infinity
middleOpacity.beginTime = CACurrentMediaTime() + 0.33
self.firstShape.addAnimation(middleOpacity, forKey: "middleOpacity")
lowOpacity.fromValue = 0.0
lowOpacity.toValue = 1.0
lowOpacity.duration = animationDuration
lowOpacity.autoreverses = true
lowOpacity.beginTime = CACurrentMediaTime() + 0.66
lowOpacity.repeatCount = .infinity
self.thirdShape.addAnimation(lowOpacity, forKey: "lowOpacity")
}
}
This is my playground file
and playground in project navigator
Animations work fine on device, but when I use playground animations not working.
Xcode 7, Swift 2
Add
import XCPlayground
at the top of the Playground, then use
XCPlaygroundPage.currentPage.liveView = view
at the bottom of the Playground, where view is the view you want to render.
You also have to open the "Assistant Editor" (in the "View" menu) to see the current live view.
Also, if you're using asynchronous operations, you have to include
XCPlaygroundPage.currentPage.needsIndefiniteExecution = true
in order to use them in a Playground.
Xcode 8, Swift 3
import PlaygroundSupport
PlaygroundPage.current.needsIndefiniteExecution = true
PlaygroundPage.current.liveView = view

CAGroupAnimation does not show animations. Animations work fine when added separately

I am implementing a simple activity indicator using Swift and Core Animation. The core animation loop consists of just two animations. When I add them to the layer directly, they work perfectly. When I add them as a CAAnimationGroup, nothing is happening at all. I am utterly confused by this behaviour, and I've already checked all questions on stackoverflow about CAAnimationGroup, all tutorials on the web, and read official docs many times. I can't figure out what's going on. Please help.
Animations:
let anim1 = CABasicAnimation(keyPath: "strokeEnd")
anim1.fromValue = 0
anim1.toValue = 1.0
anim1.duration = 2.0
anim1.beginTime = CACurrentMediaTime()
let anim2 = CABasicAnimation(keyPath:"strokeStart")
anim2.fromValue = 0
anim2.toValue = 1.0
anim2.duration = 2.0
anim2.beginTime = CACurrentMediaTime() + 2.0
This works perfectly as expected:
shapeLayer.addAnimation(anim1, forKey:nil)
shapeLayer.addAnimation(anim2, forKey:nil)
This does nothing whatsoever to my layer:
let group = CAAnimationGroup()
group.animations = [anim1, anim2]
group.duration = 4.0
shapeLayer.addAnimation(group, forKey: nil)
I made a short demo snippet to be used in Playground: https://gist.github.com/anonymous/6021295eab4e00b813ce. Please see for yourself and help me solve this. (In case you're not sure how to use Playground for prototyping animations: http://possiblemobile.com/2015/03/prototyping-uiview-animations-swift-playground/)
#MDB983's answer looks like it would work, but doesn't explain why.
When you add an animation directly to a layer, it's begin time is based on the current media time.
When you add animations to an animation group, their "local time" is the animation group. A begin time of 0 in an animation group is the beginning of the group, and a beginTime of 1.0 is 1 second into the total animation group, etc. When you add animations to an animation group change your begin times to be zero-based, not starting from CACurrentMediaTime().
Try it this way, seemingly CACurrentMediaTime() + 2.0 is causing an issue
import UIKit
import XCPlayground
let view = UIView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
let shapeLayer = CAShapeLayer()
let size:CGFloat = 52
let rect = CGRect(x: view.bounds.midX - size/2, y: view.bounds.midY-size/2, width: size, height: size)
shapeLayer.path = UIBezierPath(ovalInRect: rect).CGPath
shapeLayer.fillColor = UIColor.clearColor().CGColor
shapeLayer.strokeColor = UIColor.redColor().CGColor
shapeLayer.lineWidth = 3
shapeLayer.strokeStart = 0
shapeLayer.strokeEnd = 0
view.layer.addSublayer(shapeLayer)
XCPShowView("view", view)
let beginTime = CACurrentMediaTime()
let anim1 = CABasicAnimation(keyPath: "strokeEnd")
anim1.fromValue = 0
anim1.toValue = 1
anim1.duration = 2
let anim2 = CABasicAnimation(keyPath:"strokeEnd")
anim2.fromValue = 1
anim2.toValue = 0
anim2.duration = 2
anim2.beginTime = 2
let group = CAAnimationGroup()
group.duration = 4.0
group.removedOnCompletion = true
group.animations = [anim1, anim2]
//shapeLayer.addAnimation(anim1, forKey:nil)
//shapeLayer.addAnimation(anim2, forKey:nil)
shapeLayer.addAnimation(group, forKey: nil)
I know this is an old question but I was doing the same with animation group in swift 4. What I missed is specifying the beginTime for the CAAnimationGroup itself (I assumed that the child animations would follow their beginTime). By default, beginTime is 0.0 for CAAnimationGroup
let group = CAAnimationGroup()
group.beginTime = CACurrentMediaTime() + delay
group.duration = 4.0
group.removedOnCompletion = true
group.animations = [anim1, anim2]

Resources