Skip to content

Commit a1e6be8

Browse files
committed
Improves error reporting.
1 parent 582da06 commit a1e6be8

File tree

2 files changed

+29
-12
lines changed

2 files changed

+29
-12
lines changed

RxCocoa/Common/DelegateProxy.swift

Lines changed: 27 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -91,15 +91,14 @@
9191
*/
9292
open func sentMessage(_ selector: Selector) -> Observable<[Any]> {
9393
MainScheduler.ensureExecutingOnScheduler()
94-
checkSelectorIsObservable(selector)
9594

9695
let subject = _sentMessageForSelector[selector]
9796

9897
if let subject = subject {
9998
return subject.asObservable()
10099
}
101100
else {
102-
let subject = MessageDispatcher(delegateProxy: self)
101+
let subject = MessageDispatcher(selector: selector, delegateProxy: self)
103102
_sentMessageForSelector[selector] = subject
104103
return subject.asObservable()
105104
}
@@ -149,30 +148,36 @@
149148
*/
150149
open func methodInvoked(_ selector: Selector) -> Observable<[Any]> {
151150
MainScheduler.ensureExecutingOnScheduler()
152-
checkSelectorIsObservable(selector)
153151

154152
let subject = _methodInvokedForSelector[selector]
155153

156154
if let subject = subject {
157155
return subject.asObservable()
158156
}
159157
else {
160-
let subject = MessageDispatcher(delegateProxy: self)
158+
let subject = MessageDispatcher(selector: selector, delegateProxy: self)
161159
_methodInvokedForSelector[selector] = subject
162160
return subject.asObservable()
163161
}
164162
}
165163

166-
private func checkSelectorIsObservable(_ selector: Selector) {
164+
fileprivate func checkSelectorIsObservable(_ selector: Selector) {
167165
MainScheduler.ensureExecutingOnScheduler()
168166

169167
if hasWiredImplementation(for: selector) {
170-
print("Delegate proxy is already implementing `\(selector)`, a more performant way of registering might exist.")
168+
print("⚠️ Delegate proxy is already implementing `\(selector)`, a more performant way of registering might exist.")
171169
return
172170
}
173171

174-
guard ((self.forwardToDelegate() as? NSObject)?.responds(to: selector) ?? false) || voidDelegateMethodsContain(selector) else {
175-
rxFatalError("This class doesn't respond to selector \(selector)")
172+
if voidDelegateMethodsContain(selector) {
173+
return
174+
}
175+
176+
// In case `_forwardToDelegate` is `nil`, it is assumed the check is being done prematurely.
177+
if !(self._forwardToDelegate?.responds(to: selector) ?? true) {
178+
print("⚠️ Using delegate proxy dynamic interception method but the target delegate object doesn't respond to the requested selector. " +
179+
"In case pure Swift delegate proxy is being used please use manual observing method by using`PublishSubject`s. " +
180+
" (selector: `\(selector)`, forwardToDelegate: `\(_forwardToDelegate ?? self)`)")
176181
}
177182
}
178183

@@ -204,6 +209,15 @@
204209
MainScheduler.ensureExecutingOnScheduler()
205210
#endif
206211
self._setForwardToDelegate(delegate, retainDelegate: retainDelegate)
212+
213+
let allUsedSelectors: [Selector] =
214+
self._sentMessageForSelector.values.filter { $0.hasObservers }.map { $0.selector } +
215+
self._methodInvokedForSelector.values.filter { $0.hasObservers }.map { $0.selector }
216+
217+
for selector in Set(allUsedSelectors) {
218+
checkSelectorIsObservable(selector)
219+
}
220+
207221
self.reset()
208222
}
209223

@@ -250,14 +264,17 @@
250264
private let dispatcher: PublishSubject<[Any]>
251265
private let result: Observable<[Any]>
252266

253-
init<P, D>(delegateProxy _delegateProxy: DelegateProxy<P, D>) {
267+
fileprivate let selector: Selector
268+
269+
init<P, D>(selector: Selector, delegateProxy _delegateProxy: DelegateProxy<P, D>) {
254270
weak var weakDelegateProxy = _delegateProxy
255271

256272
let dispatcher = PublishSubject<[Any]>()
257273
self.dispatcher = dispatcher
274+
self.selector = selector
258275

259276
self.result = dispatcher
260-
.do(onSubscribed: { weakDelegateProxy?.reset() }, onDispose: { weakDelegateProxy?.reset() })
277+
.do(onSubscribed: { weakDelegateProxy?.checkSelectorIsObservable(selector); weakDelegateProxy?.reset() }, onDispose: { weakDelegateProxy?.reset() })
261278
.share()
262279
.subscribeOn(mainScheduler)
263280
}

RxSwift/Rx.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ func decrementChecked(_ i: inout Int) throws -> Int {
9393

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

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

0 commit comments

Comments
 (0)