mirror of
https://github.com/zhigang1992/ReactiveCocoa.git
synced 2026-04-29 04:45:24 +08:00
Minor proofreading/formatting, add other bridges and TOC
This commit is contained in:
@@ -1,60 +1,99 @@
|
||||
# Objective-C Bridging
|
||||
|
||||
While ReactiveCocoa 3.0 introduces an entirely new design, it also aims for maximum compatibility with RAC 2 to ease the pain of migration. To support interoperability with RAC 2's Objective-C APIs, RAC 3 offers bridging functions that can convert RAC 2 types to RAC 3 and vice versa.
|
||||
While ReactiveCocoa 3.0 introduces an entirely new design, it also aims for maximum compatibility with RAC 2, to ease the pain of migration. To interoperate with RAC 2’s Objective-C APIs, RAC 3 offers bridging functions that can convert Objective-C types to Swift types and vice-versa.
|
||||
|
||||
Because the APIs are based on fundamentally different designs, the conversion is not always one-to-one; however, every attempt has been made to faithfully translate the concepts between the two APIs (and languages).
|
||||
|
||||
Below is the list of common conversions currently available.
|
||||
The bridged types include:
|
||||
|
||||
### Conversion Between `RACSignal` And `SignalProducer` (or `Signal`)
|
||||
1. [`RACSignal` and `SignalProducer` or `Signal`](#racsignal-and-signalproducer-or-signal)
|
||||
1. [`RACCommand` and `Action`](#raccommand-and-action)
|
||||
1. [`RACScheduler` and `SchedulerType`](#racscheduler-and-schedulertype)
|
||||
1. [`RACDisposable` and `Disposable`](#racdisposable-and-disposable)
|
||||
|
||||
In RAC 3, "cold" signals are represented by the `SignalProducer` type, and "hot" signals are represented by the `Signal` type. ([Learn more about RAC 3's architectural changes](https://github.com/ReactiveCocoa/ReactiveCocoa/blob/swift-development/CHANGELOG.md)).
|
||||
For the complete bridging API, including documentation, see [`ObjectiveCBridging.swift`][ObjectiveCBridging]. To learn more about how to migrate between ReactiveCocoa 2 and 3, see the [CHANGELOG][].
|
||||
|
||||
"Cold" `RACSignal`s from RAC 2 can be converted to the new `SignalProducer` type using the new `toSignalProducer` method on `RACSignal`.
|
||||
## `RACSignal` and `SignalProducer` or `Signal`
|
||||
|
||||
```
|
||||
In RAC 3, “cold” signals are represented by the `SignalProducer` type, and “hot” signals are represented by the `Signal` type.
|
||||
|
||||
“Cold” `RACSignal`s can be converted into `SignalProducer`s using the new `toSignalProducer` method:
|
||||
|
||||
```swift
|
||||
extension RACSignal {
|
||||
func toSignalProducer(file: String = __FILE__, line: Int = __LINE__) -> SignalProducer<AnyObject?, NSError>
|
||||
func toSignalProducer() -> SignalProducer<AnyObject?, NSError>
|
||||
}
|
||||
```
|
||||
|
||||
"Hot" `RACSignal`s cannot be converted to `Signal`s because any `RACSignal` subscription could potentially involve side-effects. To obtain a `Signal`, use `RACSignal.toSignalProducer` followed by `SignalProducer.start`, thereby making those side effects explicit.
|
||||
“Hot” `RACSignal`s cannot be directly converted into `Signal`s, because _any_ `RACSignal` subscription could potentially involve side effects. To obtain a `Signal`, use `RACSignal.toSignalProducer` followed by `SignalProducer.start`, which will make those potential side effects explicit.
|
||||
|
||||
Use the `toRACSignal()` function to convert from `SignalProducer<AnyObject?, ErrorType>` or `Signal<AnyObject?, ErrorType>` to `RACSignal *`.
|
||||
For the other direction, use the `toRACSignal()` function.
|
||||
|
||||
```
|
||||
When called with a `SignalProducer`, these functions will create a `RACSignal` to `start()` the producer once for each subscription:
|
||||
|
||||
```swift
|
||||
func toRACSignal<T: AnyObject, E>(producer: SignalProducer<T, E>) -> RACSignal
|
||||
func toRACSignal<T: AnyObject, E>(producer: SignalProducer<T?, E>) -> RACSignal
|
||||
```
|
||||
|
||||
The `RACSignal` created by these functions will `start()` the producer once for each subscription.
|
||||
When called with a `Signal`, these functions will create a `RACSignal` that simply observes it:
|
||||
|
||||
```
|
||||
```swift
|
||||
func toRACSignal<T: AnyObject, E>(signal: Signal<T, E>) -> RACSignal
|
||||
func toRACSignal<T: AnyObject, E>(signal: Signal<T?, E>) -> RACSignal
|
||||
```
|
||||
|
||||
The `RACSignal` created by these functions will observe the given signal.
|
||||
## `RACCommand` and `Action`
|
||||
|
||||
### Conversion Between `RACCommand` And `Action`
|
||||
To convert `RACCommand`s into the new `Action` type, use the `toAction()` extension method:
|
||||
|
||||
Use `RACCommand.toAction` to convert `RACCommand *` to `Action<AnyObject?, AnyObject?, NSError>`.
|
||||
|
||||
```
|
||||
```swift
|
||||
extension RACCommand {
|
||||
func toAction(file: String = __FILE__, line: Int = __LINE__) -> Action<AnyObject?, AnyObject?, NSError>
|
||||
func toAction() -> Action<AnyObject?, AnyObject?, NSError>
|
||||
}
|
||||
```
|
||||
|
||||
Use the `toRACCommand` function to convert `Action<AnyObject?, AnyObject?, ErrorType>` to `RACCommand *`.
|
||||
To convert `Action`s into `RACCommand`s, use the `toRACCommand()` function:
|
||||
|
||||
```
|
||||
```swift
|
||||
func toRACCommand<Output: AnyObject, E>(action: Action<AnyObject, Output, E>) -> RACCommand
|
||||
func toRACCommand<Output: AnyObject, E>(action: Action<AnyObject?, Output, E>) -> RACCommand
|
||||
```
|
||||
|
||||
Unfortunately, the `executing` properties of actions and commands are not synchronized across the API bridge. To ensure consistency, only observe the `executing` property from the base object (the one passed _into_ the bridge, not retrieved from it), so updates occur no matter which object is used for execution.
|
||||
**NOTE:** The `executing` properties of actions and commands are not synchronized across the API bridge. To ensure consistency, only observe the `executing` property from the base object (the one passed _into_ the bridge, not retrieved from it), so updates occur no matter which object is used for execution.
|
||||
|
||||
### Conversion Between `SchedulerType`s And `RACScheduler`
|
||||
## `RACScheduler` and `SchedulerType`
|
||||
|
||||
TODO
|
||||
Any `RACScheduler` instance is automatically a `DateSchedulerType` (and therefore a `SchedulerType`), and can be passed directly into any function or method that expects one.
|
||||
|
||||
Some (but not all) `SchedulerType`s from RAC 3 can be converted into `RACScheduler` instances, using the `toRACScheduler()` method:
|
||||
|
||||
```swift
|
||||
extension ImmediateScheduler {
|
||||
func toRACScheduler() -> RACScheduler
|
||||
}
|
||||
|
||||
extension UIScheduler {
|
||||
func toRACScheduler() -> RACScheduler
|
||||
}
|
||||
|
||||
extension QueueScheduler {
|
||||
func toRACScheduler() -> RACScheduler
|
||||
}
|
||||
```
|
||||
|
||||
## `RACDisposable` and `Disposable`
|
||||
|
||||
Any `RACDisposable` instance is automatically a `Disposable`, and can be used directly anywhere a type conforming to `Disposable` is expected.
|
||||
|
||||
Although there is no direct conversion from `Disposable` into `RACDisposable`, it is easy to do manually:
|
||||
|
||||
```swift
|
||||
let swiftDisposable: Disposable
|
||||
let objcDisposable = RACDisposable {
|
||||
swiftDisposable.dispose()
|
||||
}
|
||||
```
|
||||
|
||||
[CHANGELOG]: ../CHANGELOG.md
|
||||
[ObjectiveCBridging]: ../ReactiveCocoa/Swift/ObjectiveCBridging.swift
|
||||
|
||||
Reference in New Issue
Block a user