2016-01-08 2 views
2

Борьба за простой пример работы ReactiveCocoa 4.Простой пример UIGestureRecogniser с ReactiveCocoa 4

  • У меня есть распознаватель жесты для просмотра в моей иерархии.
  • У меня есть назначенный класс назначения для моих событий касания (позволяет предположить, что я хочу создавать сетевые пакеты на основе позиции касания).

Так что, похоже, как у я хочу, чтобы создать сигнал от моего жеста распознавани, карты для извлечения сенсорного положения относительно некоторой точки зрения, то есть мой класс назначения наблюдать этот сигнал (или просто какой-то последний блок subscribeNext что вызывает метод в моем классе назначения).

Однако, похоже, что не получается ничего работать и не найти хороший пример для подражания.

Я думаю, что я должен писать что-то вроде этого (псевдо-код)

panRecognizer 
    .rac_gestureSignal() 
    .map { (pgr:UIPanGestureRecognizer) -> CGPoint in 
     return pgr.locationInView(self.someUiView) 
    }.subscribeNext { (location: CGPoint) -> Void in 
     self.someNetworkDelegate.updatePosition(location) 
    } 

такая вещь возможно (это, кажется, достаточно просто)? Может быть, я пытаюсь использовать фреймворк плохо?

+0

Этот ответ предлагает использовать расширения RAC 2 для этого: http://stackoverflow.com/a/34169581/2128900. Я не знаю, есть ли способ сделать это, используя только RAC 4 (возможно, существует стороннее расширение)? –

+0

@ MichałCiuba yep Я видел это, не компилируется в RAC 4. – chris838

ответ

0

С RAC4 это один должен хорошо работать ..

let gesRec = UIPanGestureRecognizer(target: self, action: "gesRecHandler:") 

    view.addGestureRecognizer(gesRec) 
    gesRec.rac_gestureSignal().toSignalProducer().map({ (x) -> CGPoint in 
     guard let pan = x as? UIPanGestureRecognizer else {return CGPointZero} 
     return pan.locationInView(self.view) 
    }).startWithNext { (pointInView) ->() in 
     print(pointInView) 
    } 

В RAC4 есть некоторые изменения, связанные с сигналами. Поэтому вам нужно в первую очередь преобразовать ваш RACSignal в производителя сигналов и начать его наблюдать. Вы можете прочитать о производителях сигналов в FrameworkOverview . Вот статья о преобразовании RACSignals в SignalProducer RACSignalToSignalProducer

+0

Из корня вы должны добавить [слабый я] внутри закрытия –

3

Вы действительно рядом.

Но у вас не может быть RACSignal s из CGPoint s, потому что CGPoint не является ссылочным типом. Как правило, в ReactiveCocoa 2 мира, вы получите вокруг этого явно Упаковка и распаковка типов, таких как NSValue и делает справедливый бит литья вокруг:

panRecognizer.rac_gestureSignal() 
    .map({ [unowned self] (pgr: AnyObject!) -> NSValue! in 
     let pgr = pgr as! UIPanGestureRecognizer 
     return NSValue(CGPoint: pgr.locationInView(self.someUiView)) 
    }).subscribeNext({[unowned self] locationValue in 
     let location = locationValue.CGPointValue 
     self.someNetworkDelegate.updatePosition(location) 
    }) 

Однако, путем преобразования RACSignal в SignalProducer, вы можете использовать хорошие типы, которые вы хотите. Делая это ... громоздко, поэтому я использую следующие помощники:

extension SignalProducer { 
    func castSignal<T>() -> SignalProducer<T, Error> { 
     return self.map({ $0 as! T }) 
    } 

    func cantError() -> SignalProducer<Value, NoError> { 
     // If we inline this, Swift will try to implicitly return the fatalError 
     // expression. If we put an explicit return to stop this, it complains 
     // it can never execute. One is an error, the other a warning, so we're 
     // taking the coward's way out and doing this to sidestep the problem. 
     func swallowError(error: Error) -> SignalProducer<Value, NoError> { 
      fatalError("Underlying signal errored! \(error)") 
     } 

     return self.flatMapError(swallowError) 
    } 
} 

extension RACSignal { 
    func cast<T>() -> SignalProducer<T, NoError> { 
     return self.toSignalProducer().cantError().map({ $0! }).castSignal() 
    } 
} 

Очевидно, что вы должны были бы различные помощники, если вы преобразования сигналов, которые могут ошибку, но это работает хорошо для этого примера.

С теми, вы можете написать код, так же, как это:

self.reportTapRecognizer.rac_gestureSignal().cast() 
     .map({ [unowned self] (pgr: UIPanGestureRecognizer) -> CGPoint in 
      return pgr.locationInView(self.someUiView) 
     }).startWithNext({ [unowned self] location in 
      self.someNetworkDelegate.updatePosition(location) 
     }) 

Что в основном как вы написали его выше. Обратите внимание, что аннотации типа требуются в вызове map, так что cast может правильно определить его тип возврата.

Смежные вопросы