Change line width with uislider in a subclass value - swift

My code is trying to use a slide value to change the width of a line. Right now It is not working. I only want dont want lines drawn before the value is change to be effected only new lines after the value is changed.Look at vat number in class Canvas. Struct ColoredLine controls the color of the line.
struct ColoredLine {
var color = UIColor.black
var points = [CGPoint]()
}
class ViewController: UIViewController {
#objc func hhh() {
canvas.number = Int(justinBiber.value)
}
var justinBiber = UISlider()
}
class Canvas: UIView {
var strokeColor = UIColor.green
var number = 5
func undo() {
_ = lines.popLast()
setNeedsDisplay()
}
func clear() {
lines.removeAll()
setNeedsDisplay()
}
var lines = [ColoredLine]()
override func draw(_ rect: CGRect) {
super.draw(rect)
guard let context = UIGraphicsGetCurrentContext() else { return }
context.setLineWidth(number)
context.setLineCap(.butt)
lines.forEach { (line) in
for (i, p) in line.points.enumerated() {
if i == 0 {
context.move(to: p)
} else {
context.addLine(to: p)
}
}
context.setStrokeColor(line.color.cgColor)
context.strokePath()
context.beginPath()
}
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
var coloredLine = ColoredLine()
coloredLine.color = strokeColor
lines.append(coloredLine)
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let point = touches.first?.location(in: self) else { return }
guard var lastLine = lines.popLast() else { return }
lastLine.points.append(point)
lines.append(lastLine)
setNeedsDisplay()
}
}

The line width is just another property of your line. Add that property to the ColoredLine struct:
struct ColoredLine {
var color = UIColor.black
var width = 5
var points = [CGPoint]()
}
Add a strokeWidth property to your Canvas class and update that when the slider value changes:
class Canvas : UIView {
var strokeWidth = 5
....
}
In touchesBegan(), add the current value of the strokeWidth to the coloredLine instance:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
var coloredLine = ColoredLine()
coloredLine.color = strokeColor
coloredLine.width = strokeWidth
lines.append(coloredLine)
}
Then in draw(rect:) set the context's strokeWidth before drawing the line:
lines.forEach { (line) in
for (i, p) in line.points.enumerated() {
if i == 0 {
context.move(to: p)
} else {
context.addLine(to: p)
}
}
context.setStrokeColor(line.color.cgColor)
context.setLineWidth(line.width)
context.strokePath()
context.beginPath()
}

Related

SetNeedsDisplay having no effect

I am creating a subview in a UIContainerView that is of the class described below. These values are printing correctly to the terminal window but are not actual being shown in the the subview that I am defining. I thought that setNeedsDisplay() should take care of this but nothing ever shows up.
I am creating this subview as let canvas = Canvas() and also tried
canvas.setNeedsDisplay() which has no effect.
class Canvas: UIView {
override func draw(_ rect: CGRect) {
super.draw(rect)
guard let context = UIGraphicsGetCurrentContext() else { return }
context.setStrokeColor(login_theme_color.cgColor)
context.setLineWidth(10.0)
context.setLineCap(.butt)
lines.forEach { (line) in
for(i, p) in line.enumerated(){
//context.move(to: p)
//context.addLine(to: p)
if i == 0 {
context.move(to: p)
print("First point of new line is \(p)")
}else{
context.addLine(to: p)
print("point is \(p)")
}
}
}
context.strokePath()
}
var lines = [[CGPoint]]()
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
lines.append([CGPoint]())
//setNeedsDisplay()
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let point = touches.first?.location(in: nil) else { return }
guard var lastLine = lines.popLast() else { return }
lastLine.append(point)
lines.append(lastLine)
setNeedsDisplay()
}
}
Why would the values be printing to the terminal correctly, but the lines array not actually showing the values in the view? Thanks so much in advance for your help.
I define my canvas with the following constraints :
let canvas = Canvas()
#objc fileprivate func setupCanvas(){
//canvas.setNeedsDisplay()
containerView.addSubview(canvas)
canvas.translatesAutoresizingMaskIntoConstraints = false
canvas.topAnchor.constraint(equalTo: rectangle2.topAnchor, constant: 74).isActive = true
canvas.leftAnchor.constraint(equalTo: view.safeAreaLayoutGuide.leftAnchor, constant: (view.frame.width/2) + 8).isActive = true
canvas.rightAnchor.constraint(equalTo: rectangle2.rightAnchor, constant: -4).isActive = true
canvas.bottomAnchor.constraint(equalTo: howitWorksText.bottomAnchor, constant: 0).isActive = true
canvas.layer.cornerRadius = 30
canvas.layer.shadowRadius = 0.5
canvas.layer.shadowColor = UIColor.white.cgColor
//canvas.backgroundColor = UIColor.clear
//canvas.layer.borderWidth = 2.0
//canvas.layer.borderColor = UIColor.black.cgColor
canvas.layer.masksToBounds = true
canvas.backgroundColor = .white
//canvas.setNeedsDisplay()
}
and call setupCanvas() in my ViewDidLoad()
Your coordinates are off because you are using the wrong frame of reference. Specifying nil for the view in location(in view:) selects the coordinate space of the window. So even though your touches are inside the canvas, your drawings are not. You want to get the coordinates of the touch inside of the Canvas view by passing self instead of nil to location(in:).
In touchesMoved() change:
guard let point = touches.first?.location(in: nil) else { return }
to:
guard let point = touches.first?.location(in: self) else { return }
For more information, check out the documentation for location(in:).

