如何在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()来完成。 这给你一个元组与signalobserver绑定的信号:

 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来简化这些常见的操作。 我希望这是有用的!