-
Notifications
You must be signed in to change notification settings - Fork 496
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add generic ValueType to RACSignal and RACCommand #15
Conversation
This had been discussed before, and the lightweight generics system was deemed very limited to be worthless at that time. Would you mind to show if the issues are addressed? |
@andersio thanks for taking a look. I've laid out the case for this in #12. As stated there, this is primarily for adding type annotations to existing signals for clarity and improving bridging to Swift, and expressly not for having the compiler help out with type mismatches when writing signal chains in Objective-C (the issue you linked to). Let me know if you feel like any justification is missing from #12, or if that isn't enough to merit this change. |
As a concrete example, I can show the difference in the bridging functions that would be available with this change. Currently, extension RACSignal {
public func toSignalProducer(file: String = #file, line: Int = #line) -> SignalProducer<Any?, NSError> {
return SignalProducer { observer, disposable in
let next = { obj in
observer.send(value: obj)
}
let failed: (_ nsError: Swift.Error?) -> () = {
observer.send(error: ($0 as? NSError) ?? defaultNSError("Nil RACSignal error", file: file, line: line))
}
let completed = {
observer.sendCompleted()
}
disposable += self.subscribeNext(next, error: failed, completed: completed)
}
}
} However, with this change, it can be updated to the following: public func signalProducer<Value>(from signal: RACSignal<Value>, file: String = #file, line: Int = #line) -> SignalProducer<Value?, NSError> {
return SignalProducer<Value?, NSError> { observer, disposable in
let next: (_ value: Value?) -> Void = { obj in
observer.send(value: obj)
}
let failed: (_ nsError: Swift.Error?) -> () = {
observer.send(error: ($0 as? NSError) ?? defaultNSError("Nil RACSignal error", file: file, line: line))
}
let completed = {
observer.sendCompleted()
}
disposable += signal.subscribeNext(next, error: failed, completed: completed)
}
} Note the difference in return types—before you get a |
You still can't express the semantics of Since you can always opt to not annotate the type, I don't see any reason to not do this. Have you tried using this in your codebase? I'm interested to hear how it works in practice. |
I see now that you answered that in #12. I'm still interested to hear about how this been practically in your codebase. |
@mdiep we haven't started integrating these changes specifically into our codebase. However, we've really enjoyed the benefits of adding lightweight generics to
|
I'm on board. 👍 I'll try to give this a proper review soon unless someone beats me to it. (RAC 5 and Carthage are keeping me busy atm.) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These changes look great. 👍
But are these a breaking change from 1.0?
@@ -180,7 +180,7 @@ NS_ASSUME_NONNULL_BEGIN | |||
/// Additional methods to assist with unit testing. | |||
/// | |||
/// **These methods should never ship in production code.** | |||
@interface RACSignal (Testing) | |||
@interface RACSignal<__covariant ValueType> (Testing) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is this sort of change required? i.e., is adding generics a breaking change?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No, this change was not enforced by the compiler—I just added it so that asynchronousFirstOrDefault
could have access to ValueType
. Note that RACSignal (Debugging)
does not have it as part of this change.
If someone is using RACObjC in the legacy RAC2.5 way (no generics, no Swift bridging), this should not be a breaking change. However, I know of two ways that this could be a breaking change for some users:
|
How would you suggest approaching this from a versioning perspective? |
Since there have been no changes to the implementation of ReactiveObjC, I would consider this to be a minor change to the framework. There may be some errors produced on migration, but they are easily recoverable, and only affect consumers that are using a recent API. However, I'd suggest that this would be a major/breaking change to ReactiveObjCBridge, since we'd have to change the way that signals are currently bridged from Obj-C to Swift as part of this change. |
We discussed this and decide to merge and do a 2.0 release. |
ReactiveObjC: Adapt to Xcode 9.3.
Add generic ValueType to RACSignal and RACCommand
See #12
I've made sure that this generic type can be bridged to
SignalProducer
/Signal
by adding a new free function to https://github.com/ReactiveCocoa/ReactiveObjCBridge/ as a test.I can start a pull request there as well (if desired) that integrates this pull request.