Drawing a shadow for a CGMutablePath, not closed, just a line - macos

I have the function Track.getShadowPath() that is returning a CGMutablePath.
Function returning CGMutablePath
static func getShadowPath() -> CGMutablePath{
let trackPath = CGMutablePath()
let initPoint = Track.tracks.first?.initPoint
let heigthShift = CGPoint(x: 0, y: 100)
trackPath.move(to: initPoint! - heigthShift)
var yShift = CGPoint(x: 0, y: 0)
for track:Track in Track.tracks{
let q = track.getQuadrant()
if(q == 2 || q == 5){
yShift.y = yShift.y + track.endPoint.y - track.initPoint.y
}
else {
trackPath.addLine(to: track.endPoint - heigthShift - yShift)
}
}
return trackPath
}
This path is then added to a CAShapeLayer and the layer added to my view as a sublayer. I want this path to have a shadow aspect. But when it renders, it produces a shadow as if the path was closed. How can I achieve my purpose?
NSView
class DemoView: NSView {
var trackShape:CAShapeLayer!
var trackShadowShape:CAShapeLayer!
override init(frame: CGRect){
super.init(frame: frame)
trackShape = CAShapeLayer()
trackShape.strokeColor = NSColor.black.cgColor
trackShape.lineWidth = 3
trackShape.lineJoin = kCALineJoinBevel
trackShape.lineCap = kCALineCapRound
trackShape.fillColor = nil
trackShadowShape = CAShapeLayer()
trackShadowShape.lineWidth = 14
trackShadowShape.lineJoin = kCALineJoinBevel
trackShadowShape.lineCap = kCALineCapRound
trackShadowShape.fillColor = nil
trackShadowShape.shadowColor = NSColor.blue.cgColor
trackShadowShape.shadowRadius = 10
self.layer?.addSublayer(trackShadowShape)
self.layer?.addSublayer(trackShape)
}
func redrawTrack(){
trackShape.path = Track.getCompletePath()
trackShadowShape.shadowPath = Track.getShadowPath()
trackShadowShape.shadowRadius = 20
trackShadowShape.shadowOpacity = 1
trackShadowShape.fillColor = NSColor.clear.cgColor
trackShadowShape.lineWidth = 10
}
}
The non-expected result

I solved this using the:
copy(strokingWithWidth lineWidth: CGFloat, lineCap: CGLineCap, lineJoin: CGLineJoin, miterLimit: CGFloat, transform: CGAffineTransform = default)
According to the docs
Returns a new path equivalent to the results of drawing the path with
a solid stroke.
So basically it creates a new CGPath which is the stroke's outline of the path you provide, with the desired width, cap, etc... I made my getShadowPath function return this new calculated path:
return trackPath.copy(strokingWithWidth: 6, lineCap: CGLineCap.round, lineJoin: CGLineJoin.round, miterLimit: 10) as! CGMutablePath
Then I used that path as shadowPath for my layer. The results are now the expected ones:
A similar answer in Objective-c can be found here

Related

In SpriteKit how can I have code for tracking the textures of two nodes at a time? As well code to track if all the nodes were matched in time?