Change child parent in GameKit

I am working on an arrow shooting game - The player need to shoot 3 arrows to a moving target (the target moves from left to right). When an arrow hits the target it should move with it (left to right). The most obvious thing to do would be to change the arrow parent to the target. From some reason its causing me some troubles -
I tried --- arrow.move(toParent:target) and I don't see the arrow on the screen even after I set a new location for it
If I simply --- target.addChild(arrow) I get a failure since I did not remove the arrow from its parent (which is the scene in this case)
When I --- arrow.removeFromParent() and then target.addChild(arrow) its causing other arrows to collide with each other and I still don't see the arrow on the screen.
This is my code -
class GameScene: SKScene, SKPhysicsContactDelegate {
var target:SKSpriteNode?
var arrows = [SKSpriteNode]()
var arrowContactPoint:CGPoint?
let noCategory:UInt32 = 0
let arrowCategory:UInt32 = 0b1
let targetCategory:UInt32 = 0b1 << 1
let obstacleCategory:UInt32 = 0b1 << 2
override func didMove(to view: SKView) {
allowCollisionDetection()
setTarget()
moveTargetFromSideToSide()
newArrow()
}
func didBegin(_ contact: SKPhysicsContact) {
let categoryBitMaskBodyA:UInt32 = contact.bodyA.categoryBitMask
let categoryBitMaskBodyB:UInt32 = contact.bodyB.categoryBitMask
if ((categoryBitMaskBodyA == targetCategory && categoryBitMaskBodyB == arrowCategory) || (categoryBitMaskBodyA == arrowCategory && categoryBitMaskBodyB == targetCategory)) {
arrowContactPoint = contact.contactPoint
arrowCollideWithTarget()
} else if (categoryBitMaskBodyA == obstacleCategory || categoryBitMaskBodyB == obstacleCategory) {
let obstacleNode:SKNode = ((categoryBitMaskBodyA == arrowCategory) ? contact.bodyA.node! : contact.bodyB.node)!
arrowCollideWithObstacle(obstacle:obstacleNode)
} else if (categoryBitMaskBodyA == arrowCategory && categoryBitMaskBodyB == arrowCategory) {
newGame()
} else {
print("Something went wrong")
}
newArrow()
}
func touchDown(atPoint pos : CGPoint) {
}
func touchMoved(toPoint pos : CGPoint) {
}
func touchUp(atPoint pos : CGPoint) {
shootArrow()
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchDown(atPoint: t.location(in: self)) }
}
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchMoved(toPoint: t.location(in: self)) }
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchUp(atPoint: t.location(in: self)) }
}
override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
for t in touches { self.touchUp(atPoint: t.location(in: self)) }
}
override func update(_ currentTime: TimeInterval) {
// Called before each frame is rendered
}
func allowCollisionDetection() {
self.physicsWorld.contactDelegate = self
}
func setTarget() {
target = self.childNode(withName: "target") as? SKSpriteNode
//Set the target bit mask, it's tag
target?.physicsBody?.categoryBitMask = targetCategory
//Set with which objects the target collide
target?.physicsBody?.collisionBitMask = noCategory
//Set to which coliision we want to responde/handle - didBegin will get triggered
target?.physicsBody?.contactTestBitMask = arrowCategory
}
func moveTargetFromSideToSide() {
let moveRight = SKAction.moveBy(x: frame.size.width - (target?.size.width)!, y: 0, duration: 2)
let moveLeft = SKAction.moveBy(x: -(frame.size.width - (target?.size.width)!), y: 0, duration: 2)
let moveBackAndForth = SKAction.repeatForever(SKAction.sequence([moveRight, moveLeft]))
target?.run(moveBackAndForth)
}
func newArrow() {
let arrow = SKSpriteNode(imageNamed: "arrow1")
let arrowTexture = SKTexture(imageNamed: "arrow1")
arrow.position = CGPoint.zero
self.addChild(arrow)
arrow.physicsBody = SKPhysicsBody(texture: arrowTexture, size: arrowTexture.size())
arrow.physicsBody?.isDynamic = true
arrow.physicsBody?.allowsRotation = true
arrow.physicsBody?.affectedByGravity = false
arrow.physicsBody?.friction = 0.2
arrow.physicsBody?.restitution = 0.2
arrow.physicsBody?.linearDamping = 0.1
arrow.physicsBody?.angularDamping = 0.1
arrow.physicsBody?.velocity = CGVector(dx: 0, dy: 0)
arrow.physicsBody?.categoryBitMask = arrowCategory
arrow.physicsBody?.collisionBitMask = noCategory
arrow.physicsBody?.contactTestBitMask = arrowCategory | obstacleCategory | targetCategory
arrows.append(arrow)
}
func shootArrow(){
print("shootArrow")
arrows.last!.physicsBody?.applyImpulse(CGVector(dx: 0, dy: 80))
}
func arrowCollideWithTarget() {
print("arrowCollideWithTarget")
arrows.last!.physicsBody?.velocity = CGVector(dx: 0, dy: 0)
arrows.last!.move(toParent: target!)
}
func arrowCollideWithObstacle(obstacle:SKNode) {
print("arrowCollideWithObstacle")
arrows.last!.removeFromParent()
arrows.removeLast()
}
func newGame() {
print("New Game")
for i in 0 ..< (arrows.count) {
arrows[i].removeFromParent()
}
arrows.removeAll()
}
}
What eventually solved it for me was using this method ---
move(toParent: )
This is my code -
func arrowCollideWithTarget() {
arrows.last!.move(toParent:target!)
}

