Skip to content

Commit

Permalink
Improve ProtocolProxy
Browse files Browse the repository at this point in the history
  • Loading branch information
srdanrasic committed Jun 14, 2016
1 parent c6a672a commit 3c1bc7e
Show file tree
Hide file tree
Showing 6 changed files with 301 additions and 97 deletions.
38 changes: 21 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
![](Assets/logo.png)

[![Platform](https://img.shields.io/cocoapods/p/ReactiveKit.svg?style=flat)](http://cocoadocs.org/docsets/ReactiveKit/2.0.0-beta4/)
[![Platform](https://img.shields.io/cocoapods/p/ReactiveKit.svg?style=flat)](http://cocoadocs.org/docsets/ReactiveKit/2.1.0)
[![Build Status](https://travis-ci.org/ReactiveKit/ReactiveKit.svg?branch=master)](https://travis-ci.org/ReactiveKit/ReactiveKit)
[![Join Us on Gitter](https://img.shields.io/badge/GITTER-join%20chat-blue.svg)](https://gitter.im/ReactiveKit/General)
[![Twitter](https://img.shields.io/badge/[email protected]?style=flat)](https://twitter.com/srdanrasic)
Expand Down Expand Up @@ -447,7 +447,7 @@ When you want to receive events on a specific dispatch queue, just use `context`

ReactiveKit provides NSObject extensions that makes it easy to convert delegate pattern into streams.

First make an extension on your type, UITableView in the following example, that provides a reactive delegate proxy:
First make an extension on your type, UITableView in this example, that provides a reactive delegate proxy:

```swift
extension UITableView {
Expand All @@ -462,12 +462,14 @@ You can then convert methods of that protocol into streams:
```swift
extension UITableView {
var selectedRow: Stream<Int> {
return rDelegate.streamFor(#selector(UITableViewDelegate.tableView(_:didSelectRowAtIndexPath:))) { (_: UITableView, indexPath: NSIndexPath) in indexPath.row }
return rDelegate.stream(#selector(UITableViewDelegate.tableView(_:didSelectRowAtIndexPath:))) { (s: PushStream<Int>, _: UITableView, indexPath: NSIndexPath) in
s.next(indexPath.row)
}
}
}
```

Method `streamFor` takes two parameters: a selector to convert to a stream and a mapping closure that maps selector method arguments into a stream.
Method `stream` takes two parameters: a selector of a method to convert to a stream and a closure that is invoked on each method call. You should use that closure to push events into the given `PushStream`. Method returns that `PushStream` mapped to a `Stream`.

Now you can do:

Expand All @@ -479,23 +481,25 @@ tableView.selectedRow.observeNext { row in

Protocol proxy takes up delegate slot of the object so if you also need to implement delegate methods manually, don't set `tableView.delegate = x`, rather set `tableView.rDelegate.forwardTo = x`.

Protocol methods that return values are usually used to query data. Such methods can be set up to be fed from a property type. For example:
Note that it is you who must ensure that the parameters in the `dispatch` closure are correctly typed. For example, if there is no specific type you can use Void stream.

```swift
let numberOfItems = Property(12)

tableView.rDataSource.feed(
numberOfItems,
to: #selector(UITableViewDataSource.tableView(_:numberOfRowsInSection:)),
map: { (value: Int, _: UITableView, _: Int) -> Int in value }
)
```swift
let _ = rDelegate.stream(#selector(UITextViewDelegate.textViewDidBeginEditing(_:))) { (s: PushStream<Void>, _: UITextView) in
s.next()
}
```

Method `feed` takes three parameters: a property to feed from, a selector, and a mapping closure that maps from the property value and selector method arguments to the selector method return value.
If a protocol method has return value then you must handle it by returning it in the `dispatch` closure.

You should not set more that one feed property per selector.
```swift
let _ = rDelegate.stream(#selector(UITextViewDelegate.textView(_:shouldChangeTextInRange:replacementText:))) { (s: PushStream<String>, _: UITextView, range: NSRange, text: NSString) -> Bool in
s.next(text as String)
return true
}
```

Note that in the mapping closures of both `streamFor` and `feed` methods you must be explicit about argument and return types. Also, **you must use ObjC types as this is ObjC API**. For example, use `NSString` instead of `String`.
Note that **you must use ObjC types as this is ObjC API** in the place of proxied method argument parameters. For example, use `NSString` instead of `String`.

## Requirements

Expand Down Expand Up @@ -523,14 +527,14 @@ Note that in the mapping closures of both `streamFor` and `feed` methods you mus
### CocoaPods

```
pod 'ReactiveKit', '~> 2.0'
pod 'ReactiveKit', '~> 2.1'
pod 'ReactiveUIKit', '~> 2.0'
```

### Carthage

```
github "ReactiveKit/ReactiveKit" ~> 2.0
github "ReactiveKit/ReactiveKit" ~> 2.1
github "ReactiveKit/ReactiveUIKit" ~> 2.0
```

Expand Down
4 changes: 2 additions & 2 deletions ReactiveKit.podspec
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
Pod::Spec.new do |s|
s.name = "ReactiveKit"
s.version = "2.0.4"
s.version = "2.1.0"
s.summary = "A Swift Reactive Programming Framework"
s.description = "ReactiveKit is a collection of Swift frameworks for reactive and functional reactive programming."
s.homepage = "https://github.com/ReactiveKit/ReactiveKit"
s.license = 'MIT'
s.author = { "Srdan Rasic" => "[email protected]" }
s.source = { :git => "https://github.com/ReactiveKit/ReactiveKit.git", :tag => "v2.0.4" }
s.source = { :git => "https://github.com/ReactiveKit/ReactiveKit.git", :tag => "v2.1.0" }

s.ios.deployment_target = '8.0'
s.osx.deployment_target = '10.9'
Expand Down
4 changes: 4 additions & 0 deletions ReactiveKit.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
16C33B851BEFBAC900A0DBE0 /* ReactiveKit.h in Headers */ = {isa = PBXBuildFile; fileRef = ECBCCDD31BEB6B9A00723476 /* ReactiveKit.h */; settings = {ATTRIBUTES = (Public, ); }; };
EC2515771CBD4E0700175926 /* StreamTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC2515751CBD4E0000175926 /* StreamTests.swift */; };
EC25158F1CBFB6A400175926 /* ArrayDiffTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC8A9A171CABDA5F0042A6AD /* ArrayDiffTests.swift */; };
EC5367361D05C33B000D6045 /* ProtocolProxyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC5367351D05C33B000D6045 /* ProtocolProxyTests.swift */; };
EC65A0B31CBFEE4D00B41FA7 /* OperationTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC65A0B21CBFEE4D00B41FA7 /* OperationTests.swift */; };
EC8A99E71CABD9B50042A6AD /* CollectionProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC8A99DB1CABD9B50042A6AD /* CollectionProperty.swift */; };
EC8A99E81CABD9B50042A6AD /* CollectionProperty.swift in Sources */ = {isa = PBXBuildFile; fileRef = EC8A99DB1CABD9B50042A6AD /* CollectionProperty.swift */; };
Expand Down Expand Up @@ -106,6 +107,7 @@
16C33B161BEFB9CB00A0DBE0 /* ReactiveKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ReactiveKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
16C33B241BEFBA0100A0DBE0 /* ReactiveKit.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = ReactiveKit.framework; sourceTree = BUILT_PRODUCTS_DIR; };
EC2515751CBD4E0000175926 /* StreamTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = StreamTests.swift; path = Tests/StreamTests.swift; sourceTree = SOURCE_ROOT; };
EC5367351D05C33B000D6045 /* ProtocolProxyTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = ProtocolProxyTests.swift; path = Tests/ProtocolProxyTests.swift; sourceTree = SOURCE_ROOT; };
EC65A0B21CBFEE4D00B41FA7 /* OperationTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = OperationTests.swift; path = Tests/OperationTests.swift; sourceTree = SOURCE_ROOT; };
EC8A99DB1CABD9B50042A6AD /* CollectionProperty.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = CollectionProperty.swift; path = Sources/CollectionProperty.swift; sourceTree = SOURCE_ROOT; };
EC8A99DC1CABD9B50042A6AD /* Disposable.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = Disposable.swift; path = Sources/Disposable.swift; sourceTree = SOURCE_ROOT; };
Expand Down Expand Up @@ -226,6 +228,7 @@
EC2515751CBD4E0000175926 /* StreamTests.swift */,
EC65A0B21CBFEE4D00B41FA7 /* OperationTests.swift */,
168103431D046388007D1DD4 /* CollectionPropertyTests.swift */,
EC5367351D05C33B000D6045 /* ProtocolProxyTests.swift */,
168103441D046388007D1DD4 /* Helpers.swift */,
ECBCCDE11BEB6B9B00723476 /* Info.plist */,
);
Expand Down Expand Up @@ -544,6 +547,7 @@
buildActionMask = 2147483647;
files = (
168103451D046388007D1DD4 /* CollectionPropertyTests.swift in Sources */,
EC5367361D05C33B000D6045 /* ProtocolProxyTests.swift in Sources */,
EC2515771CBD4E0700175926 /* StreamTests.swift in Sources */,
EC25158F1CBFB6A400175926 /* ArrayDiffTests.swift in Sources */,
168103461D046388007D1DD4 /* Helpers.swift in Sources */,
Expand Down
2 changes: 1 addition & 1 deletion ReactiveKit/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.0.4</string>
<string>2.1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
Expand Down
Loading

0 comments on commit 3c1bc7e

Please sign in to comment.