如何在ReactiveCocoa 4中创build自定义信号?
我有以下设置,一个由GridViewCell
组成的GridViewCell
。
网格视图
class GridView : UIView { var gridViewCells: [GridViewCell] = [] let tapHandler: Position -> () init(frame: CGRect, tapHandler: Position -> ()) { self.tapHandler = tapHandler super.init(frame: frame) self.gridViewCells = createCells(self) addCellsToView(self.gridViewCells) } func addCellsToView(cells: [GridViewCell]) { for cell in cells { self.addSubview(cell) } } }
GridViewCell
class GridViewCell: UIImageView { let position: Position let tapHandler: Position -> () init(frame: CGRect, position: Position, tapHandler: Position -> ()) { self.position = position self.tapHandler = tapHandler super.init(frame: frame) } func handleTap(sender: UITapGestureRecognizer) { self.tapHandler(self.position) } }
请注意,我省略了一些不太相关的代码部分,只知道在createCells()
创build单元格时,每个单元格都获得了一个以UITapGestureRecognizer
为目标的handleTap:
,我也在使用:
typealias Position = (Int, Int)
所以,正如你所看到的,每当一个GridView
被实例化时,它都会传递一个callback函数tapHandler: Position -> ()
,当用户点击一个单元格时,最终被单元调用。
现在,我想将点击事件转换为RAC Signal
。 我不知道如何解决这个问题,因为我对RAC很陌生。 感谢科林Eberhardts博客的文章 ,我设法得到了基本的了解的基石和实现一个自定义的信号,如下所示:
func createSignal() -> Signal<String, NoError> { var count = 0 return Signal { sink in NSTimer.schedule(repeatInterval: 1.0) { timer in sink.sendNext("tick #\(count++)") } return nil } }
我现在基本上只想要一个类似的行为,只是发出的事件不是由NSTimer
触发的,而是由handleTap()
函数触发的。
你可以通过使用Signal.pipe()
来完成。 这给你一个元组与signal
和observer
绑定的信号:
let (signal, observer) = Signal<String, NoError>.pipe()
你可以像你在你的例子中使用的方式一样使用它(请注意, sink
只是observer
的旧术语:))
在button或手势识别器的情况下,您可以使用RAC 2
扩展。 例如:
let signal: SignalProducer<(), NoError> = gestureRecognizer .rac_gestureSignal() .toSignalProducer() .mapError { fatalError("Unexpected error: \(error)"); return () } // errors cannot occur, but because they weren't typed in `RACSignal` we have to explicitly ignore them. .map { _ in () }
或者UIControl.rac_signalForControlEvents
。
我发表了扩展的gist
来简化这些常见的操作。 我希望这是有用的!