2015-10-01 102 views
3

我有一個定製的CALayer子類,繪製一個圓弧。它看起來是這樣的:爲了CAAnimation的目的,將Swift結構轉換/包裝爲NSValue?

class ArcLayer: CALayer { 
    var strokeColor:UIColor = UIColor.blackColor() { didSet { self.setNeedsDisplay() }} 
    var strokeWidth:CGFloat = 1.0 { didSet { self.setNeedsDisplay() }} 
    var strokeCap:CGLineCap = .Butt { didSet { self.setNeedsDisplay() }} 
    var startRadians:CGFloat = 0.0 { didSet { self.setNeedsDisplay() }} 
    var sweepRadians:CGFloat = Tau { didSet { self.setNeedsDisplay() }} 

    // other init's omitted for brevity 

    override init(layer: AnyObject) { 
     super.init(layer: layer) 
     if let layer = layer as? ArcLayer { 
      self.strokeColor = layer.strokeColor 
      self.strokeWidth = layer.strokeWidth 
      self.strokeCap = layer.strokeCap 
      self.startRadians = layer.startRadians 
      self.sweepRadians = layer.sweepRadians 
     } 
    } 

    override func drawInContext(ctx: CGContext) { 
     ... 
    } 

    override class func needsDisplayForKey(key: String) -> Bool { 
     return key == "startRadians" || key == "sweepRadians" || super.needsDisplayForKey(key) 
    } 
} 

我使用的是自定義子類,因爲同時CAShapeLayerpath是動畫,它不會在你所期望的弧線繞方式動畫。以上作品。開始/掃描的動畫產生所需的效果。

我想改變它。我有一個Angle結構(請參閱this answer),我寧願使用比原始的弧度CGFloat值。將這兩個變量的類型更改爲Angle編譯得很好。並且原始顯示也起作用(在從Angle變量進行適當的轉換/提取之後)。問題是現在可以對這些變量進行動畫處理。凡爲我之前可能已經喜歡寫一些代碼:

let sweep = CABasicAnimation(keyPath: "sweepRadians") 
sweep.fromValue = 0.0 // raw radians value 
sweep.toValue = Tau // raw radians value for one rotation 
sweep.duration = 10.seconds 
sweep.repeatCount = 0 
self.blueRing.addAnimation(sweep, forKey: "sweepRadians") 

我不能改變那些Angle值:

sweep.fromValue = Angle(raw: 0, unit: .Rotations) 
sweep.toValue = Angle(raw: 0, unit: .Rotations) 

這導致

cannot assign value of type 'Angle' to type of 'AnyObject?' 

我希望解決方案是我需要以某種方式將我的Angle值轉換/包裝爲NSValue對象?這確實是正確的嗎?可以做到嗎?怎麼會這樣?

我真的很喜歡Swift,但是與Objc相交的角落案例可能會讓人感到困惑。

回答

0

Angle是一個結構,它不符合AnyObject。爲了順應AnyObject,你需要將其更改爲一類,或者把它包裝成一個類像Box

final class Box<T> { 
    let value: T 
    init(_ value: T) { self.value = value } 
} 

這就是說,這是不太可能的工作。 CABasicAnimation在如何interpolate specific things專業知識:

  • 整數和雙打
  • 的CGRect,CGPoint,CGSize和CGAffineTransform結構
  • CATransform3D數據結構
  • CGColor和CGImage引用

我不相信有什麼方法可以添加到這個列表中。我不相信你可以使用CABasicAnimation來插入任意類型。你需要從一個數字動畫到一個數字,所以這將基本上是你上面的代碼。

當然你也可以讓sweepRadians是計算屬性,它只是轉發到sweep,你可以從動畫到Degrees(0).rawRadiansDegrees(360).rawRadians。所以你可以獲得你想要的大部分實際好處;只是不是沒有在某個時候手動轉換爲數字。

現在,如果這是Mac,你可以繼承NSAnimation並建立你自己的動畫師,可以做到這一點。有關這方面的討論見CABasicAnimation and custom types。但iOS上沒有NSAnimation,我不相信你可以用相同的方式將CAAnimation分類。 CAAnimation上沒有「進度」委託方法。

0

我認爲你應該嘗試使用的NSValue。您可以使用func withUnsafePointer<T, Result>(inout arg: T, @noescape _ body: UnsafePointer<T> throws -> Result) rethrows -> Result獲取指向Angle實例的指針(請參閱http://swiftdoc.org/v2.0/func/withUnsafePointer/以供參考)。 P.S.將NSValue包裝的東西傳遞給Core Animation是一種通用的工作技術。雖然CA將展開角度仍然不清楚。祝你好運。

相關問題