Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type 'CGPoint' has no member 'x' when using #keyPath in CABasicAnimation

I am trying to use the #keyPath syntax in order to get a CALayer property to animate it like this:

let myAnimation = CABasicAnimation.init(keyPath: #keyPath(CALayer.position.x))

and I get the following error:

Type 'CGPoint' has no member 'x'

What am I missing?

like image 613
TheoK Avatar asked Feb 24 '18 15:02

TheoK


2 Answers

The #keyPath directive expects an Objective-C property sequence as argument. CALayer inherits from NSObject, but its position property is struct CGPoint, which is not a class at all, and cannot used with Key-Value coding.

However, CALayer has a special implementation of value(forKeyPath:) which handles the entire key path, instead of evaluating the first key and passing down the remaining key path, compare KVC strange behavior.

So Key-Value Coding can be used with "position.x", but the compiler does not know about this special treatment. As an example, this all compiles and runs:

let layer = CALayer()
layer.position = CGPoint(x: 4, y: 5)

print(layer.value(forKeyPath: "position"))   // Optional(NSPoint: {4, 5}
print(layer.value(forKeyPath: "position.x")) // Optional(4)

print(layer.value(forKeyPath: #keyPath(CALayer.position))) // Optional(NSPoint: {4, 5})

but this does not compile:

print(layer.value(forKeyPath: #keyPath(CALayer.position.x)))
// error: Type 'CGPoint' has no member 'x'

That is the reason why

let myAnimation = CABasicAnimation(keyPath: #keyPath(CALayer.position.x))

does not compile, but this does (as Reinier Melian suggested):

let myAnimation = CABasicAnimation(keyPath: "position.x")
like image 175
Martin R Avatar answered Nov 17 '22 19:11

Martin R


position is a property in object of type CALayer and you want to access it from base class , second keyPath takes a property to animate in the layer and CALayer.position.x is not a property inside CALayer object that you want to animate , so it must be position.x that you can't write directly without string "" as you will have error saying can't find position in the class you want to declare it in , so proper way would be like this

  let myLayer = CALayer.init()
  myLayer.frame = CGRect(x: 0, y: 0, width: 20, height: 20)
  let anim =  CABasicAnimation.init(keyPath: "position.x")
  anim.fromValue = 20
  anim.toValue = 100
  anim.duration = 1
  myLayer.add(myAnimation, forKey: "position.x")
  self.view.layer.addSublayer(myLayer)
like image 1
Sh_Khan Avatar answered Nov 17 '22 20:11

Sh_Khan