-
-
Save thekarladam/c3974dc545d56b41ee5b to your computer and use it in GitHub Desktop.
protocol DelegateOwningType { | |
typealias DelegateType | |
var delegate : DelegateType { get set } | |
} | |
class DelegatedOperation <T : DelegateOwningType, TDelegate where T.DelegateType == TDelegate.Type>: NSOperation { | |
let authority : T | |
var delegate : TDelegate | |
init(someT : T, someTD : TDelegate) { | |
authority = someT | |
delegate = someTD | |
authority.delegate = someTD | |
super.init() | |
} | |
} |
So close…
Forcing preexisting types to conform remains the problem
class FooBar : NSNetServiceBrowser {
}
protocol DelegateOwningType {
typealias DelegateType : AnyObject
unowned(unsafe) var delegate : DelegateType { get set }
}
extension NSNetServiceBrowser : DelegateOwningType {}
class DelegatedOperation <T : DelegateOwningType>: NSOperation {
var authority : T
var delegate : T.DelegateType
init(someT : T, someTD : T.DelegateType) {
authority = someT
delegate = someTD
authority.delegate = someTD
super.init()
}
}
class Bar : NSObject, NSNetServiceDelegate {
}
let testOp = DelegatedOperation<NSNetServiceBrowser>(NSNetServiceBrowser(), Bar())
I was able to get this to compile, matching the optionality of the delegate
property on NSNetServiceBrowser, and making its delegate typealias explicit (even though we ought to infer it):
import Foundation
class FooBar : NSNetServiceBrowser {
}
protocol DelegateOwningType {
typealias DelegateType : AnyObject
var delegate : DelegateType? { get set }
}
extension NSNetServiceBrowser : DelegateOwningType {
// Should be able to infer this...
typealias DelegateType = NSNetServiceBrowserDelegate
}
class DelegatedOperation <T : DelegateOwningType>: NSOperation {
var authority : T
var delegate : T.DelegateType
init(someT : T, someTD : T.DelegateType) {
authority = someT
delegate = someTD
authority.delegate = someTD
super.init()
}
}
class Bar : NSObject, NSNetServiceBrowserDelegate {
}
let testOp = DelegatedOperation<NSNetServiceBrowser>(someT: NSNetServiceBrowser(), someTD: Bar())
enum Result<T, Error: ErrorType> {
case Success(T)
case Failure(Error)
}
protocol RequiredWorkerMethods {
typealias ResultType
func begin(authority : AnyObject)
var finish : (ResultType) -> Void { get set }
var result : ResultType { get set }
}
protocol DelegateOwningType : AnyObject {
typealias DelegateType
// typealias SubclassedDelegateType = protocol<RequiredWorkerMethods, DelegateType>
var delegate : DelegateType? { get set }
}
extension NSNetServiceBrowser : DelegateOwningType {
typealias DelegateType = NSNetServiceBrowserDelegate
}
extension NSNetServicesError : ErrorType {}
protocol ConcreteWorker : RequiredWorkerMethods {
typealias AuthorityType
}
class DelegatedOperation <T : DelegateOwningType, ConcreteDelegateType : ConcreteWorker, WorkProductType
where ConcreteDelegateType.AuthorityType == T>: NSOperation {
var authority : T
var delegate : ConcreteDelegateType
var operationResult : ConcreteDelegateType.ResultType { return delegate.result }
init(_ someT : T, _ someTD : T.DelegateType) {
authority = someT
delegate = someTD
^^^^ Cannot assign a value of type 'T.DelegateType' to a value of type 'ConcreteDelegateType'
authority.delegate = someTD
super.init()
}
override func start() {
var worker = delegate
worker.begin(authority)
worker.finish = { inResult in self.finished = true }
super.start()
}
}
This compiles for me if I add the T.DelegateType == ConcreteDelegateType constraint:
import Foundation
enum Result<T, Error: ErrorType> {
case Success(T)
case Failure(Error)
}
protocol RequiredWorkerMethods {
typealias ResultType
func begin(authority : AnyObject)
var finish : (ResultType) -> Void { get set }
var result : ResultType { get set }
}
protocol DelegateOwningType : AnyObject {
typealias DelegateType
// typealias SubclassedDelegateType = protocol<RequiredWorkerMethods, DelegateType>
var delegate : DelegateType? { get set }
}
extension NSNetServiceBrowser : DelegateOwningType {
typealias DelegateType = NSNetServiceBrowserDelegate
}
extension NSNetServicesError : ErrorType {}
protocol ConcreteWorker : RequiredWorkerMethods {
typealias AuthorityType
}
class DelegatedOperation <
T : DelegateOwningType,
ConcreteDelegateType : ConcreteWorker,
WorkProductType
where
ConcreteDelegateType.AuthorityType == T,
T.DelegateType == ConcreteDelegateType
>: NSOperation {
var authority : T
var delegate : ConcreteDelegateType
var operationResult : ConcreteDelegateType.ResultType { return delegate.result }
init(_ someT : T, _ someTD : T.DelegateType) {
authority = someT
delegate = someTD
// ^^^^ Cannot assign a value of type 'T.DelegateType' to a value of type 'ConcreteDelegateType'
authority.delegate = someTD
super.init()
}
override func start() {
var worker = delegate
worker.begin(authority)
worker.finish = { inResult in /*FIXME self.finished = true*/ return }
super.start()
}
}
I think our compilers may not be in sync because I get this error every time
enum Result<T, Error: ErrorType> {
case Success(T)
case Failure(Error)
}
protocol RequiredWorkerMethods {
typealias ResultType
func begin(authority : AnyObject)
var finish : (ResultType) -> Void { get set }
var result : ResultType { get set }
}
protocol DelegateOwningType : AnyObject {
typealias DelegateType
var delegate : DelegateType? { get set }
}
extension NSNetServiceBrowser : DelegateOwningType {
typealias DelegateType = NSNetServiceBrowserDelegate
}
extension NSNetServicesError : ErrorType {}
protocol ConcreteWorker : RequiredWorkerMethods {
typealias AuthorityType
}
class DelegatedOperation <T : DelegateOwningType, ConcreteDelegateType : ConcreteWorker
where T.DelegateType == ConcreteDelegateType>: NSOperation {
var authority : T
var delegate : ConcreteDelegateType
var operationResult : ConcreteDelegateType.ResultType { return delegate.result }
init(_ someT : T, _ someTD : T.DelegateType) {
authority = someT
delegate = someTD
authority.delegate = someTD
super.init()
}
override func start() {
var worker = delegate
worker.begin(authority)
worker.finish = { inResult in }
super.start()
}
}
class ConcreteFoo : NSObject, NSNetServiceBrowserDelegate, NSNetServiceDelegate, ConcreteWorker {
typealias ResultType = Result<[AnyObject], NSNetServicesError>
typealias AuthorityType = NSNetServiceBrowser
var encounteredError : NSNetServicesError?
var finish : (ResultType) -> Void
var result : ResultType
override init() {}
func begin(authority: AnyObject) {}
}
let serviceLookup = DelegatedOperation<NSNetServiceBrowser, ConcreteFoo>(NSNetServiceBrowser(), ConcreteFoo())
^^^^'DelegatedOperation' requires the types 'DelegateType' (aka 'NSNetServiceBrowserDelegate') and 'ConcreteFoo' be equivalent
Because I have to specify the type, the compiler won't accept it as a protocol and I can't declare conformance to as the compiler doesn't regard type aliases as complete types and there's no way to hint it as merely being a protocol
I see, yeah, you wouldn't be able to use ConcreteFoo as the ConcreteDelegateType and satisfy the same-type constraint. You need some way to say "I want an NSNetServiceBrowser with a specific delegate type". You could use a wrapper struct for that:
protocol DelegateOwningType {
typealias DelegateType
var delegate : DelegateType? { get nonmutating set }
}
struct ConcreteNSNetServiceBrowser<T: NSNetServiceBrowserDelegate>: DelegateOwningType {
var browser: NSNetServiceBrowser
var delegate: T? {
get {
return browser.delegate as! T?
}
set {
browser.delegate = newValue
}
}
}
which I think will work better. That lets this work:
import Foundation
enum Result<T, Error: ErrorType> {
case Success(T)
case Failure(Error)
}
protocol RequiredWorkerMethods {
typealias ResultType
func begin(authority : AnyObject)
var finish : (ResultType) -> Void { get set }
var result : ResultType? { get set }
}
struct ConcreteNSNetServiceBrowser<T: NSNetServiceBrowserDelegate> {
var browser: NSNetServiceBrowser
var delegate: T? {
get {
return browser.delegate as! T?
}
set {
browser.delegate = newValue
}
}
}
extension NSNetServicesError : ErrorType {}
protocol ConcreteWorker : RequiredWorkerMethods {
typealias AuthorityType
}
class DelegatedOperation <
ConcreteDelegateType: protocol<NSNetServiceBrowserDelegate, ConcreteWorker>
>: NSOperation {
var authority : ConcreteNSNetServiceBrowser<ConcreteDelegateType>
var delegate : ConcreteDelegateType
var operationResult : ConcreteDelegateType.ResultType { return delegate.result! }
init(_ someT : ConcreteNSNetServiceBrowser<ConcreteDelegateType>, _ someTD : ConcreteDelegateType) {
authority = someT
delegate = someTD
authority.delegate = someTD
super.init()
}
override func start() {
var worker = delegate
worker.begin(authority.browser)
worker.finish = { inResult in }
super.start()
}
}
class ConcreteFoo : NSObject, NSNetServiceBrowserDelegate, NSNetServiceDelegate, ConcreteWorker {
typealias ResultType = Result<[AnyObject], NSNetServicesError>
typealias AuthorityType = NSNetServiceBrowser
var encounteredError : NSNetServicesError?
var finish : (ResultType) -> Void
var result : ResultType?
override init() {
self.finish = {_ in}
}
func begin(authority: AnyObject) {}
}
let serviceLookup = DelegatedOperation<ConcreteFoo>(
ConcreteNSNetServiceBrowser(browser: NSNetServiceBrowser()),
ConcreteFoo()
)
Should be able to simplify to this: