I’m having trouble with the Swift bindings generated for an Objective-C NSEnumerator subclass. It seems to be impossible to tell Swift what type of object the enumerator produces; no matter what I do, the loop variable is always typed as an AnyObject. (I can cast this to the right class, but it’s a bit awkward; and this enumerator is a key part of the public API of a framework I work on, so I _know_ that users are going to get confused and ask us for support.)
I can demonstrate the problem pretty easily without showing my API. It also happens with NSDirectoryEnumerator, an NSEnumerator subclass declared in <Foundation/NSFileManager.h>. NSEnumerator is parameterized, and so is NSDirectoryEnumerator, and NSFileManager’s method enumeratorAtURL: returns an NSDirectoryEnumerator<NSURL>. So enumerating that should produce NSURLs, right?
let e = NSFileManager.defaultManager().enumeratorAtURL(NSURL(fileURLWithPath: "/tmp”), includingPropertiesForKeys: nil, options: [], errorHandler: nil)! for url in e { print(url.host) }
The above looks reasonable but produces an error “Ambiguous use of ‘host’”, because the type of `url` is actually AnyObject, not NSURL, so the compiler doesn’t know which `host` method I mean. Instead you have to use print((url as! NSURL).host) // :-P
I’ve been trying to find a way to tell Swift that my QueryEnumerator class returns QueryRow, not AnyObject, but nothing works, not even redeclaring -nextObject to return QueryRow*.
Is this just a still-rough edge of the Obj-C-to-Swift binding mechanism? Is there a plan to fix it?
—Jens
PS: I almost asked this on the swift-users list, but it’s not about ‘pure’ Swift, so I wasn’t sure it was appropriate there. |