Creation of buttons for SpriteKit

I am creating the main menu for a sprite kit application I am building. Throughout my entire project, I have used SKScenes to hold my levels and the actual gameplay. However, now I need a main menu, which holds buttons like "Play," "Levels," "Shop," etc... However, I don't feel really comfortable the way I am adding buttons now, which is like this:
let currentButton = SKSpriteNode(imageNamed: button) // Create the SKSpriteNode that holds the button
self.addChild(currentButton) // Add that SKSpriteNode to the SKScene
And I check for the touch of the button like this:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
let touch = touches.first
let touchLocation = touch!.location(in: self)
for node in self.nodes(at: touchLocation) {
guard let nodeName = node.name else {
continue
}
if nodeName == ButtonLabel.Play.rawValue {
DispatchQueue.main.asyncAfter(deadline: .now()) {
let transition = SKTransition.reveal(with: .left, duration: 1)
self.view?.presentScene(self.initialLevel, transition: transition)
self.initialLevel.loadStartingLevel()
}
return
}
if nodeName == ButtonLabel.Levels.rawValue {
slideOut()
}
}
}
However, I don't know if this is considered efficient. I was thinking of using UIButtons instead, but for that would I have to use an UIView?
Or can I add UIButtons to an SKView (I don't really get the difference between an SKView, SKScene, and UIView) What is recommended for menus?
I totally agree with #Whirlwind here, create a separate class for your button that handles the work for you. I do not think the advice from #ElTomato is the right advice. If you create one image with buttons included you have no flexibility on placement, size, look and button state for those buttons.
Here is a very simple button class that is a subclass of SKSpriteNode. It uses delegation to send information back to the parent (such as which button has been pushed), and gives you a simple state change (gets smaller when you click it, back to normal size when released)
import Foundation
import SpriteKit
protocol ButtonDelegate: class {
func buttonClicked(sender: Button)
}
class Button: SKSpriteNode {
//weak so that you don't create a strong circular reference with the parent
weak var delegate: ButtonDelegate!
override init(texture: SKTexture?, color: SKColor, size: CGSize) {
super.init(texture: texture, color: color, size: size)
setup()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
setup()
}
func setup() {
isUserInteractionEnabled = true
}
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
setScale(0.9)
self.delegate.buttonClicked(sender: self)
}
override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
setScale(1.0)
}
}
This button can be instantiated 2 ways. You can create an instance of it in the Scene editor, or create an instance in code.
class MenuScene: SKScene, ButtonDelegate {
private var button = Button()
override func didMove(to view: SKView) {
if let button = self.childNode(withName: "button") as? Button {
self.button = button
button.delegate = self
}
let button2 = Button(texture: nil, color: .magenta, size: CGSize(width: 200, height: 100))
button2.name = "button2"
button2.position = CGPoint(x: 0, y: 300)
button2.delegate = self
addChild(button2)
}
}
func buttonClicked(sender: Button) {
print("you clicked the button named \(sender.name!)")
}
You have to remember to make the scene conform to the delegate
class MenuScene: SKScene, ButtonDelegate
func buttonClicked(sender: Button) {
print("you clicked the button named \(sender.name!)")
}
For simple scenes what you are doing is fine, and actually preferred because you can use the .SKS file.
However, if you have a complex scene what I like to do is subclass a Sprite and then override that node's touchesBegan.
Here is a node that I use in all of my projects... It is a simple "on off" button. I use a "pointer" to a Boolean via the custom Reference class I made, so that way this node doesn't need to be concerned with your other scenes, nodes, etc--it simply changes the value of the Bool for the other bits of code to do with what they want:
public final class Reference<T> { var value: T; init(_ value: T) { self.value = value } }
// MARK: - Toggler:
public final class Toggler: SKLabelNode {
private var refBool: Reference<Bool>
var value: Bool { return refBool.value }
var labelName: String
/*
var offText = ""
var onText = ""
*/
func toggleOn() {
refBool.value = true
text = labelName + ": on"
}
func toggleOff() {
refBool.value = false
text = labelName + ": off"
}
/*init(offText: String, onText: String, refBool: Reference<Bool>) {
ref = refBool
super.init(fontNamed: "Chalkduster")
if refBool.value { toggleOn() } else { toggleOff() }
isUserInteractionEnabled = true
}
*/
init(labelName: String, refBool: Reference<Bool>) {
self.refBool = refBool
self.labelName = labelName
super.init(fontNamed: "Chalkduster")
isUserInteractionEnabled = true
self.refBool = refBool
self.labelName = labelName
if refBool.value { toggleOn() } else { toggleOff() }
}
public override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if refBool.value { toggleOff() } else { toggleOn() }
}
public required init?(coder aDecoder: NSCoder) { fatalError("") }
override init() {
self.refBool = Reference<Bool>(false)
self.labelName = "ERROR"
super.init()
}
};
This is a more elaborate button than say something that just runs a bit of code when you click it.
The important thing here is that if you go this route, then you need to make sure to set the node's .isUserInteractionEnabled to true or it will not receive touch input.
Another suggestion along the lines of what you are doing, is to separate the logic from the action:
// Outside of touches func:
func touchPlay() {
// Play code
}
func touchExit() {
// Exit code
}
// In touches began:
guard let name = node.name else { return }
switch name {
case "play": touchPlay()
case "exit": touchExit()
default:()
}
PS:
Here is a very basic example of how to use Toggler:
class Scene: SKScene {
let spinnyNode = SKSpriteNode(color: .blue, size: CGSize(width: 50, height: 50))
// This is the reference type instance that will be stored inside of our Toggler instance:
var shouldSpin = Reference<Bool>(true)
override func didMove(to view: SKView) {
addChild(spinnyNode)
spinnyNode.run(.repeatForever(.rotate(byAngle: 3, duration: 1)))
let toggleSpin = Toggler(labelName: "Toggle Spin", refBool: shouldSpin)
addChild(toggleSpin)
toggleSpin.position.y += 100
}
override func update(_ currentTime: TimeInterval) {
if shouldSpin.value == true {
spinnyNode.isPaused = false
} else if shouldSpin.value == false {
spinnyNode.isPaused = true
}
}
}

