2015-04-21 5 views
2

У меня есть быстрый пользовательский CALayer, который имеет несколько динамических свойств (на самом деле @NSManaged). У меня все правильно настроено и вызывается действие actionForKey.Core animation, self.presentationLayer() is nil

override public func actionForKey(key: String!) -> CAAction! { 
    switch key { 
    case "maxCircles", "numCircles": 
     let animation = CABasicAnimation(keyPath: key) 
     animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear); 
     animation.fromValue = self.presentationLayer().valueForKey(key); 
     animation.duration = 0.2 
     return animation; 
    default: 
     return super.actionForKey(key) 
    } 
} 

Иногда self.presentationLayer(). бросает исключение, потому что она неявно разворачивают и равна нулю. В Objective-C код обычно просто делает:

[[self presentationLayer] valueForKey:key] 

Что не врезаться, но я никогда не понял, что это можно назвать, хотя ноль и генерировать 0 - который чувствует себя очень плохо для меня. Нет никакой гарантии, что я одушевляю ноль.

Каков правильный путь доступа к presentationLayer в Swift? Должен ли я тестировать нуль? т.е .:

override public func actionForKey(key: String!) -> CAAction! { 
    if (key == "maxCircles" || key == "numCircles") && self.presentationLayer() != nil { 

     let animation = CABasicAnimation(keyPath: key) 
     animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear); 
     animation.fromValue = self.presentationLayer().valueForKey(key); 
     animation.duration = 0.2 
     return animation; 
    } 
    return super.actionForKey(key) 
} 

ответ

1

presentationLayer Свойство возвращает необязательный, да так, вы должны проверить на ноль. В сообщениях Objective-C nil не работает и, следовательно, не приведет к сбою приложения. Помните, что безопасность является одной из основных целей стремительной, поэтому вам нужно будет сделать свою собственную проверку здесь. Если вы пишете функцию, как это, он будет работать так же, как в Objective-C коллегой:

override public func actionForKey(key: String!) -> CAAction! { 
    if key == "maxCircles" || key == "numCircles" { 
     // Check your presentation layer first before doing anything else 
     if let presoLayer = self.presentationLayer() as? CALayer { 
      let animation = CABasicAnimation(keyPath: key) 
      animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear); 
      animation.fromValue = presoLayer.valueForKey(key); 
      animation.duration = 0.2 
      return animation; 
     } 
    } 
    return super.actionForKey(key) 
} 

Я предполагаю остальную часть кода прямо здесь и просто ответить на часть о диспозитивности в presentationLayer. Я переключил ваш switch на if, потому что он казался мне более читаемым.

+0

Это решение устраняет проблему, но обратите внимание, что 'presentationLayer()' возвращает неявно разворачиваемую опцию, поэтому пользователям этого метода не нужно проверять значение 'nil'. (Я бы рассмотрел это обходное решение для ошибки Apple API.) То есть, если он * может * быть nil, он должен возвращать 'AnyObject?', А не 'AnyObject!'. –

+0

Решение Мэтта Лонга (и мое) - обходные пути для ошибки Apple. Он не убивает приложения Objective-C, потому что в Objective-C вы можете отправить сообщение «nil», и ничего не происходит, но в Swift это незаконно. –

+0

AnyObject не конвертируется в CALayer, правильный тест: 'if self.presentationLayer() == nil' (добавлено в ответ) –

1

Решение Мэтт Лонг работает. Если вы хотите сохранить синтаксис switch, хотя, вы можете просто проверить nil используя case … where синтаксис:

override func actionForKey(key: String!) -> CAAction! { 
    switch key { 
    case "maxCircles", "numCircles" where self.presentationLayer() != nil: 
     let animation = CABasicAnimation(keyPath: key) 
     animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear); 
     animation.fromValue = self.presentationLayer().valueForKey(key); 
     animation.duration = 0.2 
     return animation; 
    default: 
     return super.actionForKey(key) 
    } 
} 

В качестве альтернативы, вы можете просто обеспечить по умолчанию fromValue, если нет представления слоя:

animation.fromValue = self.presentationLayer() != nil ? self.presentationLayer().valueForKey(key) : 0; 
+0

Добавление значения по умолчанию является болезненным, если тип более сложный - говорят цвета. –

+1

Я согласен - я просто даю вам варианты. Вы также можете просто установить его на «nil» (см. [Установка значений интерполяции] (https://developer.apple.com/library/prerelease/ios/documentation/GraphicsImaging/Reference/CABasicAnimation_class/index.html#//apple_ref/ DOC/UID/TP40004496-CH1-DontLinkElementID_3)). –