Skip to content

Commit 68484a6

Browse files
tarunonkzaher
authored andcommitted
Remove DelegateProxy.Delegate type condition.
1 parent 1c04622 commit 68484a6

File tree

3 files changed

+95
-29
lines changed

3 files changed

+95
-29
lines changed

RxCocoa/Common/DelegateProxy.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
/// Base class for `DelegateProxyType` protocol.
1919
///
2020
/// This implementation is not thread safe and can be used only from one thread (Main thread).
21-
open class DelegateProxy<P: AnyObject, D: AnyObject>: _RXDelegateProxy {
21+
open class DelegateProxy<P: AnyObject, D>: _RXDelegateProxy {
2222
public typealias ParentObject = P
2323
public typealias Delegate = D
2424

@@ -28,17 +28,17 @@
2828
/// Parent object associated with delegate proxy.
2929
private weak private(set) var _parentObject: ParentObject?
3030

31-
fileprivate let _currentDelegateFor: (ParentObject) -> Delegate?
32-
fileprivate let _setCurrentDelegateTo: (Delegate?, ParentObject) -> ()
31+
fileprivate let _currentDelegateFor: (ParentObject) -> AnyObject?
32+
fileprivate let _setCurrentDelegateTo: (AnyObject?, ParentObject) -> ()
3333

3434
/// Initializes new instance.
3535
///
3636
/// - parameter parentObject: Optional parent object that owns `DelegateProxy` as associated object.
3737
public init<Proxy: DelegateProxyType>(parentObject: ParentObject, delegateProxy: Proxy.Type)
3838
where Proxy: DelegateProxy<ParentObject, Delegate>, Proxy.ParentObject == ParentObject, Proxy.Delegate == Delegate {
3939
self._parentObject = parentObject
40-
self._currentDelegateFor = delegateProxy.currentDelegate(for:)
41-
self._setCurrentDelegateTo = delegateProxy.setCurrentDelegate(_:to:)
40+
self._currentDelegateFor = delegateProxy._currentDelegate
41+
self._setCurrentDelegateTo = delegateProxy._setCurrentDelegate
4242

4343
MainScheduler.ensureExecutingOnScheduler()
4444
#if TRACE_RESOURCES

RxCocoa/Common/DelegateProxyType.swift

Lines changed: 39 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -74,7 +74,7 @@ Since RxCocoa needs to automagically create those Proxys and because views that
7474
*/
7575
public protocol DelegateProxyType: class {
7676
associatedtype ParentObject: AnyObject
77-
associatedtype Delegate: AnyObject
77+
associatedtype Delegate
7878

7979
/// It is require that enumerate call `register` of the extended DelegateProxy subclasses here.
8080
static func registerKnownImplementations()
@@ -130,6 +130,25 @@ extension DelegateProxyType {
130130
}
131131
}
132132

133+
// workaround of Delegate: class
134+
extension DelegateProxyType {
135+
static func _currentDelegate(for object: ParentObject) -> AnyObject? {
136+
return currentDelegate(for: object).map { $0 as AnyObject }
137+
}
138+
139+
static func _setCurrentDelegate(_ delegate: AnyObject?, to object: ParentObject) {
140+
return setCurrentDelegate(castOptionalOrFatalError(delegate), to: object)
141+
}
142+
143+
func _forwardToDelegate() -> AnyObject? {
144+
return forwardToDelegate().map { $0 as AnyObject }
145+
}
146+
147+
func _setForwardToDelegate(_ forwardToDelegate: AnyObject?, retainDelegate: Bool) {
148+
return setForwardToDelegate(castOptionalOrFatalError(forwardToDelegate), retainDelegate: retainDelegate)
149+
}
150+
}
151+
133152
extension DelegateProxyType {
134153

135154
/// Store DelegateProxy subclass to factory.
@@ -168,8 +187,7 @@ extension DelegateProxyType {
168187

169188
let maybeProxy = self.assignedProxy(for: object)
170189

171-
// Type is ideally be `(Self & Delegate)`, but Swift 3.0 doesn't support it.
172-
let proxy: Delegate
190+
let proxy: AnyObject
173191
if let existingProxy = maybeProxy {
174192
proxy = existingProxy
175193
}
@@ -178,15 +196,15 @@ extension DelegateProxyType {
178196
self.assignProxy(proxy, toObject: object)
179197
assert(self.assignedProxy(for: object) === proxy)
180198
}
181-
let currentDelegate = self.currentDelegate(for: object)
199+
let currentDelegate = self._currentDelegate(for: object)
182200
let delegateProxy: Self = castOrFatalError(proxy)
183201

184202
if currentDelegate !== delegateProxy {
185-
delegateProxy.setForwardToDelegate(currentDelegate, retainDelegate: false)
186-
assert(delegateProxy.forwardToDelegate() === currentDelegate)
187-
self.setCurrentDelegate(proxy, to: object)
188-
assert(self.currentDelegate(for: object) === proxy)
189-
assert(delegateProxy.forwardToDelegate() === currentDelegate)
203+
delegateProxy._setForwardToDelegate(currentDelegate, retainDelegate: false)
204+
assert(delegateProxy._forwardToDelegate() === currentDelegate)
205+
self._setCurrentDelegate(proxy, to: object)
206+
assert(self._currentDelegate(for: object) === proxy)
207+
assert(delegateProxy._forwardToDelegate() === currentDelegate)
190208
}
191209

192210
return delegateProxy
@@ -200,10 +218,10 @@ extension DelegateProxyType {
200218
/// - parameter onProxyForObject: Object that has `delegate` property.
201219
/// - returns: Disposable object that can be used to clear forward delegate.
202220
public static func installForwardDelegate(_ forwardDelegate: Delegate, retainDelegate: Bool, onProxyForObject object: ParentObject) -> Disposable {
203-
weak var weakForwardDelegate: AnyObject? = forwardDelegate
221+
weak var weakForwardDelegate: AnyObject? = forwardDelegate as AnyObject
204222
let proxy = self.proxy(for: object)
205223

206-
assert(proxy.forwardToDelegate() === nil, "This is a feature to warn you that there is already a delegate (or data source) set somewhere previously. The action you are trying to perform will clear that delegate (data source) and that means that some of your features that depend on that delegate (data source) being set will likely stop working.\n" +
224+
assert(proxy._forwardToDelegate() === nil, "This is a feature to warn you that there is already a delegate (or data source) set somewhere previously. The action you are trying to perform will clear that delegate (data source) and that means that some of your features that depend on that delegate (data source) being set will likely stop working.\n" +
207225
"If you are ok with this, try to set delegate (data source) to `nil` in front of this operation.\n" +
208226
" This is the source object value: \(object)\n" +
209227
" This this the original delegate (data source) value: \(proxy.forwardToDelegate()!)\n" +
@@ -216,7 +234,7 @@ extension DelegateProxyType {
216234

217235
let delegate: AnyObject? = weakForwardDelegate
218236

219-
assert(delegate == nil || proxy.forwardToDelegate() === delegate, "Delegate was changed from time it was first set. Current \(String(describing: proxy.forwardToDelegate())), and it should have been \(proxy)")
237+
assert(delegate == nil || proxy._forwardToDelegate() === delegate, "Delegate was changed from time it was first set. Current \(String(describing: proxy.forwardToDelegate())), and it should have been \(proxy)")
220238

221239
proxy.setForwardToDelegate(nil, retainDelegate: retainDelegate)
222240
}
@@ -225,27 +243,25 @@ extension DelegateProxyType {
225243

226244

227245
// fileprivate extensions
228-
extension DelegateProxyType
229-
{
246+
extension DelegateProxyType {
230247
fileprivate static var factory: DelegateProxyFactory {
231248
return DelegateProxyFactory.sharedFactory(for: self)
232249
}
233250

234-
235-
fileprivate static func assignedProxy(for object: ParentObject) -> Delegate? {
251+
fileprivate static func assignedProxy(for object: ParentObject) -> AnyObject? {
236252
let maybeDelegate = objc_getAssociatedObject(object, self.identifier)
237-
return castOptionalOrFatalError(maybeDelegate.map { $0 as AnyObject })
253+
return castOptionalOrFatalError(maybeDelegate)
238254
}
239255

240-
fileprivate static func assignProxy(_ proxy: Delegate, toObject object: ParentObject) {
256+
fileprivate static func assignProxy(_ proxy: AnyObject, toObject object: ParentObject) {
241257
objc_setAssociatedObject(object, self.identifier, proxy, .OBJC_ASSOCIATION_RETAIN)
242258
}
243259
}
244260

245261
/// Describes an object that has a delegate.
246262
public protocol HasDelegate: AnyObject {
247263
/// Delegate type
248-
associatedtype Delegate: AnyObject
264+
associatedtype Delegate
249265

250266
/// Delegate
251267
var delegate: Delegate? { get set }
@@ -264,7 +280,7 @@ extension DelegateProxyType where ParentObject: HasDelegate, Self.Delegate == Pa
264280
/// Describes an object that has a data source.
265281
public protocol HasDataSource: AnyObject {
266282
/// Data source type
267-
associatedtype DataSource: AnyObject
283+
associatedtype DataSource
268284

269285
/// Data source
270286
var dataSource: DataSource? { get set }
@@ -286,7 +302,8 @@ extension DelegateProxyType where ParentObject: HasDataSource, Self.Delegate ==
286302
extension ObservableType {
287303
func subscribeProxyDataSource<DelegateProxy: DelegateProxyType>(ofObject object: DelegateProxy.ParentObject, dataSource: DelegateProxy.Delegate, retainDataSource: Bool, binding: @escaping (DelegateProxy, Event<E>) -> Void)
288304
-> Disposable
289-
where DelegateProxy.ParentObject: UIView {
305+
where DelegateProxy.ParentObject: UIView
306+
, DelegateProxy.Delegate: AnyObject {
290307
let proxy = DelegateProxy.proxy(for: object)
291308
let unregisterDelegate = DelegateProxy.installForwardDelegate(dataSource, retainDelegate: retainDataSource, onProxyForObject: object)
292309
// this is needed to flush any delayed old state (https://github.com/RxSwiftCommunity/RxDataSources/pull/75)
@@ -368,8 +385,7 @@ extension DelegateProxyType where ParentObject: HasDataSource, Self.Delegate ==
368385
_identifier = proxyType.identifier
369386
}
370387

371-
fileprivate func extend<DelegateProxy: DelegateProxyType, ParentObject>(make: @escaping (ParentObject) -> DelegateProxy)
372-
{
388+
fileprivate func extend<DelegateProxy: DelegateProxyType, ParentObject>(make: @escaping (ParentObject) -> DelegateProxy) {
373389
MainScheduler.ensureExecutingOnScheduler()
374390
precondition(_identifier == DelegateProxy.identifier, "Delegate proxy has inconsistent identifier")
375391
precondition((DelegateProxy.self as? DelegateProxy.Delegate) != nil, "DelegateProxy subclass should be as a Delegate")

Tests/RxCocoaTests/DelegateProxyTest.swift

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ import UIKit
3232

3333
protocol TestDelegateControl: NSObjectProtocol {
3434
associatedtype TestParentObject: AnyObject
35-
associatedtype TestDelegate: NSObjectProtocol
35+
associatedtype TestDelegate
3636
func doThatTest(_ value: Int)
3737

3838
var delegateProxy: DelegateProxy<TestParentObject, TestDelegate> { get }
@@ -348,6 +348,19 @@ extension DelegateProxyTest {
348348
}
349349
}
350350

351+
extension DelegateProxyTest {
352+
func test_InstallPureSwiftDelegateProxy() {
353+
let view = PureSwiftView()
354+
let mock = MockPureSwiftDelegate()
355+
356+
view.delegate = mock
357+
358+
let proxy = view.rx.proxy
359+
XCTAssertTrue(view.delegate === proxy)
360+
XCTAssertTrue(view.rx.proxy.forwardToDelegate() === mock)
361+
}
362+
}
363+
351364
#if os(iOS)
352365
extension DelegateProxyTest {
353366
func test_DelegateProxyHierarchyWorks() {
@@ -614,6 +627,43 @@ class ExtendClassViewDelegateProxy_b: InitialClassViewDelegateProxy {
614627
}
615628
}
616629

630+
631+
protocol PureSwiftDelegate: class {}
632+
633+
class PureSwiftView: ReactiveCompatible {
634+
weak var delegate: PureSwiftDelegate?
635+
}
636+
637+
extension Reactive where Base: PureSwiftView {
638+
var proxy: DelegateProxy<PureSwiftView, PureSwiftDelegate> {
639+
return PureSwiftDelegateProxy.proxy(for: base)
640+
}
641+
}
642+
643+
class PureSwiftDelegateProxy
644+
: DelegateProxy<PureSwiftView, PureSwiftDelegate>
645+
, DelegateProxyType
646+
, PureSwiftDelegate {
647+
648+
init(parentObject: PureSwiftView) {
649+
super.init(parentObject: parentObject, delegateProxy: PureSwiftDelegateProxy.self)
650+
}
651+
652+
static func registerKnownImplementations() {
653+
self.register { PureSwiftDelegateProxy.init(parentObject: $0) }
654+
}
655+
656+
static func currentDelegate(for object: ParentObject) -> PureSwiftDelegate? {
657+
return object.delegate
658+
}
659+
660+
static func setCurrentDelegate(_ delegate: PureSwiftDelegate?, to object: ParentObject) {
661+
return object.delegate = delegate
662+
}
663+
}
664+
665+
final class MockPureSwiftDelegate: PureSwiftDelegate {}
666+
617667
// }
618668

619669
#if os(macOS)

0 commit comments

Comments
 (0)