Skip to content

Instantly share code, notes, and snippets.

@thekarladam
Created September 19, 2015 02:03
Show Gist options
  • Save thekarladam/c3974dc545d56b41ee5b to your computer and use it in GitHub Desktop.
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()
}
}
@jckarter
Copy link

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()
)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment