Преобразование ленивого экземпляра Objective-C с побочными эффектами в Swift
Я преобразовал приложение Obit-C Dropit из курса Stanford CS193P в Swift. Оригинальный код находится по адресу:
http://web.stanford.edu/class/cs193p/cgi-bin/drupal/
Есть многократное использование отложенной реализации, которая выполняет дополнительную инициализацию или вызывает некоторый другой побочный эффект. Мое преобразование в Swift работает, но я не уверен, что это правильное решение или следует полностью избегать такого рода кодирования Objective-C? Первые примеры просто устанавливают некоторые свойства как часть отложенной реализации.
- (UIGravityBehavior *)gravity
{
if (!_gravity) {
_gravity = [[UIGravityBehavior alloc] init];
_gravity.magnitude = 0.9;
}
return _gravity;
}
- (UICollisionBehavior *)collider
{
if (!_collider) {
_collider = [[UICollisionBehavior alloc] init];
_collider.translatesReferenceBoundsIntoBoundary = YES;
}
return _collider;
}
Моя версия Swift:
@lazy var gravity: UIGravityBehavior = {
var tempGravity = UIGravityBehavior()
tempGravity.magnitude = 0.9
return tempGravity
}()
@lazy var collider: UICollisionBehavior = {
var tempCollider = UICollisionBehavior()
tempCollider.translatesReferenceBoundsIntoBoundary = true
return tempCollider
}()
Есть ли более понятный способ инициализации в Swift?
ViewController из Objective-C для второго примера немного сложнее:
@interface DropitViewController () <UIDynamicAnimatorDelegate>
@property (weak, nonatomic) IBOutlet UIView *gameView;
@property (strong, nonatomic) UIDynamicAnimator *animator;
@property (strong, nonatomic) DropitBehavior *dropitBehavior;
@end
@implementation DropitViewController
static const CGSize DROP_SIZE = { 40, 40 };
- (DropitBehavior *)dropitBehavior
{
if (!_dropitBehavior) {
_dropitBehavior = [[DropitBehavior alloc] init];
[self.animator addBehavior:_dropitBehavior];
}
return _dropitBehavior;
}
- (UIDynamicAnimator *)animator
{
if (!_animator) {
_animator = [[UIDynamicAnimator alloc] initWithReferenceView:self.gameView];
_animator.delegate = self;
}
return _animator;
}
В Свифте:
class ViewController: UIViewController, UIDynamicAnimatorDelegate {
@IBOutlet var gameView: UIView
let DROP_SIZE = CGSize(width: 40.0, height: 40.0)
// lazy instantiation with closures
@lazy var animator: UIDynamicAnimator = {
var tempAnimator = UIDynamicAnimator(referenceView: self.gameView)
tempAnimator.delegate = self
return tempAnimator
}()
@lazy var dropitBehavior: DropitBehavior = {
var tempBehavior = DropitBehavior()
// side effect...
self.animator.addBehavior(tempBehavior)
return tempBehavior
}()
То, как была разработана программа, во время ленивой инициализации dropitBehavior - это когда аниматор создается впервые, а затем dropitBehavior добавляется в аниматор. Это можно проверить с помощью println, в отладчике и т. Д.
Обратите внимание, что есть связанный вопрос: Ленивый экземпляр UIDynamicAnimator с referenceView - Swift
Тем не менее, предлагаемое решение, по-видимому, заключается в том, чтобы избежать @lazy, использовать дополнительные параметры и перенести работу в viewDidLoad, что тоже не кажется таким уж хорошим.
Существует много кода Objective-C, подобного этому, для перевода, поэтому я хотел бы узнать, как это сделать в Swift.