[swift-users] unsafeBitCast to Unimplemented Class

Dave Abrahams dabrahams at apple.com
Sun Feb 5 11:01:45 CST 2017


on Sat Feb 04 2017, Saagar Jha <saagar-AT-saagarjha.com> wrote:

> Thanks–your not only did you method work, it had the side effect of
> obviating the need for a Bridging Header. 

Uh, wait: this doesn't add up.  If you needed a bridging header before,
surely it was so that you could get a declaration for Bar?  If that's
the case, you shouldn't be using this protocol hack.

> One more thing: what happens if self isn’t a Bar (crash, I’m
> guessing)? 

No, it should just be using ObjC method dispatch (a.k.a. duck-typing)
under the covers.  If you have a method with the right signature, things
just work.

> Is there a way to compare the type of self, other than using `is`
> (which has the same issue as unsafeBitCast in that I don’t have the
> declaration for it)?

I think you might be able to use something like 

  class_getName(type(of: x))


>
> Saagar Jha
>
>> On Feb 4, 2017, at 4:02 PM, Dave Abrahams via swift-users <swift-users at swift.org> wrote:
>> 
>> 
>> on Fri Feb 03 2017, Saagar Jha <swift-users-AT-swift.org <http://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
>> 
>> _______________________________________________
>> swift-users mailing list
>> swift-users at swift.org <mailto:swift-users at swift.org>
>> https://lists.swift.org/mailman/listinfo/swift-users
> <https://lists.swift.org/mailman/listinfo/swift-users>

-- 
-Dave


More information about the swift-users mailing list