4

CALayer円弧を描くカスタムサブクラスがあります。次のようになります。

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)
    }
}

カスタム サブクラスを使用しています。これはpath、 のCAShapeLayerはアニメーション化可能ですが、アークが回転すると予想される方法でアニメーション化されないためです。上記の作品。開始/スイープへのアニメーションは、望ましい効果を生み出します。

変えたいけど。生のラジアン CGFloat 値よりも使用したい構造体 (この回答を参照) がありAngleますこれら 2 つの変数の型を に変更すると、正常に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 と交差するコーナー ケースは本当に混乱する可能性があります。

4

2 に答える 2

3

Angleに準拠しない構造体AnyObjectです。に準拠するにAnyObjectは、クラスに変更するか、次のようなクラスにラップする必要がありますBox

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

とはいえ、これはうまくいく可能性は低いです。特定のものを補間するCABasicAnimation方法について特別な知識を持っています:

  • 整数と倍精度
  • CGRect、CGPoint、CGSize、および CGAffineTransform 構造体
  • CATransform3D データ構造
  • CGColor と CGImage のリファレンス

このリストに追加する方法はないと思います。CABasicAnimation任意の型を補間するために使用できるとは思いません。数値から数値にアニメーション化する必要があるため、基本的には上記のコードになります。

もちろんsweepRadians、 を に転送する計算済みプロパティにすることも、からにsweepアニメートすることもできます。したがって、必要な実用的なメリットのほとんどを得ることができます。ある時点で手動で数値に変換しない限り、そうではありません。Degrees(0).rawRadiansDegrees(360).rawRadians

これが Mac の場合、これを実行できるNSAnimation独自のアニメーターをサブクラス化して構築できます。これについては、CABasicAnimation とカスタム タイプを参照してください。しかし、iOS にはありません。同じ方法でNSAnimationサブクラス化できるとは思えません。CAAnimationには「進行」デリゲート メソッドはありませんCAAnimation

于 2015-10-01T19:02:59.880 に答える