yankodimitrov / signalkit Goto Github PK
View Code? Open in Web Editor NEWSignalKit is a reactive Swift framework with focus on clean and readable API.
License: MIT License
SignalKit is a reactive Swift framework with focus on clean and readable API.
License: MIT License
How about Swift 3.0 compatible version or branch?
I have two signals, one from color picker and second from UISlider
(to pick color alpha):
let pickedColor = Signal<UIColor>()
let pickedAlpha = Signal<Float>()
I'd like to combine these two signals, so the obvious way is to use combineLatestWith
:
let _ = pickedColor.combineLatestWith(pickedAlpha).next { color, alpha in
print("color: \(color)\talpha: \(alpha)")
}.disposeWith(disposableBag)
The values are not printed, until both controls do their first sendNext
, which is expected.
I cannot wrap my head around the "nice" way to make that initial signals from both controls. Currently, what I do the next line after setting up combineLatestWith
is:
pickedColor.sendNext(colorPicker.color)
pickedAlpha.sendNext(alphaSlider.value)
...but, I feel like I'm missing something obvious from FRP.
When I try build 3.0 version from master, I get following errors
Use of undeclared CollectionChangeSet type
Use of undeclared ListOperationType
I really like this framework API and I would like to use it in our project. Could you fix this issue please? Thank you!
When I take the following sample code from the Readme.md performBatchUpdate
doesn't work.
let sectionOne = ObservableArray([1, 2])
let sectionTwo = ObservableArray([3, 4])
let list = ObservableArray<ObservableArray<Int>>([sectionOne, sectionTwo])
list.observe()
.bindTo(tableView: tableView, dataSource: dataSource)
.addTo(signalsBag)
list.performBatchUpdate { collection in
collection[0].append(22)
collection[0].removeAtIndex(0)
collection.removeAtIndex(1)
}
I traced this to an issue with the wrong initialiser being called for ArrayBindingObserver
list.observe()
is defined in ObservableArray.swift Ln: 165, as:
public func observe() -> ArrayBindingObserver<ElementType> {
return ArrayBindingObserver(array: self)
}
For the case above ElementType is ObservableArray<Int>
, so the type of self
is ObservableArray<ObservableArray<Int>>
.
Swift doesn't seem to be able to correctly match the correct initialiser, so observe()
ends up calling the convenience initialiser in ArrayBindingObserver.swift Ln: 27:
public convenience init(array: ObservableArray<T>) {
let sectionsArray = ObservableArray<ObservableArray<T>>([array])
self.init(array: sectionsArray)
}
But T
here is already ObservableArray<Int>
and so it gets wrapped in an additional Observable<T>
leading to a type of ObservableArray<ObservableArray<ObservableArray<Int>>>
It should be calling:
public init(array: ObservableArray<ObservableArray<T>>) {
self.array = array
observeForArrayEvent()
setupSectionObservers()
}
Please add support of OSX in Podspec file that will include all except UIKit extensions.
First of all, great library, really simple API!
For example:
var o1 = ObservableValue("Rose")
s = observe(o1)
.next { println($0) }
If I don't call dispatch
, the next
block will never be invoked. Is it possible to have an option to invoke the next block when attached?
Currently the UIKit bindings are based on free functions. Instead we can move them in generic type extensions on the Signal
type.
For example:
// In Swift 1.2
observe(viewModel.name)
.bindTo( textIn(nameLabel) )
will become :
// In Swift 2.0
observe(viewModel.name)
.bindTo(textIn: nameLabel)
๐
Any tips for creating a timer signal? Here's what I tried throwing together based on examples and a gesture recognizer signal I made that does work, but it doesn't fire.
public extension Signal {
// in case of a Timer, we dont start with an object on which we bootstrap a signal
// so add this class method on Signal itself for creating a timer signal (can we make this a convenience init instead?)
public class func repeatingTimer(withInterval interval: TimeInterval) -> Signal<Timer> {
let signal = Signal<Timer>()
let observer = IntervalTimerOperator(interval: interval)
observer.callback = { [weak signal] timer in
signal?.send(timer)
}
signal.disposableSource = observer
return signal
}
}
final class IntervalTimerOperator: NSObject, Disposable {
private var timer: Timer!
private var isDisposed = false
internal var callback: ((_ timer: Timer) -> Void)?
init(interval: TimeInterval, repeats: Bool = true) {
super.init()
self.timer = Timer(timeInterval: interval, target: self, selector: #selector(fire(_:)), userInfo: nil, repeats: repeats)
}
func fire(_: Timer) {
callback?(timer)
}
func dispose() {
guard !isDisposed else { return }
timer.invalidate()
isDisposed = true
}
}
This project is awesome. The syntax is much more vivid then ReactiveCocoa. But I just found some inconvenience.
Since we can combine several signals(Boolean wrapped in NSNumber) together with ReactiveCocoa:
RAC(getCodeButton, "enabled") <-- RACSignal.combineLatest([validMobileSignal, isCountingSignal]).and()
While with SignalKit:
combineLatest(mobileSignal, passwordSignal, smsCodeSignal)
.map { $0.0 == $0.1 == $0.2 == true }
.bindTo( isEnabled(fetchCodeButton) )
What if we add some convenient funcs like what ReactiveCocoa did.
combineLatest(mobileSignal, passwordSignal, smsCodeSignal).and()
.bindTo( isEnabled(fetchCodeButton) )
Let's support just .all()
and .some()
.
It will prevent memory leaks.
Something like this:
public final class DisposableBag: Disposable {
private lazy var bag = Bag<Disposable>()
internal var count: Int {
return bag.count
}
public init() {}
deinit {
dispose()
}
public func addDisposable(disposable: Disposable) -> Disposable {
let token = self.bag.insert(disposable)
return DisposableAction { [weak self] in
self?.bag.removeItemWithToken(token)
}
}
public func removeAll() {
bag.removeItems()
}
public func dispose() {
for disposable in self.bag {
disposable.1.dispose()
}
self.removeAll()
}
}
This fork with Swift 3 support, fails on the following Unit Test
NotificationObserverTests.testDisposeOnDeinit()
I have tried create custom class
class CustomObject: NSObject {
var age: Int
init(age: Int) {
self.age = age
}
}
then create instance
self.object = CustomObject(age: 1)
then observe the age property
self.object.observe().keyPath("age", value: self.object.age).next { print($0) }
and finally change age
self.object.age += 1
self.object.age += 1
self.object.age += 1
self.object.age += 1
self.object.age += 1
But the value is printed only once.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
๐ Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. ๐๐๐
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google โค๏ธ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.