With What does Apple Swizzle the IsA-pointer in KVO?

  • Hi,

    Apple says, that it uses IsA-swizzling as the underlying technology to
    implement KVO.
    What are/is the class(es), which replace the original class of the
    observed object? Is it an NSProxy subclass? Different NSProxy
    subclasses, depending on the observed object? Is it a direct subclass
    of the observed object?

    Thanks
    Phil
  • Le 23 nov. 07 à 14:42, Philip Mötteli a écrit :

    > Hi,
    >
    >
    > Apple says, that it uses IsA-swizzling as the underlying technology
    > to implement KVO.
    > What are/is the class(es), which replace the original class of the
    > observed object? Is it an NSProxy subclass? Different NSProxy
    > subclasses, depending on the observed object? Is it a direct
    > subclass of the observed object?
    >
    >
    > Thanks
    > Phil

    With 10.4, I bet on dynamically generated class that are subclass of
    NSObject (Foo is swizzled with something like NSKVONotifying_Foo and
    the debugger says it is a direct subclass of NSObject). But in any
    case, you should not rely on this, because it is an implementation
    detail and it may change.

    Jean-Daniel
  • On Nov 23, 2007 5:42 AM, Philip Mötteli <Philip.Moetteli...> wrote:
    > Hi,
    >
    >
    > Apple says, that it uses IsA-swizzling as the underlying technology to
    > implement KVO.
    > What are/is the class(es), which replace the original class of the
    > observed object? Is it an NSProxy subclass? Different NSProxy
    > subclasses, depending on the observed object? Is it a direct subclass
    > of the observed object?

    Any or none of the above. It's an implementation detail, and really
    shouldn't be relied upon. Perhaps I could provide more help if you
    stated why it is that you think that you need to know this.

    --
    Clark S. Cox III
    <clarkcox3...>
  • Am 23.11.2007 um 15:54 schrieb Clark Cox:

    > On Nov 23, 2007 5:42 AM, Philip Mötteli <Philip.Moetteli...>
    > wrote:
    >>
    >>
    >> Apple says, that it uses IsA-swizzling as the underlying technology
    >> to
    >> implement KVO.
    >> What are/is the class(es), which replace the original class of the
    >> observed object? Is it an NSProxy subclass? Different NSProxy
    >> subclasses, depending on the observed object? Is it a direct subclass
    >> of the observed object?

    > Perhaps I could provide more help if you
    > stated why it is that you think that you need to know this.

    I need to know, when an object has changed and I would prefer to reuse
    as much as possible, of what KVO already offers.
    Unfortunately, KVO is based on the internals of an object (which
    should be assumed as being hidden in OOP). So if I want to observe an
    object that either doesn't have any declared IVar, like e. g. NSString
    and many others, or does not have a corresponding IVar, because it is
    not a simple setter method, like -finalize or -dealloc, I have a
    problem.
    Ideally, I just want to implement a plug-in, that reuses the
    functionality, offered by KVO, but extends it, so that the publicly
    accessible part of an object can be observed instead of the hidden
    internals.
    I presume, I can do that, by implementing my own proxy, that prevents
    KVO to do an IsA swizzling, by implementing -
    automaticallyNotifiesObserversForKey:. But I would have liked to reuse
    the method forwarding mechanism of KVO.
  • Le 23 nov. 07 à 17:03, Philip Mötteli a écrit :

    > Am 23.11.2007 um 15:54 schrieb Clark Cox:
    >
    >> On Nov 23, 2007 5:42 AM, Philip Mötteli <Philip.Moetteli...>
    >> wrote:
    >>>
    >>>
    >>> Apple says, that it uses IsA-swizzling as the underlying
    >>> technology to
    >>> implement KVO.
    >>> What are/is the class(es), which replace the original class of the
    >>> observed object? Is it an NSProxy subclass? Different NSProxy
    >>> subclasses, depending on the observed object? Is it a direct
    >>> subclass
    >>> of the observed object?
    >
    >
    >> Perhaps I could provide more help if you
    >> stated why it is that you think that you need to know this.
    >
    > I need to know, when an object has changed and I would prefer to
    > reuse as much as possible, of what KVO already offers.
    > Unfortunately, KVO is based on the internals of an object (which
    > should be assumed as being hidden in OOP). So if I want to observe
    > an object that either doesn't have any declared IVar, like e. g.
    > NSString and many others, or does not have a corresponding IVar,
    > because it is not a simple setter method, like -finalize or -
    > dealloc, I have a problem.
    > Ideally, I just want to implement a plug-in, that reuses the
    > functionality, offered by KVO, but extends it, so that the publicly
    > accessible part of an object can be observed instead of the hidden
    > internals.
    > I presume, I can do that, by implementing my own proxy, that
    > prevents KVO to do an IsA swizzling, by implementing -
    > automaticallyNotifiesObserversForKey:. But I would have liked to
    > reuse the method forwarding mechanism of
    > KVO._______________________________________________
    >

    KVO is not based on the internals of an object (which is assumed to
    be hidden), and it does not access hiddden internals. KVO is based on
    KVC and uses accessors.
  • >
    > KVO is not based on the internals of an object (which is assumed to
    > be hidden), and it does not access hiddden internals. KVO is based
    > on KVC and uses accessors.
    >
    To expand a bit, my mental model of it is (and this could be wrong):

    No Observing:

    ObjA ----setBlah:----> ObjB

    Observing:

    ObjA ----setBlah:----> ProxyForB -----setBlah:----> ObjB
                                |
                                |
                                \-------blahChanged:---> Observer

    i.e. When the observer registers a proxy is inserted in the chain. The
    message is intercepted by the proxy and it notifies the Observer.

    I don't think it's quite like this, but this allows me to understand
    it enough to use it.

    It's also possible for the observed object (ObjB) to send a message to
    the observer with didChangeValueForKey:

    I don't quite see what wanting that you don't have. Is it that you
    want to know when any key has change, rather that one specific one?
  • On Nov 23, 2007 8:03 AM, Philip Mötteli <Philip.Moetteli...> wrote:
    > Am 23.11.2007 um 15:54 schrieb Clark Cox:
    >
    >> On Nov 23, 2007 5:42 AM, Philip Mötteli <Philip.Moetteli...>
    >> wrote:
    >>>
    >>>
    >>> Apple says, that it uses IsA-swizzling as the underlying technology
    >>> to
    >>> implement KVO.
    >>> What are/is the class(es), which replace the original class of the
    >>> observed object? Is it an NSProxy subclass? Different NSProxy
    >>> subclasses, depending on the observed object? Is it a direct subclass
    >>> of the observed object?
    >
    >
    >> Perhaps I could provide more help if you
    >> stated why it is that you think that you need to know this.
    >
    > I need to know, when an object has changed and I would prefer to reuse
    > as much as possible, of what KVO already offers.
    > Unfortunately, KVO is based on the internals of an object (which
    > should be assumed as being hidden in OOP).

    KVC (and by extension, KVO) only uses instance variable directly if:
    1) There is no appropriate accessor method
    2) +accessInstanceVariablesDirectly is not implemented to return NO

    > So if I want to observe an object that either doesn't have any declared IVar, like e. g. NSString
    > and many others, or does not have a corresponding IVar, because it is
    > not a simple setter method, like -finalize or -dealloc,

    I'm still not clear as to what you're trying to do. NSString is not
    mutable, so attempting to observe one of it's properties doesn't make
    sense, and finalize and dealloc are just methods, what would observing
    them even mean?

    > I have a problem.
    > Ideally, I just want to implement a plug-in, that reuses the
    > functionality, offered by KVO, but extends it, so that the publicly
    > accessible part of an object can be observed instead of the hidden
    > internals.

    The publicly accessible parts of objects *are* what is observed.

    > I presume, I can do that, by implementing my own proxy, that prevents
    > KVO to do an IsA swizzling, by implementing -
    > automaticallyNotifiesObserversForKey:. But I would have liked to reuse
    > the method forwarding mechanism of KVO.

    --
    Clark S. Cox III
    <clarkcox3...>
  • Am 23.11.2007 um 17:23 schrieb Jean-Daniel Dupas:
    > Le 23 nov. 07 à 17:03, Philip Mötteli a écrit :
    >> Am 23.11.2007 um 15:54 schrieb Clark Cox:
    >>
    >>> On Nov 23, 2007 5:42 AM, Philip Mötteli <Philip.Moetteli...>
    >>> wrote:
    >>>>
    >>>> Apple says, that it uses IsA-swizzling as the underlying
    >>>> technology to
    >>>> implement KVO.
    >>>> What are/is the class(es), which replace the original class of the
    >>>> observed object? Is it an NSProxy subclass? Different NSProxy
    >>>> subclasses, depending on the observed object? Is it a direct
    >>>> subclass
    >>>> of the observed object?
    >>
    >>
    >>> Perhaps I could provide more help if you
    >>> stated why it is that you think that you need to know this.
    >>
    >> I need to know, when an object has changed and I would prefer to
    >> reuse as much as possible, of what KVO already offers.
    >> Unfortunately, KVO is based on the internals of an object (which
    >> should be assumed as being hidden in OOP). So if I want to observe
    >> an object that either doesn't have any declared IVar, like e. g.
    >> NSString and many others, or does not have a corresponding IVar,
    >> because it is not a simple setter method, like -finalize or -
    >> dealloc, I have a problem.
    >> Ideally, I just want to implement a plug-in, that reuses the
    >> functionality, offered by KVO, but extends it, so that the publicly
    >> accessible part of an object can be observed instead of the hidden
    >> internals.
    >> I presume, I can do that, by implementing my own proxy, that
    >> prevents KVO to do an IsA swizzling, by implementing -
    >> automaticallyNotifiesObserversForKey:. But I would have liked to
    >> reuse the method forwarding mechanism of KVO.
    >>
    >
    > KVO is not based on the internals of an object (which is assumed to
    > be hidden), and it does not access hiddden internals. KVO is based
    > on KVC and uses accessors.

    In order to use KVO, you need to know this famous "key". The key is
    the name of an instance variable, which is an object's internal data.
    Every OOP book will tell you that ():

    > An object’s data is protected and won’t be touched by any other part
    > of the program. Methods can therefore trust its integrity. They can
    > be sure that external access hasn’t put it in an illogical or
    > untenable state.
  • Am 23.11.2007 um 18:05 schrieb Clark Cox:
    > On Nov 23, 2007 8:03 AM, Philip Mötteli <Philip.Moetteli...>
    > wrote:
    >> Am 23.11.2007 um 15:54 schrieb Clark Cox:
    >>> On Nov 23, 2007 5:42 AM, Philip Mötteli <Philip.Moetteli...>
    >>> wrote:
    >>>>
    >>>> Apple says, that it uses IsA-swizzling as the underlying technology
    >>>> to
    >>>> implement KVO.
    >>>> What are/is the class(es), which replace the original class of the
    >>>> observed object? Is it an NSProxy subclass? Different NSProxy
    >>>> subclasses, depending on the observed object? Is it a direct
    >>>> subclass
    >>>> of the observed object?
    >>
    >>
    >>> Perhaps I could provide more help if you
    >>> stated why it is that you think that you need to know this.
    >>
    >> I need to know, when an object has changed and I would prefer to
    >> reuse
    >> as much as possible, of what KVO already offers.
    >> Unfortunately, KVO is based on the internals of an object (which
    >> should be assumed as being hidden in OOP).
    >
    > KVC (and by extension, KVO) only uses instance variable directly if:
    > 1) There is no appropriate accessor method
    > 2) +accessInstanceVariablesDirectly is not implemented to return NO

    >> I have a problem.
    >> Ideally, I just want to implement a plug-in, that reuses the
    >> functionality, offered by KVO, but extends it, so that the publicly
    >> accessible part of an object can be observed instead of the hidden
    >> internals.
    >
    > The publicly accessible parts of objects *are* what is observed.
    What is the difference between:

    - (void)setValue:(id)value forKey:(NSString *)key

    and

    OBJC_EXPORT void object_setIvar(id obj, Ivar ivar, id value)

    In both versions, you have violated, what Apple writes in:

    > An object’s data is protected and won’t be touched by any other part
    > of the program. Methods can therefore trust its integrity. They can
    > be sure that external access hasn’t put it in an illogical or
    > untenable state.

    So yes, in my eyes, KVC violates OO principles (except, when it uses a
    publicly declared accessor).

    > I'm still not clear as to what you're trying to do. NSString is not
    > mutable, so attempting to observe one of it's properties doesn't make
    > sense,

    Yes, bad example. Take NSMutableString or NSMutableRLEArray,
    NSMutableAttributedString, NSAttributedString, NSMutableCharacterSet,…

    > and finalize and dealloc are just methods, what would observing
    > them even mean?

    That your object has disappeared, which is also a kind of changement.

    But Clarc, tell me, do you know the answer to my initial question:
    > With What does Apple Swizzle the IsA-pointer in KVO?
    >

    Then, please tell me.
  • On Nov 23, 2007, at 11:50 AM, Paul Sargent wrote:

    >> KVO is not based on the internals of an object (which is assumed
    >> to be hidden), and it does not access hiddden internals. KVO is
    >> based on KVC and uses accessors.
    >>
    > To expand a bit, my mental model of it is (and this could be wrong):
    >
    > No Observing:
    >
    > ObjA ----setBlah:----> ObjB
    >
    > Observing:
    >
    > ObjA ----setBlah:----> ProxyForB -----setBlah:----> ObjB
    > |
    > |
    > \-------blahChanged:---> Observer
    >
    > i.e. When the observer registers a proxy is inserted in the chain.
    > The message is intercepted by the proxy and it notifies the Observer.

    Isa-swizzling does not involve a proxy object - it changes the class
    of ObjB directly by manipulating its isa ivar, hence the name.

    When you observe an object, a new subclass is created that inherits
    from that object's class, and overrides its KVC methods with versions
    that send -willChangeValueForKey: and -didChangeValueForKey: to any
    observers before and after calling the original class' KVC methods.
    The observed object's class is then changed by storing a pointer to
    the subclass in its isa ivar.

    sherm--

    Web Hosting by West Virginians, for West Virginians: http://wv-www.net
    Cocoa programming in Perl: http://camelbones.sourceforge.net
  • On Nov 23, 2007, at 10:09 AM, Philip Mötteli wrote:

    > In order to use KVO, you need to know this famous "key". The key is
    > the name of an instance variable, which is an object's internal
    > data. Every OOP book will tell you that (<Object-Oriented
    > Programming with Objective-C- Classes.webloc>):
    >
    Please read the documentation to see why you are wrong.

    mmalc
  • On Nov 23, 2007, at 12:09 PM, Philip Mötteli wrote:

    >> KVO is not based on the internals of an object (which is assumed to
    >> be hidden), and it does not access hiddden internals. KVO is based
    >> on KVC and uses accessors.
    >
    > In order to use KVO, you need to know this famous "key". The key is
    > the name of an instance variable, which is an object's internal
    > data. Every OOP book will tell you that (<Object-Oriented
    > Programming with Objective-C- Classes.webloc>):

    No you don't.  All that matters is that there is a method "foo" that
    returns something, and a corresponding "setFoo:" that takes a similar
    type as "foo" returns and you can observe it (and the second method
    isn't needed, so long as some mechanism exists to let KVO know when
    the value of "foo" has changed)

    It doesn't matter if there is an ivar with same name, similar name, or
    if the whole thing is synthesized.  For example, you could have:

    @class Name : NSObject {
    NSString *myFirstName;
    NSString *myLastName;
    }
    - (NSString *) firstName;
    - (void) setFirstName: (NSString *) name;
    - (NSString *) lastName;
    - (void) setLastName: (NSString *) name;
    - (NSString *) fullName;
    @end

    where "fullName" is just:

    - (NSString *) fullName
    {
    return [myFirstName stringByAppendingFormat: @" %@", myLastName];
    }

    Add in

    + (void) initialize
    {
        [self setKeys: [NSArray arrayWithObjects: @"firstName",
    @"lastName" NULL] triggerChangeNotificationsForDependentKey:
    @"fullName"];
    }

    and you can now observe firstName, lastName (both getting and
    setting), and fullName, none of which are the names of ivars and one
    of which doesn't even exist as an ivar (and has no "setFullName:), yet
    everything will work as expected.

    Glenn Andreas                      <gandreas...>
      <http://www.gandreas.com/> wicked fun!
    quadrium | prime : build, mutate, evolve, animate : the next
    generation of fractal art
  • Am 23.11.2007 um 19:09 schrieb Sherm Pendley:
    > On Nov 23, 2007, at 11:50 AM, Paul Sargent wrote:
    >
    >>> KVO is not based on the internals of an object (which is assumed
    >>> to be hidden), and it does not access hiddden internals. KVO is
    >>> based on KVC and uses accessors.
    >>>
    >> To expand a bit, my mental model of it is (and this could be wrong):
    >>
    >> No Observing:
    >>
    >> ObjA ----setBlah:----> ObjB
    >>
    >> Observing:
    >>
    >> ObjA ----setBlah:----> ProxyForB -----setBlah:----> ObjB
    >> |
    >> |
    >> \-------blahChanged:---> Observer
    >>
    >> i.e. When the observer registers a proxy is inserted in the chain.
    >> The message is intercepted by the proxy and it notifies the Observer.

    > When you observe an object, a new subclass is created that inherits
    > from that object's class,

    So Apple has the same solution as GNUstep.
    It actually doesn't implement any method forwarding, but uses
    objc_msgsend()'s.

    Thanks
  • On Nov 23, 2007, at 1:09 PM, Philip Mötteli wrote:

    > In order to use KVO, you need to know this famous "key". The key is
    > the name of an instance variable

    Not so:

    - (id)foo {
    return bar;
    }

    This is a KVC-compliant accessor method for the key "foo", and
    doesn't rely on an instance variable named "foo".

    > , which is an object's internal data. Every OOP book will tell you
    > that

    You might want to re-read those books. One of the primary points of
    KVC is to disassociate public keys from private instance variables.
    Granted, a one-to-one mapping of keys to ivars is often the most
    convenient way to implement it, but it's definitely not a requirement.

    sherm--

    Web Hosting by West Virginians, for West Virginians: http://wv-www.net
    Cocoa programming in Perl: http://camelbones.sourceforge.net
  • On Nov 23, 2007 10:09 AM, Philip Mötteli <Philip.Moetteli...> wrote:
    > Am 23.11.2007 um 17:23 schrieb Jean-Daniel Dupas:
    >
    >> Le 23 nov. 07 à 17:03, Philip Mötteli a écrit :
    >>> Am 23.11.2007 um 15:54 schrieb Clark Cox:
    >>>
    >>>> On Nov 23, 2007 5:42 AM, Philip Mötteli <Philip.Moetteli...>
    >>>> wrote:
    >>>>>
    >>>>> Apple says, that it uses IsA-swizzling as the underlying
    >>>>> technology to
    >>>>> implement KVO.
    >>>>> What are/is the class(es), which replace the original class of the
    >>>>> observed object? Is it an NSProxy subclass? Different NSProxy
    >>>>> subclasses, depending on the observed object? Is it a direct
    >>>>> subclass
    >>>>> of the observed object?
    >>>
    >>>
    >>>> Perhaps I could provide more help if you
    >>>> stated why it is that you think that you need to know this.
    >>>
    >>> I need to know, when an object has changed and I would prefer to
    >>> reuse as much as possible, of what KVO already offers.
    >>> Unfortunately, KVO is based on the internals of an object
    >>
    >> KVO is not based on the internals of an object (which is assumed to
    >> be hidden), and it does not access hiddden internals. KVO is based
    >> on KVC and uses accessors.
    >
    > In order to use KVO, you need to know this famous "key". The key is
    > the name of an instance variable,

    Not true, the key is the name of a property of the class. If the class
    implements -key and setKey:, then KVC will never directly touch a
    "key" instance variable (in fact such a variable need not exist).

    --
    Clark S. Cox III
    <clarkcox3...>
previous month november 2007 next month
MTWTFSS
      1 2 3 4
5 6 7 8 9 10 11
12 13 14 15 16 17 18
19 20 21 22 23 24 25
26 27 28 29 30    
Go to today