I would like to have one piece of code in my app where I can track the textures of two nodes at a time. If the textures of the two nodes don't match I would like them reset back to their original state before the user touched them. On top of that i would like another piece of code for tracking if the particular node's textures were matched under a particular time frame like 90 seconds. Any tips on how I can do something like this for my app? Thanks.
Here is my current code:
import Foundation
import SpriteKit
class EasyScreen: SKScene {
override func didMove(to view: SKView) {
var background = SKSpriteNode(imageNamed: "Easy Screen Background")
let timerText = SKLabelNode(fontNamed: "Arial")
timerText.fontSize = 40
timerText.fontColor = SKColor.white
timerText.position = CGPoint(x: 20, y: 400)
timerText.zPosition = 1
var counter:Int = 90
timerText.run(SKAction.repeatForever(SKAction.sequence([SKAction.run {
counter-=1
timerText.text = " Time: \(counter)"
print("\(counter)")
if counter <= 0{
let newScene = TryAgainScreen(fileNamed: "Try Again Screen")
newScene?.scaleMode = .aspectFill
self.view?.presentScene(newScene)
}
},SKAction.wait(forDuration: 1)])))
background.position = CGPoint(x: 0, y: 0)
background.size.width = self.size.width
background.size.height = self.size.height
background.anchorPoint = CGPoint(x: 0.5,y: 0.5)
let matchCardOne = SKSpriteNode(imageNamed: "Fruit Match Card")
let matchCardTwo = SKSpriteNode(imageNamed: "Fruit Match Card")
let matchCardThree = SKSpriteNode(imageNamed: "Fruit Match Card")
let matchCardFour = SKSpriteNode(imageNamed: "Fruit Match Card")
matchCardOne.name = "FruitMatchCard1"
matchCardTwo.name = "FruitMatchCard2"
matchCardThree.name = "FruitMatchCard3"
matchCardFour.name = "FruitMatchCard4"
matchCardOne.size = CGSize(width: 150, height: 300)
matchCardTwo.size = CGSize(width: 150, height: 300)
matchCardThree.size = CGSize(width: 150, height: 300)
matchCardFour.size = CGSize(width: 150, height: 300)
matchCardOne.zPosition = 1
matchCardTwo.zPosition = 1
matchCardThree.zPosition = 1
matchCardFour.zPosition = 1
matchCardOne.anchorPoint = CGPoint(x: 0.5, y: 0.5)
matchCardTwo.anchorPoint = CGPoint(x: 0.5, y: 0.5)
matchCardThree.anchorPoint = CGPoint(x: 0.5, y: 0.5)
matchCardFour.anchorPoint = CGPoint(x: 0.5, y: 0.5)
matchCardOne.position = CGPoint(x: -125, y: 60)
matchCardTwo.position = CGPoint(x: -125, y: -260)
matchCardThree.position = CGPoint(x: 70, y: 60)
matchCardFour.position = CGPoint(x: 70 , y: -260)
addChild(background)
addChild(matchCardOne)
addChild(matchCardTwo)
addChild(matchCardThree)
addChild(matchCardFour)
addChild(timerText)
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
self.view?.isMultipleTouchEnabled = false
let touch = touches.first
let positionInSceneOne = touch!.location(in: self)
let tappedNodes = nodes(at: positionInSceneOne)
for node in tappedNodes{
if let tappedCard = node as? SKSpriteNode {
if tappedCard.name == "FruitMatchCard1" {
tappedCard.texture = SKTexture(imageNamed: "Apple")
}
}
let touchTwo = touches.first
let positionInSceneTwo = touch!.location(in: self)
let tappedNodesTwo = nodes(at: positionInSceneTwo)
for node in tappedNodesTwo{
if let tappedCard = node as? SKSpriteNode {
if tappedCard.name == "FruitMatchCard2" {
tappedCard.texture = SKTexture(imageNamed: "Apple")
}
}
let touchThree = touches.first
let positionInSceneThree = touch!.location(in: self)
let tappedNodesThree = nodes(at: positionInSceneThree)
for node in tappedNodesThree{
if let tappedCard = node as? SKSpriteNode {
if tappedCard.name == "FruitMatchCard3" {
tappedCard.texture = SKTexture(imageNamed: "Grapes")
}
}
let touchFour = touches.first
let positionInSceneFour = touch!.location(in: self)
let tappedNodesFour = nodes(at: positionInSceneFour)
for node in tappedNodesFour{
if let tappedCard = node as? SKSpriteNode {
if tappedCard.name == "FruitMatchCard4" {
tappedCard.texture = SKTexture(imageNamed: "Grapes")
}
}
}
}
}
}
}
}

macOS Swift CALayer.contents does not load image

