Reputation: 2259
I'm trying to migrate my FRP understanding from ReactiveCocoa 2.5 to RxSwift and I have one misunderstanding. In ReactiveCocoa, I used rac_signalForSelector
when I wanted to observe an invocation of a method. Is there any way to implement this logic using RxSwift?
I wrote a small example in which I want to dispose a subscription when the test
method invokes. But in the subscribe block I can still see a next(6)
event. What am I doing wrong?
let subject = PublishSubject<Int>()
subject.takeUntil(self.rx.sentMessage(#selector(test))).subscribe { event in
print(event)
}
subject.onNext(3)
test()
subject.onNext(6)
//////////////////
func test() {
}
Upvotes: 4
Views: 4866
Reputation: 93
Another solution, which avoids using sentMessage, is to define a testSubject and trigger a next event on it in your test function.
let subject = PublishSubject<Int>()
let testSubject = PublishSubject<Void>()
subject.takeUntil(testSubject).subscribe { event in
print(event)
}
subject.onNext(3)
test()
subject.onNext(6)
//////////////////
func test() {
testSubject.onNext(())
}
This will only print until test() is called.
Upvotes: 0
Reputation: 64
I am adding this comment after encounter the same problem but now I've solved it.
The solution for me, -- I am sorry if this is not the thing you search for but hope will help others with the same issue --, was just adding dynamic
modifier for the observed function.
This is the code
func viewDidLoad() {
rx.sentMessage(#selector(ViewController.test))
.debug("Test", trimOutput: true)
.subcribe()
.disposed(by: bag)
}
@objc dynamic test() {}
Without dynamic
modifier the call to test isn't observed because the debug doesn't print anything.
I am new to RxSwift.
Thanks @zhongwuzw above, I got the idea after read his comment.
Upvotes: 2
Reputation: 156
you should use dynamic
modifier for test
function that access to test
function is never inlined or devirtualized by the compiler.
like this:
dynamic func test() {}
Upvotes: 4
Reputation: 7729
You can use sentMessage
:
class ViewController: UIViewController {
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
self.rx.sentMessage(#selector(UIViewController.viewWillAppear(_:)))
.subscribe({ e in
print(e)
})
.addDisposableTo(disposeBag)
}
}
Outputs:
next([0])
Or another example:
class SomeNSObjectClass: NSObject {
}
class ViewController: UIViewController {
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
let myObj = SomeNSObjectClass()
myObjc.rx.sentMessage(NSSelectorFromString("dealloc"))
.subscribe({ e in
print(e)
})
.addDisposableTo(disposeBag)
}
}
}
Outputs:
next([])
completed
Upvotes: 7