[swift-users] unsafeBitCast to Unimplemented Class

Dave Abrahams dabrahams at apple.com
Sat Feb 4 18:02:08 CST 2017


on Fri Feb 03 2017, Saagar Jha <swift-users-AT-swift.org> wrote:

> Hello,
>
> I’m having an issue migrating some old Objective-C code that looks like this:
>
> @implementation Foo
>
> - (void)load {
> 	// Swizzle one of Bar’s methods to call Foo’s baz method
> }
>
> - (void)baz {
> 	[self baz];
> 	if ([self isKindOfClass:NSClassFromString(@“Bar”)]) {
> 		Bar *bar = (Bar *)self; // I can’t migrate this
> 		// work with bar
> 	}
> }
>
> @end
>
> I’m trying to cast self to a Bar at runtime, and use it to call Bar’s methods. Sounds like an easy
> to task for unsafeBitCast, right? The issue is that I don’t have access to the implementation of
> Bar’s class at compile time (this is a plugin, so it’s loaded by another application which contains
> Bar). In Objective-C I can create a header and stick a dummy interface for Bar in it; the cast will
> work if Bar exists at runtime. However, in Swift, unsafeBitCast requires me to use Bar.self, which
> does not exist. Is there any way to get this cast to work?

Bar.self exists if you have a declaration of it exposed to swift, which
would be required for all the “work with bar” code above.  If you don't
have Bar.self, it's because there's no declaration visible to your Swift
code.  My usual workaround would be to declare an @objc protocol having
the bar APIs you want to use, and then cast self to an instance of that
@objc protocol.  The right way to do that is by using
UnsafePointer.withMemoryRebound(to: ), e.g.

      var mutableSelf = self // can't get pointer to immutable value
      withUnsafePointer(to: &mutableSelf) { selfPtr in
        selfPtr.withMemoryRebound(to: BarProtocol, capacity: 1) { barPtr in
          let bar = barPtr.pointee
          // work with bar
        }
      }

HTH,

-- 
-Dave



More information about the swift-users mailing list