The code below creates a red rectangle that is animated to move across the view from left to right. I would like to have an arbitrary shape loaded from an image to either superimpose or replace the rectangle. However, the circleLayer.contents = NSImage statement in the initializeCircleLayer function doesn't produce any effect. The diagnostic print statement seems to verify that the image exists and has been found, but no image appears in the view. How do I get an image into the layer to replace the animated red rectangle? Thanks!
CODE BELOW:
import Cocoa
class ViewController: NSViewController {
var circleLayer = CALayer()
override func viewDidLoad() {
super.viewDidLoad()
self.view.wantsLayer = true
initializeCircleLayer()
simpleCAAnimationDemo()
}
func initializeCircleLayer(){
circleLayer.bounds = CGRect(x: 0, y: 0, width: 150, height: 150)
circleLayer.position = CGPoint(x: 50, y: 150)
circleLayer.backgroundColor = NSColor.red.cgColor
circleLayer.cornerRadius = 10.0
let testIm = NSImage(named: NSImage.Name(rawValue: "testImage"))
print("testIm = \(String(describing: testIm))")
circleLayer.contents = NSImage(named: NSImage.Name(rawValue: "testImage"))?.cgImage
circleLayer.contentsGravity = kCAGravityCenter
self.view.layer?.addSublayer(circleLayer)
}
func simpleCAAnimationDemo(){
circleLayer.removeAllAnimations()
let animation = CABasicAnimation(keyPath: "position")
let startingPoint = NSValue(point: NSPoint(x: 50, y: 150))
let endingPoint = NSValue(point: NSPoint(x: 600, y: 150))
animation.fromValue = startingPoint
animation.toValue = endingPoint
animation.repeatCount = Float.greatestFiniteMagnitude
animation.duration = 10.0
circleLayer.add(animation, forKey: "linearMovement")
}
}
Why it doesn't work
The reason why
circleLayer.contents = NSImage(named: NSImage.Name(rawValue: "testImage"))?.cgImage
doesn't work is because it's a reference to the cgImage(forProposedRect:context:hints:) method, meaning that its type is
((UnsafeMutablePointer<NSRect>?, NSGraphicsContext?, [NSImageRep.HintKey : Any]?) -> CGImage?)?
You can see this by assigning NSImage(named: NSImage.Name(rawValue: "testImage"))?.cgImage to a local variable and ⌥-clicking it to see its type.
The compiler allows this assignment because circleLayer.contents is an Any? property, so literally anything can be assigned to it.
How to fix it
As of macOS 10.6, you can assign NSImage objects to a layers contents directly:
circleLayer.contents = NSImage(named: NSImage.Name(rawValue: "testImage"))

Capturing MTKView texture to UIImageView efficiently

I want to capture the contents of the portion of an MTKView that has most recently updated into an UIImageView. I the following piece of code to accomplish this task:
let cicontext = CIContext(mtlDevice: self.device!) // set up once along with rest of renderPipeline
...
let lastSubStrokeCIImage = CIImage(mtlTexture: lastDrawableDisplayed.texture, options: nil)!.oriented(CGImagePropertyOrientation.downMirrored)
let bboxChunkSubCurvesScaledAndYFlipped = CGRect(...) // get bounding box of region just drawn
let imageCropCG = cicontext.createCGImage(lastSubStrokeCIImage, from: bboxStrokeAccumulatingScaledAndYFlipped)
// Now that we have a CGImage of just the right size, we have to do the following expensive operations before assigning to a UIIView
UIGraphicsBeginImageContextWithOptions(bboxStrokeAccumulating.size, false, 0) // open a bboxKeyframe-sized context
UIGraphicsGetCurrentContext()?.translateBy(x: 0, y: bboxStrokeAccumulating.height)
UIGraphicsGetCurrentContext()?.scaleBy(x: 1.0, y: -1.0)
UIGraphicsGetCurrentContext()?.draw(imageCropCG!, in: CGRect(x: 0, y: 0 , width: bboxStrokeAccumulating.width, height: bboxStrokeAccumulating.height))
// Okay, finally we create a CALayer to be a container for what we've just drawn
let layerStroke = CALayer()
layerStroke.frame = bboxStrokeAccumulating
layerStroke.contents = UIGraphicsGetImageFromCurrentImageContext()?.cgImage
UIGraphicsEndImageContext()
strokeView.layer.sublayers = nil // empty out strokeView
strokeView.layer.addSublayer(layerStroke) // add our hard-earned drawing in its latest state
So, this code works, but is not very efficient and makes the app lag when bboxStrokeAccumulating gets very large. Can anyone suggest more efficient alternatives?
For swift 4.0,
let lastDrawableDisplayed = metalView?.currentDrawable?.texture
if let imageRef = lastDrawableDisplayed?.toImage() {
let uiImage:UIImage = UIImage.init(cgImage: imageRef)
}
extension MTLTexture {
func bytes() -> UnsafeMutableRawPointer {
let width = self.width
let height = self.height
let rowBytes = self.width * 4
let p = malloc(width * height * 4)
self.getBytes(p!, bytesPerRow: rowBytes, from: MTLRegionMake2D(0, 0, width, height), mipmapLevel: 0)
return p!
}
func toImage() -> CGImage? {
let p = bytes()
let pColorSpace = CGColorSpaceCreateDeviceRGB()
let rawBitmapInfo = CGImageAlphaInfo.noneSkipFirst.rawValue | CGBitmapInfo.byteOrder32Little.rawValue
let bitmapInfo:CGBitmapInfo = CGBitmapInfo(rawValue: rawBitmapInfo)
let selftureSize = self.width * self.height * 4
let rowBytes = self.width * 4
let releaseMaskImagePixelData: CGDataProviderReleaseDataCallback = { (info: UnsafeMutableRawPointer?, data: UnsafeRawPointer, size: Int) -> () in
return
}
let provider = CGDataProvider(dataInfo: nil, data: p, size: selftureSize, releaseData: releaseMaskImagePixelData)
let cgImageRef = CGImage(width: self.width, height: self.height, bitsPerComponent: 8, bitsPerPixel: 32, bytesPerRow: rowBytes, space: pColorSpace, bitmapInfo: bitmapInfo, provider: provider!, decode: nil, shouldInterpolate: true, intent: CGColorRenderingIntent.defaultIntent)!
return cgImageRef
}
}
you can set the uiImage to your uiImageView

