I'm trying to get a Live View to show a simple animation in a Swift Playground. Whenever I import the XCPlayground framework to execute the XCPShowView function i get this error:
Playground execution failed: error: Couldn't lookup symbols:_CGPointMake
The error changes for a few other "symbols" as well, including CGRectMake.
After being advised to modifying my code to remove the "make" from methods such as CGRectMake I still get an error from Xcode when I try to animate my view. The error message is really long, but basically it says
"Unable to simultaneously satisfy constraints.
Probably at least one of the constraints in the following list is one you don't want."
Here is the code I am trying to work with:
//Circle Button
class timerButtonGraphics: UIView {
override func drawRect(rect: CGRect) {
let colorGreen = UIColor(red: 0.310, green: 0.725, blue: 0.624, alpha: 1.000)
let colorRed = UIColor(red: 241/255, green: 93/255, blue: 79/255, alpha: 100)
var bounds = self.bounds
var center = CGPoint()
center.x = bounds.origin.x + bounds.size.width / 2
center.y = bounds.origin.y + bounds.size.height / 2
var radius = 61
var path:UIBezierPath = UIBezierPath()
path.addArcWithCenter(center, radius: CGFloat(radius), startAngle: CGFloat(0.0), endAngle: CGFloat(Float(M_PI) * 2.0), clockwise: true)
path.strokeWithBlendMode(kCGBlendModeNormal, alpha: 100)
path.lineWidth = 2
if strokeRed == true {
colorRed.setStroke()
}
else {
colorGreen.setStroke()
}
path.stroke()
}
var strokeRed = true
}
var test = timerButtonGraphics(frame: CGRect(x: 0, y: 400, width: 400, height: 400))
UIView.animateWithDuration(2.0, delay: 2, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.5, options: nil, animations: {
test.transform = CGAffineTransformMakeTranslation(0.5, 0)
}, completion: nil)
XCPShowView("Circle Animation", test)
try with this, maybe it can help you
test.setTranslatesAutoresizingMaskIntoConstraints(false)
Related
I am aiming to make a program in which I am using using SwiftUI buttons to update by SCNView in SceneKit. I have a cylinder as a SCNCylinder in my SCNView inside a frame in SwiftUI. I want my cylinder to rotate about 180° after I press the button. In my current code I have used #State and #Binding to update the view. But somehow the cylinder rotates as soon as I run the code, not waiting for me to touch the button. Not sure why this happens
Here is my code :
struct ContentView: View {
#State var rotationAngle: Float = 180
var body: some View {
VStack{
Button(action: {
// What to perform
self.rotationAngle = 180
}) {
// How the button looks like
Text("180°")
.frame(width: 100, height: 100)
.position(x: 225, y: 500)
}
SceneKitView(angle: self.$rotationAngle)
.frame(width: 300, height: 300)
.position(x: 225, y: 0)
}
}
}
struct SceneKitView: UIViewRepresentable {
#Binding var angle: Float
func degreesToRadians(_ degrees: Float) -> CGFloat {
return CGFloat(degrees * .pi / 180)
}
func makeUIView(context: UIViewRepresentableContext<SceneKitView>) -> SCNView {
let sceneView = SCNView()
sceneView.scene = SCNScene()
sceneView.allowsCameraControl = true
sceneView.autoenablesDefaultLighting = true
sceneView.backgroundColor = UIColor.white
sceneView.frame = CGRect(x: 0, y: 10, width: 0, height: 1)
return sceneView
}
func updateUIView(_ sceneView: SCNView, context: UIViewRepresentableContext<SceneKitView>) {
let cylinder = SCNCylinder(radius: 0.02, height: 2.0)
let cylindernode = SCNNode(geometry: cylinder)
cylindernode.position = SCNVector3(x: 0, y: 0, z: 0)
cylinder.firstMaterial?.diffuse.contents = UIColor.green
cylindernode.pivot = SCNMatrix4MakeTranslation(0, -1, 0)
let rotation = SCNAction.rotate(by: self.degreesToRadians(self.angle), around: SCNVector3(1, 0, 0), duration: 5)
sceneView.scene?.rootNode.addChildNode(cylindernode)
cylindernode.runAction(rotation)
}
typealias UIViewType = SCNView
}
I want the cylinder to rotate after I press the button. Please help me with this problem.
just set startingAngle to 0
#State var rotationAngle: Float = 0
I have a popup view, that I would like to populate with ~15 UISwitches. Now it would be stupid to do all of that manually, so in Android I have set up a for loop to create said UISwitches from an array and you are able to toggle each one on and off and so on, each having their own value. I have created one switch, but when trying to create multiple from an array, none show up and I have no idea how I would be able to position them one after another.
let mySwitch = UISwitch()
mySwitch.isOn = false
mySwitch.center = self.view.center
mySwitch.thumbTintColor = UIColor(red: 23.0/255, green: 145.0/255, blue: 255.0/255, alpha: 1.0)
mySwitch.tintColor = UIColor(red: 23.0/255, green: 145.0/255, blue: 255.0/255, alpha: 1.0)
mySwitch.onTintColor = UIColor.black
mySwitch.backgroundColor = UIColor.white
self.view.addSubview(mySwitch)
var scrol = UIScrollView()
override func viewDidLoad() {
super.viewDidLoad()
scrol.frame = CGRect(x: 10, y: 0, width: self.view.frame.size.width, height: 200)
var yPos = 0.0
for i in 0...10 {
let mySwitch = UISwitch()
mySwitch.frame = CGRect(x: 10, y: yPos + 10, width: 50, height: 25)
mySwitch.isOn = false
// mySwitch.center = self.view.center
mySwitch.tag = i
mySwitch.thumbTintColor = UIColor(red: 23.0/255, green: 145.0/255, blue: 255.0/255, alpha: 1.0)
mySwitch.tintColor = UIColor(red: 23.0/255, green: 145.0/255, blue: 255.0/255, alpha: 1.0)
mySwitch.onTintColor = UIColor.black
mySwitch.backgroundColor = UIColor.white
yPos = Double(mySwitch.frame.origin.y + mySwitch.frame.size.height)
mySwitch.addTarget(self, action: #selector(onSwitchChange(_:)), for: .touchUpInside)
scrol.addSubview(mySwitch)
}
scrol.backgroundColor = .yellow
scrol.isScrollEnabled = true
self.view.addSubview(scrol)
}
func onSwitchChange(_ sender: UISwitch) {
print(" switch tapped \(sender.tag)")
}
Check out this, i have added a scrollView inside a UIView and have added multiple UISwitch as you have given in code with Frame set for UISwitch.
I'd recommend looking at UIStackView.
This allows you to easily add multiple UI elements to the screen at consistent positions without any hassle.
First you'd want to create a stack view:
let stackView = UIStackView()
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.spacing = 10
add it and constrain it:
view.addSubview(stackView)
NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: view.topAnchor),
// etc, etc
])
Then you'd simply add a series of switches to the stack view:
for i in 0..<10 {
let switch = UISwitch()
// Configure switch
stackView.addArrangedSubview(switch)
}
I have an animation that deletes a circle in the UI and then recreates it somewhere else, but when I recreate it, it is smaller than what I want. I can't figure out why it is appearing smaller.
let viewsToAnimate = [circleFrame]
UIView.perform(UISystemAnimation.delete, on: viewsToAnimate, options: [], animations: {
}, completion: { finished in
self.circle.removeFromSuperlayer()
self.circleFrame.removeFromSuperview()
self.circleFrame.layer.removeAllAnimations()
self.createCircle()
self.score = self.score + 1
self.scoreLabel.text = "Taps: " + String(self.score)
self.tapsLabel.text = "Taps: " + String(self.initialTaps + self.score)
})
func createCircle() {
let randomX = generateRandomX()
let randomY = generateRandomY()
circleCenter = generateCircleCenter(x: randomX, y: randomY)
circleFrame.frame = CGRect(x: randomX, y: randomY, width: 100, height: 100)
circleFrame.alpha = 1.0
self.view.addSubview(circleFrame)
circle.path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: 100, height: 100), cornerRadius: 50).cgPath
circle.fillColor = UIColor(red: 0, green: greenValue/255, blue: 0.6, alpha: 1.0).cgColor
circle.strokeColor = UIColor(red: 1, green: greenValue/255, blue: 0, alpha: 1.0).cgColor
circle.lineWidth = 0
circleFrame.layer.addSublayer(circle)
}
I have tried removing all the animations among other things but it always appears smaller. Any help on why this happens would be great.
Here is how it looks the first time createCircle() is called.
This is how it looks when it is called from the animation.
I think is enough to set removedOnCompletion to true, so CAAnimation will reset to original size.
Give a try ! :)
I've been working on an app for over a month and have many variables defined at the top of the Swift document that came with my tabbed interface template in XCODE. I've declared various UIColors to be used globally and have made a few classes where I draw a few different icon shapes. All of a sudden today Xcode is throwing up red errors of "Use of unresolved identifier [one of my UIColor variabls]" for all of my colors used throughout my drawing classes. I've tried to clean the project and restart Xcode Any idea what could be going on?
Here are my global variables:
import Foundation
import UIKit
import QuartzCore
//----Global Variables----
var timerMode = "start"
var arrowButtonTapped = false
var timerButtonTouched = false
var currentView = "brew it"
//--------My Colors -----------
let colorGreen = UIColor(red: 0.310, green: 0.725, blue: 0.624, alpha: 1.000)
let colorLightGreen = UIColor(red: 211/255, green: 217/255, blue: 195/255, alpha: 100)
var colorRed = UIColor(red: 241/255, green: 93/255, blue: 79/255, alpha: 100)
let colorDarkBlue = UIColor(red: 27/255, green: 29/255, blue: 38/255, alpha: 1.0)
let colorOrange = UIColor(red: 241/255, green: 162/255, blue: 128/255, alpha: 1.0)
let colorTransparent = UIColor(red: 241/255, green: 162/255, blue: 128/255, alpha: 0.0)
//----Countdown times----
var countTime : NSTimeInterval = 6
var halfCountTime : NSTimeInterval = countTime * 0.5
var okCountTime : NSTimeInterval = 2
//---- End Global Variables ----
//let cup1Graphic = coffeeMugVector()
//let cup2Graphic = coffeeMugVector()
//let cup3Graphic = coffeeMugVector()
//let cup4Graphic = coffeeMugVector()
//let cup5Graphic = coffeeMugVector()
//let cup6Graphic = coffeeMugVector()
//Coffe Cups x Coffee Strength returns amount of coffee as an integer
class coffeeCalculator {
var selectedCups = 0
var cupSelect = false
let coffeeStronger = 20
var coffeeStrength = 15
let coffeeWeaker = 15
var water = 226
//var cupAnimation = CSAnimationView(type:"morph", duration:0.5, delay:0)
// What to do when a cup is selected
func cupSelected() {
if cupSelect == true{
selectedCups++
}
else if selectedCups > 0{
selectedCups--
}
println("\(selectedCups)")
}
//take coffee cups multiplied by coffee strength and return the amount as a string
//Calcualte coffee and return an attributed string
func coffeeTextOnly() ->String {
var calculatedCoffee = selectedCups * coffeeStrength
var coffeeToString = "\(calculatedCoffee)"
return coffeeToString
}
func calculateCoffee() -> (NSMutableAttributedString) {
var calculatedCoffee = selectedCups * coffeeStrength
var coffeeToString = "\(calculatedCoffee)"
//Convert the CoffeeCalculator output to an attributed string
var coffeeText = NSMutableAttributedString(string:coffeeToString)
//Part 2 set the font attributes for the lower case g
var coffeeTypeFaceAttributes = [NSFontAttributeName : UIFont.systemFontOfSize(18)]
//Part 3 create the "g" character and give it the attributes that you set up
var coffeeG = NSMutableAttributedString(string:"g", attributes:coffeeTypeFaceAttributes)
coffeeText.appendAttributedString(coffeeG)
return (coffeeText)
}
//Calculate teh amount of water needed and return it as a string
func calculateWater() -> (NSMutableAttributedString) {
var calculatedWater = water * selectedCups
var waterToString = "\(calculatedWater)"
var waterText = NSMutableAttributedString(string:waterToString)
//Part 2 set the font attributes for the lower case g
var waterTypeFaceAttributes = [NSFontAttributeName : UIFont.systemFontOfSize(18)]
//Part 3 create the "g" character and give it the attributes that you set up
var waterG = NSMutableAttributedString(string:"g", attributes:waterTypeFaceAttributes)
waterText.appendAttributedString(waterG)
return (waterText)
}
}
////----BEGIN GRAPHICS ----////
//----Main Timer (circle) Button----//
#IBDesignable
class timerButtonGraphics: UIView {
override func drawRect(rect: CGRect) {
var bounds = self.bounds
var center = CGPoint()
center.x = bounds.origin.x + bounds.size.width / 2
center.y = bounds.origin.y + bounds.size.height / 2
var radius = 31
var path:UIBezierPath = UIBezierPath()
path.addArcWithCenter(center, radius: CGFloat(radius), startAngle: CGFloat(0.0), endAngle: CGFloat(Float(M_PI) * 2.0), clockwise: true)
path.strokeWithBlendMode(kCGBlendModeNormal, alpha: 0)
path.lineWidth = 1
if timerMode == "reset" || timerMode == "ok" {
colorRed.setStroke()
colorRed.setFill()
}
else {
colorGreen.setStroke()
colorGreen.setFill()
}
if timerButtonTouched == true {
path.lineWidth = 2
path.fill()
}
path.stroke()
}
}
//------Arrow Button------//
#IBDesignable
class arrowButtonGraphic: UIView {
override func drawRect(rect: CGRect) {
var bezierPath = UIBezierPath()
bezierPath.moveToPoint(CGPointMake(20.36, 2.68))
bezierPath.addLineToPoint(CGPointMake(2.69, 20.23))
bezierPath.addCurveToPoint(CGPointMake(2.69, 28.32), controlPoint1: CGPointMake(0.44, 22.46), controlPoint2: CGPointMake(0.44, 26.09))
bezierPath.addCurveToPoint(CGPointMake(10.84, 28.32), controlPoint1: CGPointMake(4.94, 30.56), controlPoint2: CGPointMake(8.59, 30.56))
bezierPath.addLineToPoint(CGPointMake(22.71, 16.53))
bezierPath.addCurveToPoint(CGPointMake(26.29, 16.53), controlPoint1: CGPointMake(23.7, 15.55), controlPoint2: CGPointMake(25.3, 15.56))
bezierPath.addLineToPoint(CGPointMake(38.16, 28.32))
bezierPath.addCurveToPoint(CGPointMake(46.31, 28.32), controlPoint1: CGPointMake(40.41, 30.56), controlPoint2: CGPointMake(44.06, 30.56))
bezierPath.addCurveToPoint(CGPointMake(46.31, 20.23), controlPoint1: CGPointMake(48.56, 26.09), controlPoint2: CGPointMake(48.56, 22.46))
bezierPath.addLineToPoint(CGPointMake(28.64, 2.68))
bezierPath.addCurveToPoint(CGPointMake(24.48, 1), controlPoint1: CGPointMake(27.49, 1.54), controlPoint2: CGPointMake(25.98, 0.98))
bezierPath.addCurveToPoint(CGPointMake(20.36, 2.68), controlPoint1: CGPointMake(22.99, 0.99), controlPoint2: CGPointMake(21.5, 1.55))
bezierPath.closePath()
bezierPath.miterLimit = 4;
colorGreen.setStroke()
bezierPath.lineWidth = 1
bezierPath.stroke()
colorGreen.setFill()
//Rotate arrow if on "weigh it" page
if arrowButtonTapped == true {
bezierPath.lineWidth = 2
bezierPath.stroke()
}
}
}
//----Timer Baground Circle ----//
#IBDesignable
class timerBackgroundCircle: UIView {
override func drawRect(rect: CGRect) {
var ovalPath = UIBezierPath(ovalInRect: CGRectMake(0, 0, 238, 238))
colorLightGreen.setFill()
ovalPath.fill()
}
}
//----Timer Bagkround Mask ----//
#IBDesignable
class timerMask: UIView {
override func drawRect(rect: CGRect) {
let colorGreen = UIColor(red: 0.310, green: 0.725, blue: 0.624, alpha: 1.000)
let colorRed = UIColor(red: 241/255, green: 93/255, blue: 79/255, alpha: 100)
let colorLightGreen = UIColor(red: 211/255, green: 217/255, blue: 195/255, alpha: 100)
//The shape to mask out
/*var ovalPath = UIBezierPath(ovalInRect: CGRect(x: 0, y: 0, width: 238, height: 238))
colorGreen.setFill()
ovalPath.fill()*/
//The rectangle
var bounds : CGRect = self.bounds
var maskRect = CAShapeLayer()
maskRect.frame = bounds
//maskRect.fillColor = colorLightGreen.CGColor
//The circle mask
var maskCirclePath = UIBezierPath(ovalInRect: CGRect(x: 40, y: 150, width: 238, height: 238))
maskCirclePath.appendPath(UIBezierPath(rect: bounds))
//combine appended path to rectangle path
maskRect.path = maskCirclePath.CGPath
colorRed.setFill()
maskCirclePath.fill()
maskRect.fillRule = kCAFillRuleEvenOdd
self.layer.mask = maskRect
}
}
I'm not sure if my classes are being declared correctly. I made a group called "Vectors" where I planned to make a separate class for each drawing. I'm not sure if i'm supposed to select file -> new -> file and select a Cocoa Touch Class, or if i can just create a blank Swift file and write out my class code from scratch there. This is the option I was trying to figure out when my globial variables "went bad".
What's more strange is that the app compiles just fine in the simulator, my colors appear correctly for the classes applied to my icons that use the global color variables. But Xcode is throwing a fit so my #IBDesignables won't compile in storyboard and I have a bunch of red errors.
UPDATE
Somewhere along the way here, the Swift file that I posted in my question was removed from my projects "tests" target membership. The little checkbox was unchecked. I have no idea how I could have done this, but everything was back to normal until i got an xcode error whiting out all of my text and saying that editing is currently disabled. I ended up removing all of my swift files from "tests" (unchecking the "tests" target membership for all of the files"), then creating a new Objective C file which prompted Xcode to ask me to configure a new bridging header I transferred my old bridging header code to the new file. This seems to have fixed the problem. I'm not submitting this an an answer because I don't know what the actual problem was.
Been going nuts trying to get a live view of an animation in a Swift Playground like in the WWDC "Swift Playgrounds" video. I tried to do a UIView.animateWithDuration with no luck so I am now trying to do a CABasicaAnimation because this seems to be what was used in the demo. I'be gotten rid of a lot of confusing errors and have imported the proper frameworks but am still having no luck getting my little circle to do anything but sit still in the center of my XCPShowView. Here is my code:
import Foundation
import XCPlayground
import UIKit
import QuartzCore
//Circle Button
class timerButtonGraphics: UIView {
override func drawRect(rect: CGRect) {
let colorGreen = UIColor(red: 0.310, green: 0.725, blue: 0.624, alpha: 1.000)
let colorRed = UIColor(red: 241/255, green: 93/255, blue: 79/255, alpha: 100)
var bounds = self.bounds
var center = CGPoint()
center.x = bounds.origin.x + bounds.size.width / 2
center.y = bounds.origin.y + bounds.size.height / 2
var radius = 61
var path:UIBezierPath = UIBezierPath()
path.addArcWithCenter(center, radius: CGFloat(radius), startAngle: CGFloat(0.0), endAngle: CGFloat(Float(M_PI) * 2.0), clockwise: true)
path.strokeWithBlendMode(kCGBlendModeNormal, alpha: 100)
path.lineWidth = 5
colorGreen.setStroke()
path.stroke()
//Define the animation here
var anim = CABasicAnimation()
anim.keyPath = "scale.x"
anim.fromValue = 1
anim.toValue = 100
anim.delegate = self
self.layer.addAnimation(anim, forKey: nil)
}
}
var test = timerButtonGraphics(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
test.setTranslatesAutoresizingMaskIntoConstraints(true)
XCPShowView("Circle Animation", test)`
The first part of the solution is to enable the Run in Full Simulator option. See this answer for a step-by-step.
The second part of the solution is to contain your animated view in a container view, e.g.:
let container = UIView(frame: CGRect(x: 0, y: 0, width: 400, height: 400))
XCPShowView("Circle Animation", container)
let test = timerButtonGraphics(frame: CGRect(x: 198, y: 0, width: 4, height: 400))
container.addSubview(test)
The third part of the solution is to correct your animation. The keyPath should be transform.scale.x instead of scale.x and you need to add a duration, e.g.:
anim.keyPath = "transform.scale.x"
anim.duration = 5
You should then be able to view the animation in your playground.