issue with animation in swift playground - swift

I'm totally new to animations with swift and I started this concept by using playground here's my code below I have no "idea" why it doesn't work.
import UIKit
import PlaygroundSupport
let liveViewFrame = CGRect(x: 0, y: 0, width: 500, height: 500)
let liveView = UIView(frame: liveViewFrame)
liveView.backgroundColor = .white
PlaygroundPage.current.liveView = liveView
let smallFrame = CGRect(x: 0, y: 0, width: 100, height: 100)
let square = UIView(frame: smallFrame)
square.backgroundColor = .purple
liveView.addSubview(square)
UIView.animate(withDuration: 3.0) {
liveView.backgroundColor = .blue
}

This piece of code is working fine

Related

Swift UIView "Empty Image"

Could someone explain me the difference between these two pictures please?
Code with preview of the UIView:
Code without the preview of the UIView:
What's the difference? And why can't I get a preview on the second code example? It only shows "empty image"....
Thanks for helping me.
This seems to be a "feature" (bug) of a Swift playground. If you don't create the view instance using a non-zero frame width and height, you will get "empty image".
This works:
let rect = UIView(frame: CGRect(x: 0, y: 0, width: 1, height: 1))
rect.frame = CGRect(x: 0, y: 0, width: 200, height: 200)
rect.backgroundColor = .green
But this doesn't:
let rect = UIView(frame: .zero)
// also bad: let rect = UIView(frame: CGRect(x: 0, y: 0, width: 1, height: 0))
rect.frame = CGRect(x: 0, y: 0, width: 200, height: 200)
rect.backgroundColor = .green
And remember that:
let rect = UIView()
is essentially the same as doing:
let rect = UIView(frame: .zero)
So when using a playground, create a view with a non-zero frame width and height in the initializer if you don't want to see "empty image".

How to apply an inverse text mask in Swift?

I am trying programmatically create a layer with transparent text. Everything I try doesn't seem to work. My end goal is to create an inner shadow on text.
Instead of a circle as in the code below I want text.
let view = UIView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
view.backgroundColor = .white
// MASK
let blackSquare = UIView(frame: CGRect(x: 100, y: 100, width: 200, height: 200))
blackSquare.backgroundColor = .black
view.addSubview(blackSquare)
let maskLayer = CAShapeLayer()
// Create a path with the rectangle in it.
let path = CGMutablePath()
path.addArc(center: CGPoint(x: 100, y: 100), radius: 50, startAngle: 0.0, endAngle: 2.0 * .pi, clockwise: false)
path.addRect(CGRect(x: 0, y: 0, width: blackSquare.frame.width, height: blackSquare.frame.height))
maskLayer.backgroundColor = UIColor.black.cgColor
maskLayer.path = path;
maskLayer.fillRule = kCAFillRuleEvenOdd
blackSquare.layer.mask = maskLayer
maskLayer.masksToBounds = false
maskLayer.shadowRadius = 4
maskLayer.shadowOpacity = 0.5
maskLayer.shadowOffset = CGSize(width: 5, height: 5)
view.addSubview(blackSquare)
I'm also able to use text as a mask but I'm unable to invert the mask. Any help is appreciated.
EDIT:
I figured it out based on Rob's answer as suggested by Josh. Here's my playground code.
import Foundation
import UIKit
import PlaygroundSupport
// view
let view = UIView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
view.backgroundColor = .black
// button
let button = UIButton(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
button.setTitle("120", for: .normal)
button.setTitleColor(.white, for: .normal)
button.titleLabel?.font = UIFont(name: "AvenirNextCondensed-UltraLight", size: 200)
view.addSubview(button)
addInnerShadow(button: button)
func addInnerShadow(button: UIButton) {
// text
let text = button.titleLabel!.text!
// get context
UIGraphicsBeginImageContextWithOptions(button.bounds.size, true, 0)
let context = UIGraphicsGetCurrentContext()
context?.scaleBy(x: 1, y: -1)
context?.translateBy(x: 0, y: -button.bounds.size.height)
let font = button.titleLabel!.font!
// draw the text
let attributes = [
NSAttributedStringKey.font: font,
NSAttributedStringKey.foregroundColor: UIColor.white
]
let size = text.size(withAttributes: attributes)
let point = CGPoint(x: (button.bounds.size.width - size.width) / 2.0, y: (button.bounds.size.height - size.height) / 2.0)
text.draw(at: point, withAttributes: attributes)
// capture the image and end context
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
// create image mask
let cgimage = image?.cgImage!
let bytesPerRow = cgimage?.bytesPerRow
let dataProvider = cgimage?.dataProvider!
let bitsPerPixel = cgimage?.bitsPerPixel
let width = cgimage?.width
let height = cgimage?.height
let bitsPerComponent = cgimage?.bitsPerComponent
let mask = CGImage(maskWidth: width!, height: height!, bitsPerComponent: bitsPerComponent!, bitsPerPixel: bitsPerPixel!, bytesPerRow: bytesPerRow!, provider: dataProvider!, decode: nil, shouldInterpolate: false)
// create background
UIGraphicsBeginImageContextWithOptions(button.bounds.size, false, 0)
UIGraphicsGetCurrentContext()!.clip(to: button.bounds, mask: mask!)
view.backgroundColor!.setFill()
UIBezierPath(rect: button.bounds).fill()
let background = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
let backgroundView = UIImageView(image: background)
// add shadows
backgroundView.layer.shadowOffset = CGSize(width: 2, height: 2)
backgroundView.layer.shadowRadius = 2
backgroundView.layer.shadowOpacity = 0.75
button.addSubview(backgroundView)
}
PlaygroundPage.current.liveView = view
Whilst not exactly the same, please refer to the answer provided here by Rob who answered a similar question:
How do I style a button to have transparent text?
This should get you started at the very least...
Stumbled on a possible solution that I've updated to proper syntax:
func mask(withRect rect: CGRect, inverse: Bool = false) {
let path = UIBezierPath(rect: rect)
let maskLayer = CAShapeLayer()
if inverse {
path.append(UIBezierPath(rect: self.view.bounds))
maskLayer.fillRule = kCAFillRuleEvenOdd
}
maskLayer.path = path.cgPath
self.view.layer.mask = maskLayer
}
You'll obviously need to pick parts out to see if it works for you.

How to make this UIButton's action operate correctly?

Every time I run this swift playground (on Xcode), I get an error on the last line saying:
'PlaygroundView' cannot be constructed because it has no accessible initialisers.
I also have another error on line 4 saying:
class 'PlaygroundView' has no initializers.
import UIKit
import PlaygroundSupport
class PlaygroundView:UIViewController {
var introImage:UIImageView
var introButton:UIButton
override func loadView() {
print("workspace started running.")
//Main Constant and Variable Declarations/General Setup
let mainView = UIView()
//Main View Modifications & styling
mainView.backgroundColor = UIColor.init(colorLiteralRed: 250, green: 250, blue: 250, alpha: 1)
func addItem(item: UIView) {
mainView.addSubview(item)
}
//Sub-Element Constant and Variable Declarations
introImage = UIImageView(frame: CGRect(x: 87.5, y: -300, width: 200, height: 200))
introImage.layer.borderColor = UIColor.black.cgColor
introImage.layer.borderWidth = 4
introImage.alpha = 0
introImage.transform = CGAffineTransform(rotationAngle: -90.0 * 3.14/180.0)
introImage.image = UIImage(named: "profile_pic.png")
introImage.image?.accessibilityFrame = introImage.frame
introImage.layer.cornerRadius = 100
addItem(item: introImage)
introButton = UIButton(frame: CGRect(x: 87.5, y: 900, width: 200, height: 30))
introButton.alpha = 0
introButton.setTitle("Tap to meet me", for: .normal)
introButton.titleLabel?.font = UIFont(name: "Avenir Book", size: 20)
introButton.backgroundColor = UIColor.black
introButton.layer.cornerRadius = 15
introButton.layer.borderWidth = 5
addItem(item: introButton)
introButton.addTarget(self, action: #selector(self.introButtonAction), for: .touchDown)
UIView.animate(withDuration: 1.5, delay: 1, options: .curveEaseInOut, animations: {
self.introImage.frame = CGRect(x: 87.5, y: 175, width: 200, height: 200)
self.introButton.frame = CGRect(x: 87.5, y: 400, width: 200, height: 30)
self.introImage.transform = CGAffineTransform(rotationAngle: 0.0 * 3.14/180.0)
self.introImage.alpha = 1
self.introButton.alpha = 1
}) { (mainAnimationComped) in
if mainAnimationComped == true {
print("introduction animation comped.")
}
}
}
//User Interface Actions
func introButtonAction() {
print("user interacted with user interface")
}
}
PlaygroundPage.current.liveView = PlaygroundView()
How would I fix this problem?
That's because in Swift, you need to initialize variables before use them in the code. On the other hand, since in this case you set them explicitly in your function, you might declare them as implicitly unwrapped optionals
var introImage:UIImageView!
var introButton:UIButton!
and this should work without changing anything else in your code
Add ? after introImage and introButton
var introImage:UIImageView?
var introButton:UIButton?

UIImageView Animation Playground

import UIKit
import PlaygroundSupport
import XCPlayground
//main window
let view = UIView(frame: CGRect(x:0, y: 0, width: 480, height: 320))
//array of images
let animationPictures: [UIImage] =
[
UIImage(named: "first.png")!,
UIImage(named: "second.png")!
]
var animationBkg = UIImageView()
animationBkg.animationImages = animationPictures;
animationBkg.animationDuration = 0.5
animationBkg.startAnimating()
Here is the code I currently have. the goal is to have these two images playing one after another as an animation, but it isn't working. In the preview of my code, all it has is a black square.
let animationPictures: [UIImage] =
[
UIImage(named: "first.png")!,
UIImage(named: "second.png")!
]
//animation
var animationView = UIImageView(frame: CGRect(x: CGFloat(0), y: CGFloat(0), width: CGFloat(480), height: CGFloat(320)))
animationView.animationImages = animationPictures
animationView.animationDuration = 1.5
animationView.animationRepeatCount = 0
animationView.startAnimating()
view.addSubview(animationView)
I found a solution to my own problem. Thanks for the help

How to add a UIButton to Swift Playground?

So I opened up playground, I just want to add a simple UIButton (or a simple UIView) for testing purposes. I can't get it to display though. This is what I have so far:
import UIKit
var uiButton = UIButton.buttonWithType(UIButtonType.System) as UIButton
uiButton.frame = CGRectMake(0, 0, 100, 100)
uiButton.setTitle("Test", forState: UIControlState.Normal);
//self.view.addSubview(uiButton) <-- doesn't work
Do you guys know what I'm doing wrong? Thanks
I think you can add button into playground and your code is correct you can see your button here when you click on Quick Look:
or you can see that button with clicking on Value History:
you dont need to add that into view.
If you import XCPlayground in your playground you can show views using:
let view=UIView()
//other setup
XCPShowView("View Title",view)
This will show the view in the assistant editor
To show the assistant editor goto View > Assistant Editor > Show Assistant Editor
import XCPlayground has been deprecated and is now import PlaygroundSupport.
You need to create your view first and give it a size.
let view = UIView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
view.backgroundColor = UIColor.black
then add PlaygroundPage.current.liveView = view to be able to see the view in the assistant editor.
now that you have created your view, and you can see the live preview of it. You can now add other views to it. In my playground I added several views so I created simple function with a default width and height.
func addSquareView(x: Int, y: Int, width: Int = 100, height: Int = 100, color: UIColor) {
let newView = UIView(frame: CGRect(x: x, y: y, width: width, height: height))
newView.backgroundColor = color
view.addSubview(newView)
}
addSquareView(x: 100, y: 100, color: .blue)
Now there is a blue square in the center of my view.
I was just doing my sorting programming and pated the code..it will help you to add a button in playgroud with target.
import UIKit
import PlaygroundSupport
let aButton = UIButton(frame: CGRect(x: 0, y: 0, width: 100, height: 50))
aButton.backgroundColor = .lightGray
aButton.setTitle("Run Sorting", for: .normal)
aButton.layer.cornerRadius = 10
aButton.clipsToBounds = true
class Sorting {
#objc func callSorting() {
self.getSortedArrayUsingSelectionSort()
}
func getSortedArrayUsingSelectionSort() {
var arr = [4, 9, 10, 6, 1, 3]
let n = arr.count
for i in 0..<(n - 1) {
var minIndex = i
for j in (i+1)..<n {
if arr[j] < arr[minIndex] {
minIndex = j
}
}
if minIndex != i {
let temp = arr[minIndex]
arr[minIndex] = arr[i]
arr[i] = temp
} }
print(arr)
}
}
let target = Sorting()
aButton.addTarget(target, action: #selector(Sorting.callSorting), for: .touchUpInside)
let containerView = UIView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
containerView.backgroundColor = .white
PlaygroundPage.current.liveView = containerView
containerView.addSubview(aButton)