[swift-dev] NSProxy dynamic casting to Swift or ObjC class behaves differently

Yavuz Nuzumlalı manuyavuz at gmail.com
Wed Jun 8 14:24:01 CDT 2016


And +1 for documentation. Do you have any guide about how dynamic casting
actually works? It would perfectly fit there.

And if there is no public guide, I think it would be great to have one
because as far as I see from the code, there are many different scenarios
and different behaviors for each scenario, and implementations are
implicitly affected by that.

I had to follow stack trace on crash, tried to find the method
corresponding to the ObjC type case, find them in source code and compare :)
On Wed, 8 Jun 2016 at 22:17, Yavuz Nuzumlalı <manuyavuz at gmail.com> wrote:

> Hmm, interesting.
>
> So, we can say that NSProxy class, which is the base structure for
> implementing proxy pattern, will not work for a Swift type, right? And I
> simply can't use proxy pattern if real object can be a Swift type.
>
> In my use case, I have a framework, and I want to switch developer's some
> delegate object with my NSProxy standin, listen delegate method myself,
> then forward to the developer's original delegate object.
>
> It was working without any issues for delegate objects which are
> Objective-C classes. But, it fails for Swift types because dynamic casting
> does not work anymore.
>
> So, do you have any suggestions about how can I handle this interception
> functionality without NSProxy?
>
> I don't want to do swizzling :)
>
> Thanks for the explanations!
>
> On Wed, 8 Jun 2016 at 21:13, Jordan Rose <jordan_rose at apple.com> wrote:
>
>>
>> On Jun 8, 2016, at 10:52, Joe Groff via swift-dev <swift-dev at swift.org>
>> wrote:
>>
>>
>> On Jun 8, 2016, at 12:44 AM, Yavuz Nuzumlalı via swift-dev <
>> swift-dev at swift.org> wrote:
>>
>> Hi all,
>>
>> swift_dynamicCastClassUnconditional and
>> swift_dynamicCastObjCClassUnconditional methods behave differently while
>> verifying casting.
>>
>> swift_dynamicCastObjCClassUnconditional method calls -isKindOfClass:
>> method before falling back to object_getClass function.
>>
>> swift_dynamicCastClassUnconditional method calls swift_dynamicCastClass
>> method which calls _swift_getClassOfAllocated method which calls directly
>> object_getClass function.
>>
>> This causes problems if underlying object is an NSProxy subclass.
>>
>> NSProxy class does not implement -isKindOfClass: method, so calls to this
>> method are forwarded to the real object through -forwardInvocation: method,
>> which causes -isKindOfClass: method to return answer according to the real
>> object's class.
>>
>> However, object_getClass function directly accesses to the metadata of
>> the given object, so it returns NSProxy subclass.
>>
>> I think this is a conflicting behavior, and I think
>> swift_dynamicCastClassUnconditional method should also verify first using
>> -isKindOfClass: method, in order to provide consistency.
>>
>>
>> This is intentional, since NSProxy instances are generally expected to be
>> standins for the proxied object. Important Cocoa idioms break down if the
>> "real" class is exposed instead of the class a proxy pretends to be.
>>
>>
>> For a little more detail, Swift relies on a bit more information about
>> layout of both instances and classes than Objective-C does, so an NSProxy
>> stand-in wouldn't work for a Swift type. (And by "wouldn't work" I mean
>> "would crash your program".) However, for an Objective-C type, all accesses
>> Swift does will always go through the Objective-C runtime, so it's safe to
>> use an Objective-C-style proxy, and indeed some Cocoa APIs expect this.
>>
>> This is probably something we could stand to document more explicitly,
>> but I'm not sure where.
>>
>> Jordan
>>
>>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.swift.org/pipermail/swift-dev/attachments/20160608/8fa472e4/attachment.html>


More information about the swift-dev mailing list