Collision detection in Xcode(swift) won't work, I am trying to set up boundaries in which the player cannot cross

I have the SKContactDelegate setup
class GameScene: SKScene, SKPhysicsContactDelegate
{
override func didMoveToView(view: SKView)
{
self.physicsWorld.contactDelegate = self
Here I setup the enum
enum ColliderType:UInt32
{
case Player = 1
case Boundary = 2
}
Here I make the player node.
let playerTexture = SKTexture(imageNamed: "testCircle1.png")
thePlayer = SKSpriteNode(texture: playerTexture)
thePlayer.position = CGPointMake(frame.size.width - 350, frame.size.height/2)
thePlayer.zPosition = 5
thePlayer.size = CGSize(width: 100, height: 100)
thePlayer.name = "playerNode"
thePlayer.physicsBody = SKPhysicsBody(circleOfRadius: playerTexture.size().height/2)
thePlayer.physicsBody!.dynamic = false
thePlayer.physicsBody!.allowsRotation = false
thePlayer.physicsBody!.categoryBitMask = ColliderType.Player.rawValue
thePlayer.physicsBody!.contactTestBitMask = ColliderType.Boundary.rawValue
thePlayer.physicsBody!.collisionBitMask = ColliderType.Boundary.rawValue
addChild(thePlayer)
Then I setup the Boundaries
ground = SKSpriteNode(color: UIColor.redColor(), size: CGSizeMake(frame.size.width - 150, 10))
ground.position = CGPointMake(frame.size.width/2 - 75, 96)
ground.zPosition = 5
ground.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(ground.size.width, ground.size.height))
ground.physicsBody!.dynamic = false
ground.physicsBody!.allowsRotation = false
ground.physicsBody!.categoryBitMask = ColliderType.Boundary.rawValue
ground.physicsBody!.contactTestBitMask = ColliderType.Player.rawValue
ground.physicsBody!.collisionBitMask = ColliderType.Player.rawValue
addChild(ground)
sky = SKSpriteNode(color: UIColor.redColor(), size: CGSizeMake(frame.size.width - 150, 10))
sky.position = CGPointMake(frame.size.width/2 - 75, frame.size.height - 96)
sky.zPosition = 5
sky.physicsBody = SKPhysicsBody(rectangleOfSize: CGSizeMake(frame.size.width - 150, 10))
sky.physicsBody!.dynamic = false
sky.physicsBody!.allowsRotation = false
sky.physicsBody!.categoryBitMask = ColliderType.Boundary.rawValue
sky.physicsBody!.contactTestBitMask = ColliderType.Player.rawValue
sky.physicsBody!.collisionBitMask = ColliderType.Player.rawValue
addChild(sky)
Then the collision detection
func didBeginContact(contact: SKPhysicsContact)
{
print("Contact")
if contact.bodyA.categoryBitMask == ColliderType.Boundary.rawValue || contact.bodyB.categoryBitMask == ColliderType.Boundary.rawValue
{
print("Contact")
thePlayer.removeAllActions()
}
}
I tried putting the print outside of the if statement to see if it was even detecting collision at all, but it wasn't.
I have looked at many tutorials and followed what they did but it just won't work and I only have a couple more weeks to turn this in.
In the player node
remove this:
thePlayer.physicsBody!.dynamic = false
That is setting the physics body to be a boundary and not a body...

Xcode Stopped Recognizing Global Variables - Swift

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.

Resources