【问题标题】:How to create custom signal in ReactiveCocoa 4?如何在 ReactiveCocoa 4 中创建自定义信号?
【发布时间】:2015-12-08 22:48:33
【问题描述】:

我有以下设置,一个由GridViewCells 组成的GridView

网格视图

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() 中创建单元格时,每个单元格都会获得一个以handleTap: 为目标的UITapGestureRecognizer,我也在使用:

typealias Position = (Int, Int)

因此,如您所见,每当 GridView 被实例化时,它都会传递一个回调函数 tapHandler: Position -> (),当用户点击单元格时,该函数最终会被单元格调用。

现在,我想将点击事件转换为 RAC Signal。我不知道如何处理这个问题,因为我对 RAC 很陌生。感谢Colin Eberhardts blog articles,我设法对构建块有一个基本的了解并实现了一个自定义信号,如下所示:

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() 函数触发。

【问题讨论】:

    标签: ios swift reactive-cocoa


    【解决方案1】:

    您可以使用Signal.pipe() 完成此操作。这为您提供了一个元组,其中 signalobserver 都与该信号相关联:

    let (signal, observer) = Signal<String, NoError>.pipe()
    

    您可以像在示例中使用 sink 一样使用它(请注意,sink 只是 observer 的旧术语 :))

    但对于按钮或手势识别器,您可以利用 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

    我发布了带有扩展名的a gist,以简化其中一些常见操作。我希望这很有用!

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-10-22
      • 1970-01-01
      • 1970-01-01
      • 2022-01-20
      • 2014-11-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多