7

I'm working with an Observer API (ObserverSet) which have the following function :

public func add<T: AnyObject>(object: T, _ f: T -> Parameters -> Void) -> ObserverSetEntry<Parameters>

It simply register an object then call the instance method f on the object when notification triggers

In one of my manager, I need to hide the previous function with one of mine so I can force an observer to call a predefine function implemented via a protocol.

Here's what I've done so far :

@objc protocol Observer : NSObjectProtocol {
    func observe(param: String) -> Void
}

func addObserver<T: AnyObject where T: Observer>(observer: T) {
    let f: T -> String -> Void = observer.dynamicType.observe
    entries.addObserver(observer, f)
}

Unfortunately, I have the following error showing up Partial application of generic method is not allowed

I've found a possible workaround somewhere on SO which look like that :

let f: T -> String -> Void = { (obs: T) in obs.dynamicType.observe(obs) }

But this line of code drives my XCode crazy with some Segmentation Fault: 11 on compilation (and Communication interrupted with Playground ..)

Is there any workaround for what I'm trying to do ?

duplode
  • 33,731
  • 7
  • 79
  • 150
Yaman
  • 3,949
  • 4
  • 38
  • 60
  • What happens if you declare your protocol as a pure Swift protocol instead of degrading it to an objc protocol? – augustzf Feb 05 '15 at 21:44
  • Exact same error. If I also remove the implementation of `NSObjectProtocol` I get `error: 'T' is not a subtype of 'inout T'` – Yaman Feb 05 '15 at 21:47

1 Answers1

5

I haven't tested but you can try:

@objc protocol Observer : NSObjectProtocol {
    func observe(param: String) -> Void
}

func addObserver<T: AnyObject where T: Observer>(observer: T) {
    let f: T -> String -> Void = { ($0 as AnyObject).observe }
    entries.addObserver(observer, f)
}

At least, this compiles because AnyObject has all methods from ObjC - including @objc - classes/protocols, as ImplicitlyUnwrappedOptional.

So, this compiles:

let str = NSString(string: "test")
(str as AnyObject).observe("foo")

Of course this causes runtime error because NSString has no observe(_:) method. But, in your case, T is guaranteed to be Observer, it should works.

rintaro
  • 51,423
  • 14
  • 131
  • 139
  • Yay ! That cast did it. But I don't understand why I have a segmentation fault without it ? `` already telling that `T` is an `AnyObject` right ? Possible bug ? – Yaman Feb 09 '15 at 14:09
  • Segfault clash itself is definitely a bug. But I'm not sure about the requirement of casting, it's maybe a language limitation. If so, compiler should report corresponding error message. – rintaro Feb 09 '15 at 15:46