Multiple circles drawn SpriteKit

I'm working on simple game which will based on paiting background by player. In left and right corner there will be buttons which will move character to left or right. I've already implemented that (character is moving and lefts painted background behind), but with adding another circles fps's drops really fast. Is there any solution to that?
import SpriteKit
class GameScene: SKScene {
var playerDot:PlayerDot = PlayerDot(imageNamed:"player")
var isTurningLeft:Bool = false
var isTurningRight:Bool = false
var lastLocation:CGPoint = CGPoint()
override func didMoveToView(view: SKView) {
/* Setup your scene here */
let myLabel = SKLabelNode(fontNamed:"Helvetica")
myLabel.name = "left"
myLabel.text = "Left"
myLabel.fontSize = 30
myLabel.horizontalAlignmentMode = .Left
myLabel.position = CGPoint(x:CGRectGetMinX(self.frame), y:CGRectGetMinY(self.frame))
self.addChild(myLabel)
let myLabel2 = SKLabelNode(fontNamed:"Helvetica")
myLabel2.name = "right"
myLabel2.text = "Right"
myLabel2.fontSize = 30
myLabel2.horizontalAlignmentMode = .Right
myLabel2.position = CGPoint(x:CGRectGetMaxX(self.frame), y:CGRectGetMinY(self.frame))
self.addChild(myLabel2)
playerDot.position = CGPoint(x:CGRectGetMaxX(self.frame)/2, y:CGRectGetMinY(self.frame))
self.addChild(playerDot)
}
override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
if let theName = self.nodeAtPoint(location).name {
if theName == "left" {
isTurningLeft = true
isTurningRight = false
}
else if theName == "right" {
isTurningRight = true
isTurningLeft = false
}
}
}
}
override func touchesEnded(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
if let theName = self.nodeAtPoint(location).name {
if theName == "left" {
isTurningLeft = false
}
else if theName == "right" {
isTurningRight = false
}
}
}
}
override func touchesMoved(touches: Set<UITouch>, withEvent event: UIEvent?) {
for touch in touches {
let location = touch.locationInNode(self)
if let theName = self.nodeAtPoint(location).name {
if theName == "left" {
isTurningLeft = false
}
else if theName == "right" {
isTurningRight = false
}
}
}
}
override func update(currentTime: CFTimeInterval) {
if(isTurningLeft){
playerDot.increaseAngle()
} else if (isTurningRight){
playerDot.decreaseAngle()
}
//calculates new character position based on angle of movement changed
playerDot.updatePosition()
drawCircle()
}
func drawCircle(){
if(distanceFromCGPoints(lastLocation, b: playerDot.position)>2){
let circle = SKShapeNode(circleOfRadius: 10 )
circle.position = playerDot.position
circle.fillColor = SKColor.orangeColor()
circle.strokeColor = SKColor.orangeColor()
self.addChild(circle)
lastLocation = playerDot.position
}
}
func distanceFromCGPoints(a:CGPoint,b:CGPoint)->CGFloat{
return sqrt(pow(a.x-b.x,2)+pow(a.y-b.y,2));
}
func random() -> CGFloat {
return CGFloat(Float(arc4random()) / 0xFFFFFFFF)
}
func random(min min: CGFloat, max: CGFloat) -> CGFloat {
return random() * (max - min) + min
}
}
EDIT:
drawCircle with SKShapeNode replaced with SKSpriteNote
func drawCircle(){
if(distanceFromCGPoints(lastLocation, b: playerDot.position)>2){
let playerDot2 = SKSpriteNode(imageNamed:"player")
playerDot2.position = playerDot.position
self.addChild(playerDot2)
lastLocation = playerDot.position
}
}
If you are having frame rate drops then some parts of your code are slowing down execution too much. You need to optimise your code. Use Instruments (Time Profiler) to find out which lines/functions are causing problems speed wise. If you have never used it before read up on it and use it a couple times to get the gist, then I recommend watching the WWDC video Profiling In-Depth
Based on your edit (switching to SKSpriteNode), this is how you could do it:
Declare a texture as a property of your scene. This way, you load it once and reuse it later:
let yourTexture = SKTextureAtlas(named: "yourAtlas").textureNamed("yourTexture")
Then in your drawCircle method:
func drawCircle(){
if(distanceFromCGPoints(lastLocation, b: playerDot.position)>2){
let playerDot2 = SKSpriteNode(texture: yourTexture)
playerDot2.position = playerDot.position
self.addChild(playerDot2)
lastLocation = playerDot.position
}
}
This way (by using SKSpriteNode instead of SKShapeNode) you have reduced number of draw calls required to render all those circles. Also because you are reusing the same texture, instead of allocating it every time using imageNamed you have reduced greatly an amount of memory that app consumes. Now, SpriteKit can render hundreds of nodes #60 fps if those nodes are rendered in batches. Still there is a limit before fps start dropping. And that depends on a device.

How to hide controls in YTPlayerView?

I am using youtube-ios-player-helper library to play youtube videos in my app.
There is a small time delay between you press play button and video starts playing in the full screen. So I want to hide controls in this between time.
How can I do this?
Here what I have right now in Swift:
protocol YouTubePlayerViewDelegate {
func playVideo(id: String)
}
class DeferredYouTubePlayerView : UIView, EventActionable, YTPlayerViewDelegate {
var youtubeId: String!
var origin: String!
var playerWidth: Int!
var imageView: ImageLoadingBackgroundView?
var playImageView: UIImageView?
var player: YTPlayerView?
var backDropView: UIView?
var eventCategory:String!
var touchCancelled = false
let playerVars:[NSObject:AnyObject] = [
"playsinline":0,
"autoplay" : 0,
"modestbranding" : 1,
"origin":MetroManager.sharedInstance.selectedMetro!.baseURL
]
var delegate : YouTubePlayerViewDelegate?
func loadVideo() {
backgroundColor = UIColor.blackColor()
if imageView == nil {
imageView = ImageLoadingBackgroundView()
imageView!.setTranslatesAutoresizingMaskIntoConstraints(false)
imageView?.constrain(.FillParent(self))
}
if playImageView == nil {
playImageView = UIImageView(image: UIImage(named: "play_button"))
playImageView?.constrain(.Height(42))
playImageView?.constrain(.Height(42))
playImageView?.constrain(.CenterInParent(imageView!))
}
if let url = buildImageURL() {
imageView?.alpha = 1
imageView!.imageURL = url
} else {
imageView?.alpha = 0
}
if backDropView == nil {
backDropView = UIView()
backDropView?.backgroundColor = UIColor.blackColor()
backDropView?.constrain(.CenterInParent(self))
backDropView?.constrain(.FillParent(self))
addSubview(backDropView!)
}
if player == nil {
player = YTPlayerView()
player?.constrain(.CenterInParent(self))
player?.constrain(.FillParent(self))
player?.delegate = self
player!.loadWithVideoId(youtubeId, playerVars: playerVars)
addSubview(player!)
bringSubviewToFront(imageView!)
}
}
func buildImageURL() -> NSURL? {
return NSURL(string: "http://img.youtube.com/vi/\(youtubeId)/0.jpg")
}
override func touchesBegan(touches: Set<NSObject>, withEvent event: UIEvent) {
if let playImageView = playImageView {
playImageView.image = UIImage(named: "play_button_highlighted")
}
}
//If the user moves their finger, they probably want to slide to the next view, cancel touches
override func touchesMoved(touches: Set<NSObject>, withEvent event: UIEvent) {
if let playImageView = playImageView {
playImageView.image = UIImage(named: "play_button")
}
touchCancelled = true
}
func playerView(playerView: YTPlayerView!, didChangeToState state: YTPlayerState) {
switch state {
case .Buffering:
fallthrough
case .Playing:
hidePoster()
case .Ended:
fallthrough
case .Paused:
showPoster()
default:
()
}
}
func hidePoster() {
UIView.animateWithDuration(DEFAULT_ANIMATION_TIME, animations: { () -> Void in
self.imageView?.alpha = 0
})
}
func showPoster() {
UIView.animateWithDuration(DEFAULT_ANIMATION_TIME, animations: { () -> Void in
self.imageView?.alpha = 1
})
}
override func touchesEnded(touches: Set<NSObject>, withEvent event: UIEvent) {
println("ended")
if let playImageView = playImageView {
playImageView.image = UIImage(named: "play_button")
}
if(!touchCancelled){
loggerA(category: eventCategory, action: "Cover Scroll", label: "Video Play")
// delegate?.playVideo(youtubeId)
hidePoster()
player!.playVideo()
}
touchCancelled = false
}
deinit{
//delegate = nil
}
}
Oh, I have just found the solution: I need to set the "controls" to (0) false value in playerVars; So in my context it will look like this: let playerVars:[NSObject:AnyObject] = [ "controls":0, ... ]
And it just worked!