Skip to content

Commit

Permalink
Improves error reporting.
Browse files Browse the repository at this point in the history
  • Loading branch information
kzaher committed Nov 1, 2017
1 parent 582da06 commit a1e6be8
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 12 deletions.
37 changes: 27 additions & 10 deletions RxCocoa/Common/DelegateProxy.swift
Original file line number Diff line number Diff line change
Expand Up @@ -91,15 +91,14 @@
*/
open func sentMessage(_ selector: Selector) -> Observable<[Any]> {
MainScheduler.ensureExecutingOnScheduler()
checkSelectorIsObservable(selector)

let subject = _sentMessageForSelector[selector]

if let subject = subject {
return subject.asObservable()
}
else {
let subject = MessageDispatcher(delegateProxy: self)
let subject = MessageDispatcher(selector: selector, delegateProxy: self)
_sentMessageForSelector[selector] = subject
return subject.asObservable()
}
Expand Down Expand Up @@ -149,30 +148,36 @@
*/
open func methodInvoked(_ selector: Selector) -> Observable<[Any]> {
MainScheduler.ensureExecutingOnScheduler()
checkSelectorIsObservable(selector)

let subject = _methodInvokedForSelector[selector]

if let subject = subject {
return subject.asObservable()
}
else {
let subject = MessageDispatcher(delegateProxy: self)
let subject = MessageDispatcher(selector: selector, delegateProxy: self)
_methodInvokedForSelector[selector] = subject
return subject.asObservable()
}
}

private func checkSelectorIsObservable(_ selector: Selector) {
fileprivate func checkSelectorIsObservable(_ selector: Selector) {
MainScheduler.ensureExecutingOnScheduler()

if hasWiredImplementation(for: selector) {
print("Delegate proxy is already implementing `\(selector)`, a more performant way of registering might exist.")
print("⚠️ Delegate proxy is already implementing `\(selector)`, a more performant way of registering might exist.")
return
}

guard ((self.forwardToDelegate() as? NSObject)?.responds(to: selector) ?? false) || voidDelegateMethodsContain(selector) else {
rxFatalError("This class doesn't respond to selector \(selector)")
if voidDelegateMethodsContain(selector) {
return
}

// In case `_forwardToDelegate` is `nil`, it is assumed the check is being done prematurely.
if !(self._forwardToDelegate?.responds(to: selector) ?? true) {
print("⚠️ Using delegate proxy dynamic interception method but the target delegate object doesn't respond to the requested selector. " +
"In case pure Swift delegate proxy is being used please use manual observing method by using`PublishSubject`s. " +
" (selector: `\(selector)`, forwardToDelegate: `\(_forwardToDelegate ?? self)`)")
}
}

Expand Down Expand Up @@ -204,6 +209,15 @@
MainScheduler.ensureExecutingOnScheduler()
#endif
self._setForwardToDelegate(delegate, retainDelegate: retainDelegate)

let allUsedSelectors: [Selector] =
self._sentMessageForSelector.values.filter { $0.hasObservers }.map { $0.selector } +
self._methodInvokedForSelector.values.filter { $0.hasObservers }.map { $0.selector }

for selector in Set(allUsedSelectors) {
checkSelectorIsObservable(selector)
}

self.reset()
}

Expand Down Expand Up @@ -250,14 +264,17 @@
private let dispatcher: PublishSubject<[Any]>
private let result: Observable<[Any]>

init<P, D>(delegateProxy _delegateProxy: DelegateProxy<P, D>) {
fileprivate let selector: Selector

init<P, D>(selector: Selector, delegateProxy _delegateProxy: DelegateProxy<P, D>) {
weak var weakDelegateProxy = _delegateProxy

let dispatcher = PublishSubject<[Any]>()
self.dispatcher = dispatcher
self.selector = selector

self.result = dispatcher
.do(onSubscribed: { weakDelegateProxy?.reset() }, onDispose: { weakDelegateProxy?.reset() })
.do(onSubscribed: { weakDelegateProxy?.checkSelectorIsObservable(selector); weakDelegateProxy?.reset() }, onDispose: { weakDelegateProxy?.reset() })
.share()
.subscribeOn(mainScheduler)
}
Expand Down
4 changes: 2 additions & 2 deletions RxSwift/Rx.swift
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ func decrementChecked(_ i: inout Int) throws -> Int {

if count > 1 {
synchronizationError(
"⚠️ Reentrancy anomaly was detected. ⚠️\n" +
"⚠️ Reentrancy anomaly was detected.\n" +
" > Debugging: To debug this issue you can set a breakpoint in \(#file):\(#line) and observe the call stack.\n" +
" > Problem: This behavior is breaking the observable sequence grammar. `next (error | completed)?`\n" +
" This behavior breaks the grammar because there is overlapping between sequence events.\n" +
Expand All @@ -109,7 +109,7 @@ func decrementChecked(_ i: inout Int) throws -> Int {

if _threads.count > 1 {
synchronizationError(
"⚠️ Synchronization anomaly was detected. ⚠️\n" +
"⚠️ Synchronization anomaly was detected.\n" +
" > Debugging: To debug this issue you can set a breakpoint in \(#file):\(#line) and observe the call stack.\n" +
" > Problem: This behavior is breaking the observable sequence grammar. `next (error | completed)?`\n" +
" This behavior breaks the grammar because there is overlapping between sequence events.\n" +
Expand Down

0 comments on commit a1e6be8

Please sign in to comment.