Re: Stupid objective-c question

2016-09-27 Thread Alastair Houghton
On 27 Sep 2016, at 05:31, Britt Durbrow  
wrote:
> 
> FWIW, it’s currently an implementation detail that SELs do map into the 
> global address space in a way that doesn’t collide with anything else; but 
> technically, they are in their own address space and the system could map 
> them otherwise in a manner that does have collisions with other stuff.

That’s true.  IIRC GNUStep SEL values don’t work the same way as they do with 
the Apple/NeXT runtime, so this trick wouldn’t work there.

> In practice, I don’t think that will ever happen, because a) too much 
> existing code makes the assumption that a SEL is de-referenceable or 
> otherwise depends on this implementation detail; and b) we have 64-bit 
> addressing, so we’re not going to run out of address space such that making 
> that change would be advantageous.

Agreed, it seems unlikely that Apple would change it; not impossible, but quite 
unlikely.  As I say, relying on it means your code won’t straightforwardly port 
to GNUStep, but most of us don’t care too much about that.

Kind regards,

Alastair.

--
http://alastairs-place.net


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-27 Thread Alastair Houghton
On 27 Sep 2016, at 02:17, Slipp Douglas Thompson  
wrote:
> 
> I'm just going to throw this out there as a solution, not because I recommend 
> this approach (it's API misuse after all) but because it would work.
> 
> Instead of using an `NSString *` you could use a `SEL` (AKA `struct 
> objc_selector *`) since SELs are guaranteed to be unique for each given 
> string they represent (within a process; AFAIR).

Indeed, they’re interned by the Objective-C runtime.  However, this is a 
blessing and a curse; it’s a blessing in that comparing with a selector will be 
fast, you can use “==“ to do the comparison, and the resulting code will be 
easy to read.  It’s a curse in that it means you must choose a unique selector. 
 So @selector(mediaLibraryLoaded) is unlikely to be a good choice; something 
like @selector(com:mycompany:mediaLibraryLoaded) might be.

> My 2¢: I'm still in favor of making all usages of `context` in your app 
> `NSObject *`s or `nil` because sometimes you do want to store an 
> `NSDictionary *` or other data in `context` that's meant to be read later.

The context value is not retained (and there’s no obvious guarantee about when 
you can expect that it won’t be used again; assuming that you won’t be called 
with your context value immediately after deregistering for KVO notifications 
will probably result in the creation of a subtle race condition).  Also, other 
code might result in you receiving a non-nil pointer that doesn’t point to an 
object.  The safest way really is to take the address of a static variable in 
your code and use that; there are, as you rightly suggest, alternative 
addresses you could use (a selector, or a function address would both work, as 
would a dynamically allocated address, provided you stored it somewhere).

> But if you're stuck with using other libs that don't use `NSObject *`s or 
> `nil`, or if you really want to ensure your code won't crash because its 
> making assumptions about what's in the  `context` your code registered, then 
> I acknowledge your case.  Key point: I personally wouldn't use the `SEL` 
> approach, but still.

The SEL approach is better, modulo the requirement for the name to be unique.  
But the idiom used by most of us is to take the address of a static variable, 
and I’d recommend sticking to that.

The important point in all of this, though, is that you can’t safely 
dereference the context pointer, because you don’t know what it is.  You may 
*think* you do, because you’ve supplied *one* possible value for it, but other 
code that you don’t control can supply other non-nil values and they will point 
at whatever that code chose to point them at, which probably wasn’t the same as 
your choice.

Kind regards,

Alastair.

--
http://alastairs-place.net


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-26 Thread Britt Durbrow
FWIW, it’s currently an implementation detail that SELs do map into the global 
address space in a way that doesn’t collide with anything else; but 
technically, they are in their own address space and the system could map them 
otherwise in a manner that does have collisions with other stuff.

In practice, I don’t think that will ever happen, because a) too much existing 
code makes the assumption that a SEL is de-referenceable or otherwise depends 
on this implementation detail; and b) we have 64-bit addressing, so we’re not 
going to run out of address space such that making that change would be 
advantageous.


> On Sep 26, 2016, at 6:17 PM, Slipp Douglas Thompson 
>  wrote:
> 
> I'm just going to throw this out there as a solution, not because I recommend 
> this approach (it's API misuse after all) but because it would work.
> 
> Instead of using an `NSString *` you could use a `SEL` (AKA `struct 
> objc_selector *`) since SELs are guaranteed to be unique for each given 
> string they represent (within a process; AFAIR).
> 
> So your code would become:
> 
>   if (context == @selector(mediaLibraryLoaded))
>   {
>   // …
> 
> Or in Swift:
> 
>   if context == Selector("mediaLibraryLoaded")
>   {
>   // …
> (Swift's `Selector.init(_ str:String)` implementation 
>   
> >
>  just calls `sel_registerName` and (curiously) treats the returned pointer as 
> a C-string.)
> 
> Again, this is a blatant mis-use of the Objective-C API… but it is also a 
> built-in compiler-optimized guaranteed-interned string, it won't cause issues 
> when comparing to other arbitrary `void *`s, and the usage in Swift is almost 
> identical to Objective-C.
> 
> 
> 
> 
> 
> My 2¢: I'm still in favor of making all usages of `context` in your app 
> `NSObject *`s or `nil` because sometimes you do want to store an 
> `NSDictionary *` or other data in `context` that's meant to be read later.  
> But if you're stuck with using other libs that don't use `NSObject *`s or 
> `nil`, or if you really want to ensure your code won't crash because its 
> making assumptions about what's in the  `context` your code registered, then 
> I acknowledge your case.  Key point: I personally wouldn't use the `SEL` 
> approach, but still.
> 
> — Slipp
> 

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-26 Thread Slipp Douglas Thompson
I'm just going to throw this out there as a solution, not because I recommend 
this approach (it's API misuse after all) but because it would work.

Instead of using an `NSString *` you could use a `SEL` (AKA `struct 
objc_selector *`) since SELs are guaranteed to be unique for each given string 
they represent (within a process; AFAIR).

So your code would become:

if (context == @selector(mediaLibraryLoaded))
{
// …

Or in Swift:

if context == Selector("mediaLibraryLoaded")
{
// …
(Swift's `Selector.init(_ str:String)` implementation 

 just calls `sel_registerName` and (curiously) treats the returned pointer as a 
C-string.)

Again, this is a blatant mis-use of the Objective-C API… but it is also a 
built-in compiler-optimized guaranteed-interned string, it won't cause issues 
when comparing to other arbitrary `void *`s, and the usage in Swift is almost 
identical to Objective-C.





My 2¢: I'm still in favor of making all usages of `context` in your app 
`NSObject *`s or `nil` because sometimes you do want to store an `NSDictionary 
*` or other data in `context` that's meant to be read later.  But if you're 
stuck with using other libs that don't use `NSObject *`s or `nil`, or if you 
really want to ensure your code won't crash because its making assumptions 
about what's in the  `context` your code registered, then I acknowledge your 
case.  Key point: I personally wouldn't use the `SEL` approach, but still.

— Slipp



> On Sep 24, 2016, at 12:34 AM, Graham Cox  wrote:
> 
> 
>> On 24 Sep 2016, at 12:13 PM, Uli Kusterer  
>> wrote:
>> 
>>> I expect the first thing -isEqualToString: does is a pointer comparison, so 
>>> it’s unlikely to be significantly less performant for the case of when the 
>>> pointers are literally identical.
>> 
>> No, Graham, don't do that!
>> 
>> There is no guarantee that the context is a valid object. It is just 
>> supposed to be a unique pointer value so your class can tell a KVO 
>> notification from notifications for other observers on the same object (e.g. 
>> if a subclass observes the same value as a base class).
> 
> 
> Yep, I’ve realised (from this discussion) that that’s an invalid assumption 
> of another kind.
> 
> I’ve been revising code that does this as a result.
> 
> Always something to learn :)
> 
> —Graham
> 
> 
> 
> ___
> 
> Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
> 
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
> 
> Help/Unsubscribe/Update your Subscription:
> https://lists.apple.com/mailman/options/cocoa-dev/apple%2Bcocoa-dev%40slippyd.com
> 
> This email sent to apple+cocoa-...@slippyd.com

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-26 Thread Britt Durbrow

> On Sep 26, 2016, at 3:31 AM, Slipp Douglas Thompson 
>  wrote:
> 
> I'm sorry if I'm not up to snuff on compiler architecture, but how would a 
> pointer to the memory address of that same pointer ever collide with any 
> other pointer?

When ***Somebody*** is Doing It Wrong.

Having been bitten before by this phenomenon (i.e, others doing bizarre, 
illogical things; often in oddball close-source code libraries and/or drivers); 
I felt compelled to point out that non-collision wasn’t an *absolute* 
guarantee, but rather just a reasonable assumption *almost* always.

In other words, just when you think you’ve got it Idiot Proof, somebody goes 
and invents a better Idiot…

:-)

>  Only one thing may exist at at time at a given memory address, so— yes, if 
> you're assigning arbitrary values into a pointer instead of an actual valid 
> memory address you could have a problem, but that usage in itself is the 
> smell.

It’s not *you* - the good, sane programmer - who’s doing that. It’s the other 
guy who’s Doing It Wrong… but it shows up as misbehavior in *your* code, 
leading *you* to tear your hair out.

And yes, the malodorousness of that code is positively wretched… 8-p


Alternatively, a memory scribbler or leakage via an improperly initialized 
variable may induce similar misbehavior (so, one should not assume that just 
because it *shouldn’t* happen under sane circumstances, that it *can’t* when 
facing a bug). 

:-)
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-26 Thread Fritz Anderson
On 23 Sep 2016, at 9:49 PM, Uli Kusterer  wrote:
> 
> Are you sure? I only learned Cocoa when it came to OS X, but my impression 
> was that, while KVC came from NeXT, KVO arrived with bindings … that would 
> have been 10.3 or 10.4-ish?

As I remember, when KVO was introduced, it was framed as a bottleneck for 
implementing bindings. Foundation exposed it as a courtesy to developers who 
would find it useful in itself.

Cocoa practice has changed since then, but that’s what I gathered at the time.

You’re right, KVC was NeXTStep. The patent on it was one of NS/Apple’s crown 
jewels.

— F

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-26 Thread Quincey Morris
On Sep 26, 2016, at 02:45 , Britt Durbrow 
 wrote:
> 
>>  void *kMyContext = 
>> 
>> is *guaranteed* to give you a unique address that nobody else's object may 
>> occupy?
>> 
> 
> Splitting hairs, but that’s not ***guaranteed*** - just super highly unlikely 
> to have a collision.

If you’re going to split hairs, you shouldn’t leave out half the words (“ that 
nobody else's object may occupy”). Regardless of whether you take “object” in 
the Obj-C sense or the C spec sense, no other object is going to have the same 
address. The weaker condition of a unique *pointer* can’t be guaranteed, since 
C allows any bit pattern to be cast to a pointer (as in your example).

> Also, FWIW, even declaring a single pointer variable in the global space that 
> isn’t used as an actual variable strikes me as a bit of a code smell

But if I use the above construct, then I use “kMyContext” as my context, not 
“”:

>   if (context != kMyContext) { [super observeValueForKeyPath: …]; return; 
> }


In that case, I really am using the value of the variable.

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-26 Thread Britt Durbrow
> 
>   void *kMyContext = 
> 
> is *guaranteed* to give you a unique address that nobody else's object may 
> occupy?
> 

Splitting hairs, but that’s not ***guaranteed*** - just super highly unlikely 
to have a collision.

There’s never any guarantee that somebody else isn’t Doing It Wrong (TM).

Some yahoo sticking something like this in their framework or plugin could well 
create havoc, should you get unlucky…

void *thisWillNeverCollideWithAnything = 0x00010003b568LL; // Yeah, right! 
And I gotta bridge to sell you!







Also, FWIW, even declaring a single pointer variable in the global space that 
isn’t used as an actual variable strikes me as a bit of a code smell…. perhaps 
this is something that there should be a compiler extension for… something like 
this, maybe:

NS_UNIQUE_TOKEN(myContext);

which would resolve to:

static const void *myContext __attribute__((uniqueToken));

and that attribute would cause the pointer to be given a unique address by the 
linker (i.e, no hazard of coalescing), without the physical RAM actually being 
allocated for it (or, alternatively, perhaps all unique tokens could just be 
lumped together in a separate page, so that if the OS is doing lazy RAM 
allocation, that page - because it should never be de-referenced - never gets 
physically allocated).

or Swiftly,

uniqueToken myContext; // no ‘let’ here because I think it would be unnecessary 
and awkward; as there is no initializer half to the statement.

:-)
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-23 Thread Graham Cox

> On 24 Sep 2016, at 12:13 PM, Uli Kusterer  
> wrote:
> 
>> I expect the first thing -isEqualToString: does is a pointer comparison, so 
>> it’s unlikely to be significantly less performant for the case of when the 
>> pointers are literally identical.
> 
> No, Graham, don't do that!
> 
> There is no guarantee that the context is a valid object. It is just supposed 
> to be a unique pointer value so your class can tell a KVO notification from 
> notifications for other observers on the same object (e.g. if a subclass 
> observes the same value as a base class).


Yep, I’ve realised (from this discussion) that that’s an invalid assumption of 
another kind.

I’ve been revising code that does this as a result.

Always something to learn :)

—Graham



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-23 Thread Uli Kusterer
On 23 Sep 2016, at 01:19, Sandor Szatmari  wrote:
> // my .m file
> static NSString * const kMyContext = @"my fantastic context";

 This avoids the issue of having a different string in a different module and 
relying on details of your compiler and its optimizer. However, it can still 
run afoul of them, in the other direction, depending on which string you use: 
I've seen people do this and use the name of the property being observed as the 
string's value. Which is not an unlikely choice for an observation in the base 
class. And in that case, the optimizer might give the base class and you the 
same string to point to in your static variable.

 OTOH, if you use your subclass's name, you're less likely to collide. But why 
use the memory for the additional string and risk making the value less unique 
when

void *kMyContext = 

is *guaranteed* to give you a unique address that nobody else's object may 
occupy?

Cheers,
-- Uli Kusterer
"The Witnesses of TeachText are everywhere..."
http://www.zathras.de


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-23 Thread Uli Kusterer

> On 23 Sep 2016, at 01:07, Quincey Morris 
>  wrote:
> 
> On Sep 22, 2016, at 15:45 , Gabriel Zachmann  wrote:
>> 
>> Sure, but an observation method is what would be called a "callback" in 
>> plain C.
>> In C, I can have many different callbacks.
>> I don't see why that should not be possible in Obj-C - I just would need a 
>> mechanism to add tell the system the names / function pointers to be 
>> registered as observers.
> 
> It is of course possible in Obj-C. There are APIs that have a “didEnd” 
> selector, such as (deprecated) ‘[NSApplication 
> beginSheet:modalForWindow:modalDelegate:didEndSelector:contextInfo:]’. That’s 
> similar to the KVO notification method concept, except that you get to 
> specify a selector and a target object. Note, however, that such APIs tend to 
> have a context parameter, too**.
> 
> But that’s because the KVO notification mechanism is a more ancient design 
> concept, where it likely seemed simple, adequate and flexible. I assume it 
> comes from NeXTStep days (late 80s or early 90s), not OS X 10.0 days (early 
> 2000s), although I don’t know for sure.

 Are you sure? I only learned Cocoa when it came to OS X, but my impression was 
that, while KVC came from NeXT, KVO arrived with bindings … that would have 
been 10.3 or 10.4-ish?

> ** In the “didEnd” selector mechanism, the context parameter is likely used 
> for actual context information, rather than for identifying the source of the 
> invocation. It can be used that way with KVO notifications, too, but the fact 
> that they’re funneled through a single method in the observer object means 
> that the context is implicitly known anyway, and the context parameter has 
> been appropriated as a marker for the source of the observation.

 Yeah, I wouldn't conflate the context on beginSheet: and the majority of Cocoa 
calls with the one on KVO. And I would actually argue that you *should not* use 
the KVO context as actual storage, as as soon as it contains useful 
information, you can't tell it from someone else's context anymore (such as 
your superclass's). At the least using it for data would be bad style.

Cheers,
-- Uli Kusterer
"The Witnesses of TeachText are everywhere..."
http://www.zathras.de


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-23 Thread Uli Kusterer
On 23 Sep 2016, at 00:45, Gabriel Zachmann  wrote:
>> Because the observer is an object. Your observation and a superclass 
>> observation come from the same object. Whether these are to be treated as 
>> different observations** cannot be determined automatically, hence the need 
>> for a “context”.
> 
> Sure, but an observation method is what would be called a "callback" in plain 
> C.
> In C, I can have many different callbacks.
> I don't see why that should not be possible in Obj-C - I just would need a 
> mechanism to add tell the system the names / function pointers to be 
> registered as observers.
> 
> Anyways, the concept of a block gets closer to what I mean, except it is 
> still not a named function/method.

 The problem is that KVO was designed (probably because it avoids the overhead 
of an NSInvocation, as the observeValueForKeyPath method can't be called using 
performSelector) to funnel all its callbacks through a single method on your 
object.

 If it allowed specifying a SEL to call, on the observer, you wouldn't need a 
context parameter.

Cheers,
-- Uli Kusterer
"The Witnesses of TeachText are everywhere..."
http://www.zathras.de


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-23 Thread Uli Kusterer

> On 22 Sep 2016, at 19:53, Quincey Morris 
>  wrote:
> 
> On Sep 22, 2016, at 03:16 , Gabriel Zachmann  wrote:
>> 
>> That makes me wonder: why isn't it possible to register several, different 
>> observers for the same thing?
>> That way, I wouldn't need to care about observations I didn't create, would 
>> I?
> 
> Because the observer is an object. Your observation and a superclass 
> observation come from the same object. Whether these are to be treated as 
> different observations** cannot be determined automatically, hence the need 
> for a “context”.
> 
> The reason it’s messy is that the observer/notification API is old and 
> doesn’t follow modern API design practices. If this were being designed 
> today, the “observeValueForKeyPath…” method would likely be replaced by a 
> block/closure (similar to a completion handler) that’s passed as a parameter 
> to the “addObserver…” call, and there wouldn’t be any contexts.

Or it could be done like other places in Cocoa (was it NSTrackingArea? Or the 
event monitors?), where you get an "id" return value back (some unknown object) 
that represents your registration and that you keep around and pass to the 
remove call to specify which registration to unregister.

Cheers,
-- Uli Kusterer
"The Witnesses of TeachText are everywhere..."
http://www.zathras.de


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-23 Thread Uli Kusterer
On 22 Sep 2016, at 04:00, Doug Hill  wrote:
> As to the context type, I would be interested to know of cases where the 
> observer doesn't have control over the context.

 As your quote says:

> "Contexts chosen in a similar manner in the super- or subclass will be 
> unlikely to overlap."

 It is to insulate code inherited from a superclass that observes the same 
property as code in the superclass. By using a unique context as an additional 
identifier for the subscription, the subclass can't accidentally unsubscribe 
the base class that still wants to stay subscribed.

Cheers,
-- Uli Kusterer
"The Witnesses of TeachText are everywhere..."
http://www.zathras.de


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-23 Thread Uli Kusterer

> On 22 Sep 2016, at 03:36, Graham Cox  wrote:
> 
> 
>> On 22 Sep 2016, at 10:40 AM, Quincey Morris 
>>  wrote:
>> 
>> On Sep 21, 2016, at 17:01 , Graham Cox  wrote:
>>> 
>>> This should be: if([(NSString*)context 
>>> isEqualToString:@“mediaLibraryLoaded”])…
>> 
>> Actually, this is not a good idea either, because *other* observations — 
>> ones you don’t control — might use a value that’s not an object, or not even 
>> a valid pointer.
> 
> 
> Fair point.
> 
> Which is yet another reason why void* is such a shitty concept. Apple could 
> easily have insisted that parameter was id without any real 
> problems, so void*… sheesh.
> 
> So Gabriel’s alternative is basically to use a global address, as you 
> otherwise suggested.
> 
> void* tsk… *goes away muttering*

No. It is not supposed to be a refCon or userInfo. It's a unique identifier for 
this observation (which can't be "self", because then observations registered 
by a subclass would get the same identifier as observations registered by the 
base class, and if one unsubscribes or re-subscribes earlier than the other, 
one could remove the other's observation and would break things.

Cheers,
-- Uli Kusterer
"The Witnesses of TeachText are everywhere..."
http://www.zathras.de


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-23 Thread Uli Kusterer

> On 22 Sep 2016, at 03:21, Slipp Douglas Thompson 
>  wrote:
> 
> 
>> On Sep 21, 2016, at 8:00 PM, Slipp Douglas Thompson 
>>  wrote:
>> 
>>> On Sep 21, 2016, at 17:01 , Graham Cox  wrote:
 
 This should be: if([(NSString*)context 
 isEqualToString:@“mediaLibraryLoaded”])…
>>> 
>>> Actually, this is not a good idea either, because *other* observations — 
>>> ones you don’t control — might use a value that’s not an object, or not 
>>> even a valid pointer.
>> 
> 
> I see your point about context plausibly not being neither an NSObject nor 
> nil.  While you could check if context is an NSObject beforehand (is there 
> even a reliable way to do this?  CocoaWithLove 
> 
>  couldn't find a great approach ;-/)— I think coding consistently against all 
> other addObserver: calls in your app is a good-enough solution.  I.E. If you 
> implement observeValueForKeyPath: with [context isEqual: …] checks, make sure 
> all the other addObserver: calls (for those same keys, at least) are using 
> nil or NSObjects.

That's not enough. You would also have to ensure that none of Apple's code uses 
a non-object context in any KVOs it installs on any of your objects.

Which you can't.

Cheers,
-- Uli Kusterer
"The Witnesses of TeachText are everywhere..."
http://www.zathras.de


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-23 Thread Uli Kusterer

> On 22 Sep 2016, at 02:05, Gabriel Zachmann  wrote:
>> 
>>> how can the compiler know that '==' in this case is a NSString comparison?
>> 
>> It can’t because it isn't. What’s being compared are raw pointers. The 
>> string value is irrelevant.
> 
> Let me try to paraphrase, in order to check whether I am understanding 
> correctly.
> 
> Whenever I have two string literals @"XYZ" at different places in the same 
> compilation unit,
> and the XYZ are identical, then the compiler (or the Objective-C standard) 
> make sure that
> the pointers to those literals are identical?
> In other words, the compiler unifies the two occurrences of the two literals, 
> thus effectively storing only one literal?

 This is an optimization that Apple's compiler (and most compilers) currently 
apply for string constants, yes. However, they can only do that in the same 
executable. I.e. a framework or loadable plug-in bundle will get its own copy, 
as we can't know whether the executable loading it already has its own copy of 
that string or not. Also, of course, if you have an NSMutableString that ends 
up having the same content as an NSString, you get different addresses.

 If you want a more detailed answer, I blogged about this a while ago:

http://orangejuiceliberationfront.com/cocoa-string-comparisons-and-the-optimizer/

>> So, this technique is generally Not A Good Idea™.
> 
> If my understanding is correct, then I wholeheartedly agree.
> 
> That brings me to another question.  I've got this piece of code from an 
> example on MLMediaLibrary.
> 
> This is how I start the whole thing:
> 
>  [mediaLibrary_ addObserver: self
>  forKeyPath: @"mediaSources"
> options: 0
> context: (__bridge void *) @"mediaLibraryLoaded"];
> 
> And this is the beginning of the corresponding KVO:
> 
> - (void) observeValueForKeyPath: (NSString *) keyPath   ofObject: (id) object
>   change: (NSDictionary *) change context: (void *) 
> context
> {
>  MLMediaSource * mediaSource = [mediaLibrary_.mediaSources objectForKey: 
> MLMediaSourcePhotosIdentifier];
>  if ( context == (__bridge void *) @"mediaLibraryLoaded" )
>  {
> 
> So what would be the proper way to do it?  Should I just define my own string 
> constant?

Do

void *kMediaLibraryLoadedKVOContext = 

for more details, see my other message in this thread.

-- Uli


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-23 Thread Uli Kusterer
On 22 Sep 2016, at 02:02, Doug Hill  wrote:
>>> My question is: how can the compiler know that '==' in this case is a 
>>> NSString comparison?
>>> Or is some other magic going on here? if so, which?
>>> Does the compiler know it should perform some kind of dynamic method 
>>> dispatch?
>> 
>> My guess, without seeing the code that set up the observer, is that it was 
>> also set up with @"mediaLibraryLoaded", and the compiler collects and reuses 
>> string constants, so the address is the same. I'd guess that if you ensure 
>> that the string is a unique variable, it won't work.
>> 
>> NSString* s = [NSString stringWithFormat:@"%@%@%@", @"media", @"Library", 
>> @"Loaded"];
>> if(context == (__bridge void*)s)
>> 
>> Steve via iPad
> 
> For the above test, you could also try turning off the LLVM code-gen setting 
> "gcc_reuse_strings".
> (Which parenthetically, you probably wouldn't want to do in shipping code, 
> particularly if you have a lot of strings.)
> 
> But yeah, as everyone says, it's generally not a good thing to rely upon this 
> behavior, and just use -[NSString isEqual:]

 Do *not* call methods on the context to a KVO observation! It is not 
guaranteed to actually be an object! It is not storage for user data, it is 
simply a unique identifier for your subscription to these KVO callbacks.

-- Uli
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-23 Thread Uli Kusterer

> On 22 Sep 2016, at 02:01, Graham Cox  wrote:
> 
> 
>> On 22 Sep 2016, at 9:44 AM, Gabriel Zachmann  wrote:
>> 
>> I have found on the net 
> 
> That isn’t always a recommendation ;)
> 
> 
>>  if ( context == (__bridge void *) @"mediaLibraryLoaded" )

Gabriel,

this is a pointer comparison, not a string comparison. If the addObserver call 
happens in another module (usually unlikely) or Apple changes how its compiler 
coalesces string constants, this will break.

> Don’t do this, even if it appears to work. You got lucky, or are taking 
> advantage of undocumented implementation details.
> 
> This should be: if([(NSString*)context 
> isEqualToString:@“mediaLibraryLoaded”])…
> 
> I expect the first thing -isEqualToString: does is a pointer comparison, so 
> it’s unlikely to be significantly less performant for the case of when the 
> pointers are literally identical.

No, Graham, don't do that!

There is no guarantee that the context is a valid object. It is just supposed 
to be a unique pointer value so your class can tell a KVO notification from 
notifications for other observers on the same object (e.g. if a subclass 
observes the same value as a base class).

The best (but a bit clever) way to declare your context is

void* kMediaLibraryLoadedContext = 

this may look invalid, but actually just reserves a bit of memory in your app's 
globals section that now has a unique address. As a convenience, it writes this 
address into itself. So instead of  you can just 
write kMediaLibraryLoadedContext.

Cheers,
-- Uli



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-23 Thread Sandor Szatmari
Thanks to both of you for clarifying this and for a nice solution.

Basically then, I must not use address pointed to, but instead, the address of 
the pointer itself.

I liked the readability of using a string, but I think there is too much room 
for misinterpretation, conflating the contents of the string with the 
uniqueness requirement.

Regards,
Sandor Szatmari

> On Sep 23, 2016, at 05:04, Quincey Morris 
>  wrote:
> 
>> On Sep 23, 2016, at 01:36 , Alastair Houghton  
>> wrote:
>> 
>> Note that you can use *any* type for your variable; in some ways, it might 
>> make sense to use a non-pointer type, just to make clear that it’s the 
>> address that matters, e.g.
>> 
>> static const int kMyContext = 0xabadf00d;
>> 
>> Otherwise some smart-ass might go and delete the “&” operators from your 
>> code, and that makes it vulnerable to problems.
> 
> As previously mentioned, the safest way to do this is:
> 
>> static void* kMyContext = 
> 
> 
> That makes the “&” optional (at comparison time), and it should even avoid 
> the coalescing problem if it’s declared const.
> 
> ___
> 
> Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
> 
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
> 
> Help/Unsubscribe/Update your Subscription:
> https://lists.apple.com/mailman/options/cocoa-dev/admin.szatmari.net%40gmail.com
> 
> This email sent to admin.szatmari@gmail.com
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-23 Thread Alastair Houghton
On 23 Sep 2016, at 10:04, Quincey Morris  
wrote:
> 
>> static void* kMyContext = 
> 
> That makes the “&” optional (at comparison time), and it should even avoid 
> the coalescing problem if it’s declared const.

Yes, that’s a good way to do it.

It might be a good idea for Apple to have a macro for this purpose, so you 
could write

  NS_DECLARE_KVO_CONTEXT(kMyContext);

as that would avoid any confusion whatsoever (filed as rdar://2842).

Kind regards,

Alastair.

--
http://alastairs-place.net


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-23 Thread Jonathan Mitchell

> On 23 Sep 2016, at 10:04, Quincey Morris 
>  wrote.
> 
> As previously mentioned, the safest way to do this is:
> 
>> static void* kMyContext = 
> 
Thats a neat trick. It’s not an initialisation that I have seen before and on 
first glance I thought it was a typo but it works.
I normally go with:

static char myContext;

However, being able to ditch the address of operator has some appeal.


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-23 Thread Quincey Morris
On Sep 23, 2016, at 01:36 , Alastair Houghton  
wrote:
> 
> Note that you can use *any* type for your variable; in some ways, it might 
> make sense to use a non-pointer type, just to make clear that it’s the 
> address that matters, e.g.
> 
>  static const int kMyContext = 0xabadf00d;
> 
> Otherwise some smart-ass might go and delete the “&” operators from your 
> code, and that makes it vulnerable to problems.

As previously mentioned, the safest way to do this is:

> static void* kMyContext = 


That makes the “&” optional (at comparison time), and it should even avoid the 
coalescing problem if it’s declared const.

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-23 Thread Alastair Houghton
On 23 Sep 2016, at 09:36, Alastair Houghton  
wrote:
> 
> Note that you can use *any* type for your variable; in some ways, it might 
> make sense to use a non-pointer type, just to make clear that it’s the 
> address that matters, e.g.
> 
>  static const int kMyContext = 0xabadf00d;

On second thoughts, it might also be best not to use “const”, as that might 
conceivably also get coalesced.  So

   static int kMyContext;

would do.  No need to initialise - you don’t care about the value.

Kind regards,

Alastair.

--
http://alastairs-place.net


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-23 Thread Alastair Houghton
On 23 Sep 2016, at 00:07, Quincey Morris  
wrote:
> 
> On Sep 22, 2016, at 15:45 , Gabriel Zachmann  wrote:
>> 
>> Sure, but an observation method is what would be called a "callback" in 
>> plain C.
>> In C, I can have many different callbacks.
>> I don't see why that should not be possible in Obj-C - I just would need a 
>> mechanism to add tell the system the names / function pointers to be 
>> registered as observers.
> 
> It is of course possible in Obj-C. There are APIs that have a “didEnd” 
> selector, such as (deprecated) ‘[NSApplication 
> beginSheet:modalForWindow:modalDelegate:didEndSelector:contextInfo:]’. That’s 
> similar to the KVO notification method concept, except that you get to 
> specify a selector and a target object. Note, however, that such APIs tend to 
> have a context parameter, too**.
> 
> But that’s because the KVO notification mechanism is a more ancient design 
> concept, where it likely seemed simple, adequate and flexible. I assume it 
> comes from NeXTStep days (late 80s or early 90s), not OS X 10.0 days (early 
> 2000s), although I don’t know for sure.

KVO is an OS X thing, introduced in 10.3.

Why it uses this approach rather than taking a selector is a good question.  I 
imagine it’s motivated by the desire to allow subclasses to override 
superclasses’ observation behaviour, and perhaps there might also be a 
performance argument (it *might* make it more likely that the 
-observeValueForKeyPath: method hits the method cache, and/or provide 
additional opportunities to use IMPs).

Kind regards,

Alastair.

--
http://alastairs-place.net


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-23 Thread Alastair Houghton
On 23 Sep 2016, at 00:19, Sandor Szatmari  wrote:
> 
> I wanted to get some opinions on the following which I have done in the past 
> and perceive as different because the string constant is introduced and 
> defined once and only once.
> 
> // my .m file
> static NSString * const kMyContext = @"my fantastic context";
> 
> // later on
> - (void) observeValueForKeyPath: (NSString *) keyPath   ofObject: (id) object
>   change: (NSDictionary *) change context: (void *) 
> context
> {
>  if ( context == kMyContext )
>  { // do my stuff }
>  else
>  // call super
> }
> 
> My interpretation of how to use context has been as an arbitrary pointer...  
> Does this run afoul of anyone's sensibility?

Yes, it’s wrong.

The compiler and linker perform an optimisation known as string coalescing.  
What this means is that if *anyone* else uses the string @"my fantastic 
context" in their code and it just happens to get (statically) linked to yours, 
the address will not be unique.  Given the string you picked, it isn’t unlikely 
that the same string could be used elsewhere as a KVO context.

At present, the risk is confined mainly to your own codebase because string 
coalescing isn’t performed by the dynamic linker and the system doesn’t intern 
string constants.

The correct approach is to take *the address of a static variable* and use 
that, as that’s guaranteed to be unique.

i.e. you need to do this:

  static NSString * const kMyContext = @"My fantastic context";

  ...

[foo addObserver:myObject forKeyPath:@"some.key.path" options:0 
context:];

  ...

  - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
  change:(NSDictionary *)change context:(void *)context
  {
if (context == ) {
  // Do my stuff
} else {
  [super observeValueForKeyPath:keyPath ofObject:object change:change 
context:context];
}
  }

Note that you can use *any* type for your variable; in some ways, it might make 
sense to use a non-pointer type, just to make clear that it’s the address that 
matters, e.g.

  static const int kMyContext = 0xabadf00d;

Otherwise some smart-ass might go and delete the “&” operators from your code, 
and that makes it vulnerable to problems.

Kind regards,

Alastair.

--
http://alastairs-place.net


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-22 Thread Quincey Morris
On Sep 22, 2016, at 16:52 , Charles Srstka  wrote:
> 
> Actually nope, it showed up in 10.3, making it younger than the 
> target/selector approach.

In that case, I have no plausible rationale why this was done differently. It’s 
possible there was a performance-related reason. It’s possible it was a design 
preference on the part of the engineer who introduced the capability. It’s 
possible it has to do with the ease of overriding the behavior in subclasses. 
(It’s sometimes awkward to customize the “didEnd”-style behavior.)

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-22 Thread Doug Hill

> On Sep 22, 2016, at 4:19 PM, Sandor Szatmari  
> wrote:
> 
> So there was lots of discussion and plenty of 'don't do anything that equates 
> to this' --> @"myString" == @"myString", and I agree.  
> 
> I wanted to get some opinions on the following which I have done in the past 
> and perceive as different because the string constant is introduced and 
> defined once and only once.
> 
> // my .m file
> static NSString * const kMyContext = @"my fantastic context";
> 
> // later on
> - (void) observeValueForKeyPath: (NSString *) keyPath   ofObject: (id) object
>   change: (NSDictionary *) change context: (void *) 
> context
> {
>  if ( context == kMyContext )
>  { // do my stuff }
>  else
>  // call super
> }
> 
> My interpretation of how to use context has been as an arbitrary pointer...  
> Does this run afoul of anyone's sensibility?
> 
> Sandor Szatmari

This appears to follow Apple recommended practice. I think after all the 
discussion on this thread, pretty much the only thing you should do is compare 
the context to a static pointer. And a static string maybe makes it easier to 
identify a particular context. I’m actually changing some old code right now to 
use these recommendations.

Good luck!

Doug Hill


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-22 Thread Charles Srstka
> On Sep 22, 2016, at 6:07 PM, Quincey Morris 
>  wrote:
> 
> But that’s because the KVO notification mechanism is a more ancient design 
> concept, where it likely seemed simple, adequate and flexible. I assume it 
> comes from NeXTStep days (late 80s or early 90s), not OS X 10.0 days (early 
> 2000s), although I don’t know for sure.

Actually nope, it showed up in 10.3, making it younger than the target/selector 
approach.

Charles

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-22 Thread Sandor Szatmari
So there was lots of discussion and plenty of 'don't do anything that equates 
to this' --> @"myString" == @"myString", and I agree.  

I wanted to get some opinions on the following which I have done in the past 
and perceive as different because the string constant is introduced and defined 
once and only once.

// my .m file
static NSString * const kMyContext = @"my fantastic context";

// later on
- (void) observeValueForKeyPath: (NSString *) keyPath   ofObject: (id) object
   change: (NSDictionary *) change context: (void *) context
{
  if ( context == kMyContext )
  { // do my stuff }
  else
  // call super
}

My interpretation of how to use context has been as an arbitrary pointer...  
Does this run afoul of anyone's sensibility?

Sandor Szatmari
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-22 Thread Jens Alfke

> On Sep 22, 2016, at 3:45 PM, Gabriel Zachmann  wrote:
> 
> I don't see why that should not be possible in Obj-C - I just would need a 
> mechanism to add tell the system the names / function pointers to be 
> registered as observers.

That’s more like the way NSNotificationCenter works — you specify the target 
and selector, which together act similarly to a function pointer.

I’m not sure why, but KVO uses a single method to deliver all notifications. 
That’s just the way Apple designed it, and KVO is newer than 
NSNotificationCenter so they must have had a good reason for doing so. That 
means the only thing that can uniquely distinguish different KVO registrations 
is the ‘context’ value.

—Jens
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-22 Thread Quincey Morris
On Sep 22, 2016, at 15:45 , Gabriel Zachmann  wrote:
> 
> Sure, but an observation method is what would be called a "callback" in plain 
> C.
> In C, I can have many different callbacks.
> I don't see why that should not be possible in Obj-C - I just would need a 
> mechanism to add tell the system the names / function pointers to be 
> registered as observers.

It is of course possible in Obj-C. There are APIs that have a “didEnd” 
selector, such as (deprecated) ‘[NSApplication 
beginSheet:modalForWindow:modalDelegate:didEndSelector:contextInfo:]’. That’s 
similar to the KVO notification method concept, except that you get to specify 
a selector and a target object. Note, however, that such APIs tend to have a 
context parameter, too**.

But that’s because the KVO notification mechanism is a more ancient design 
concept, where it likely seemed simple, adequate and flexible. I assume it 
comes from NeXTStep days (late 80s or early 90s), not OS X 10.0 days (early 
2000s), although I don’t know for sure.

It’s not that there *can’t* be a better mechanism, just that there isn’t***.


** In the “didEnd” selector mechanism, the context parameter is likely used for 
actual context information, rather than for identifying the source of the 
invocation. It can be used that way with KVO notifications, too, but the fact 
that they’re funneled through a single method in the observer object means that 
the context is implicitly known anyway, and the context parameter has been 
appropriated as a marker for the source of the observation.

*** Yet. KVO is one of the things that Swift hasn’t touched, even though it 
doesn’t translate very naturally. I believe (suspect) that’s because there’s an 
intention to replace it with a completely re-designed property notification 
system at some indefinite future time, but I’ve seen no discussion of what a 
new observer architecture might look like.

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-22 Thread Gabriel Zachmann
> 
> Because the observer is an object. Your observation and a superclass 
> observation come from the same object. Whether these are to be treated as 
> different observations** cannot be determined automatically, hence the need 
> for a “context”.

Sure, but an observation method is what would be called a "callback" in plain C.
In C, I can have many different callbacks.
I don't see why that should not be possible in Obj-C - I just would need a 
mechanism to add tell the system the names / function pointers to be registered 
as observers.

Anyways, the concept of a block gets closer to what I mean, except it is still 
not a named function/method.

Best regards, 
Gabriel.


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-22 Thread Quincey Morris
On Sep 22, 2016, at 03:16 , Gabriel Zachmann  wrote:
> 
> That makes me wonder: why isn't it possible to register several, different 
> observers for the same thing?
> That way, I wouldn't need to care about observations I didn't create, would I?

Because the observer is an object. Your observation and a superclass 
observation come from the same object. Whether these are to be treated as 
different observations** cannot be determined automatically, hence the need for 
a “context”.

The reason it’s messy is that the observer/notification API is old and doesn’t 
follow modern API design practices. If this were being designed today, the 
“observeValueForKeyPath…” method would likely be replaced by a block/closure 
(similar to a completion handler) that’s passed as a parameter to the 
“addObserver…” call, and there wouldn’t be any contexts.


** That is, a superclass ‘addObserver’ may be in common code that’s used by all 
the subclasses, or it may be a private observation that’s separate from what 
subclasses use. Where the observation is created is insufficient to determine 
whether it’s an observation “you” created, or you “care about”.
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Quincey Morris
On Sep 21, 2016, at 21:47 , Jeff Evans  wrote:
> 
> Of course, so [[NSArray alloc]init] is actually useless; I hadn't thought of 
> that. No one would ever declare an array that way.

Just continuing my nitpicking tour of this thread:

It isn’t useless. Sometimes you really want an empty array. For example, there 
are Cocoa APIs that have a parameter that’s an array of (say) options. In some 
cases, an API might accept nil as meaning “no options”, but in others it might 
throw an exception. It’s safer to pass [[NSArray alloc] init], or [NSArray 
array], or @[].

Another example where it might be needed is if you’re using 
“arrayByAddingObject:” or “arrayByAddingObjectsFromArray:” to construct an 
array, and you might want to start, conditionally, from an existing array or an 
empty array.

So it’s degenerate perhaps, but not exactly useless.

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Jens Alfke

> On Sep 21, 2016, at 9:47 PM, Jeff Evans  wrote:
> 
> One would have to init it with objects to be useful at all, and then it 
> presumably would point to different data than another NSArray (even 
> nonmutable) inited with objects.

Yup. Another fun fact is that the non-mutable classes all implement -copy as 
simply “return self”, since copying an immutable object is a no-op*. 
Again, the mutable subclasses override -copy to make an actual copy.

—Jens

* aside from bumping the retain count, but I’m ignoring that because with ARC 
we no longer care about such things, right?
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Doug Hill

> On Sep 21, 2016, at 10:07 PM, Quincey Morris 
>  wrote:
> 
> On Sep 21, 2016, at 21:10 , Doug Hill  > wrote:
>> 
>> I believe the original question was why you can compare a string literal to 
>> another object pointer using the == operator and it somehow works.
> 
> Actually, we’re more or less on the same page here, but for posterity…
> 
> There’s no “somehow” with the == operator. It’s a C thing, not an Obj-C 
> thing, so putting it between two pointers is well-defined, even if either of 
> them happens to be an object reference. Indeed, constructs like "(void*)3" 
> are also a C thing 

Just as an example of how this “somehow worked”, but just as easily couldn't:

@“xyz123” == @“xyz123”

isn’t guaranteed to resolve to YES.

Crazy stuff. :)

But I appreciate everyone jumping in on this topic, another thread for the ages.

Doug Hill
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Quincey Morris
On Sep 21, 2016, at 21:10 , Doug Hill  wrote:
> 
> I believe the original question was why you can compare a string literal to 
> another object pointer using the == operator and it somehow works.

Actually, we’re more or less on the same page here, but for posterity…

There’s no “somehow” with the == operator. It’s a C thing, not an Obj-C thing, 
so putting it between two pointers is well-defined, even if either of them 
happens to be an object reference. Indeed, constructs like "(void*)3" are also 
a C thing (any int can be cast to a pointer, provided the pointer size is at 
least as big as the int size on the architecture being compiled for).

The original solution rested on a matter of *uniqueness* of pointers to string 
literals. The point was that the characters making up the string were never 
intended to be compared, only the pointers themselves, relying on the 
uniqueness of pointers to different string values. It’s an extremely delicate 
(that is, nerdy) distinction, but it’s clearer when you consider that a pointer 
comparison can always be assumed to be really, really cheap (1 machine 
instruction, almost always), whereas a string comparison can be quite 
expensive, quite apart from the question of whether objects or dynamism are 
involved.

Another way of saying it is that the original solution leveraged the difference 
between literal string values without actually comparing them. That’s why it 
was clever (if only it wasn’t fatally flawed for a different reason).

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Jeff Evans
Ah - yes, thank you.  Of course, so [[NSArray alloc]init] is actually useless; 
I hadn't thought of that. No one would ever declare an array that way.
One would have to init it with objects to be useful at all, and then it 
presumably would point to different data than another NSArray (even nonmutable) 
inited with objects.

Jeff


On Sep 21, 2016, at 9:33 PM, Jens Alfke wrote:


> On Sep 21, 2016, at 9:19 PM, Jeff Evans  wrote:
> 
>   Is it really true what Jens says,  that [[NSArray alloc]init] always 
> returns the same pointer?
>   If that is the case, how can one declare two separate arrays?

NSArray is immutable, so any two empty NSArrays are equal/identical.
Now, _mutable_ arrays are different — every call to [[NSMutableArray alloc] 
init] returns a new instance.

The same thing is true of other immutable Foundation classes like NSDictionary, 
NSString and NSNumber, so you’ll see the same optimization for e.g. short 
strings and small integers. (In fact, the latter two are now implemented using 
magic tagged pointers that don’t allocate memory at all!)

—Jens


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Jens Alfke

> On Sep 21, 2016, at 9:19 PM, Jeff Evans  wrote:
> 
>   Is it really true what Jens says,  that [[NSArray alloc]init] always 
> returns the same pointer?
>   If that is the case, how can one declare two separate arrays?

NSArray is immutable, so any two empty NSArrays are equal/identical.
Now, _mutable_ arrays are different — every call to [[NSMutableArray alloc] 
init] returns a new instance.

The same thing is true of other immutable Foundation classes like NSDictionary, 
NSString and NSNumber, so you’ll see the same optimization for e.g. short 
strings and small integers. (In fact, the latter two are now implemented using 
magic tagged pointers that don’t allocate memory at all!)

—Jens
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Doug Hill
I think it’s because an NSArray is immutable such that an empty array is 
guaranteed to never change. This gives the compiler opportunities for 
optimization based on this knowledge.

It starts to get interesting when you do things like:

NSArray *emptyArray   = [[NSArray alloc] init];
NSArray *anotherArray = [emptyArray arrayByAddingObject:anObject];

But this creates a new array. Consequently, any meaningful array won’t be the 
one created with [[NSArray alloc] init].

Doug Hill


> On Sep 21, 2016, at 9:19 PM, Jeff Evans  wrote:
> 
> Whoa - maybe I've had too much wine with dinner, but:
> 
>   Is it really true what Jens says,  that [[NSArray alloc]init] always 
> returns the same pointer?
>   If that is the case, how can one declare two separate arrays?
> 
> Jeff
> 
> On Sep 21, 2016, at 8:50 PM, Jens Alfke wrote:
> 
> 
>> On Sep 21, 2016, at 6:36 PM, Graham Cox  wrote:
>> 
>> Which is yet another reason why void* is such a shitty concept. Apple could 
>> easily have insisted that parameter was id without any real 
>> problems, so void*… sheesh.
> 
> It’s not an object! It’s just an opaque ‘cookie’ that you can use to 
> recognize which observer is being invoked, and specify which one to remove.
> 
> The point of using a void* is that it’s easy to generate guaranteed-unique 
> values by taking the address of a static variable. If the context were an 
> object, people would be likely to assume they should use -isEqual: to compare 
> them (as half the people on this thread seem to be doing), but that’s not a 
> good idea because it can result in false positives comparing 
> equal-but-different objects.
> 
> Moreover, it can be hard to be sure whether you’re getting distinct objects 
> in Obj-C, since initializers will often return unique singletons for common 
> cases. For instance, [[NSArray alloc] init] will always return the same 
> pointer every time it’s called, making it a terrible choice for a context.
> 
> —Jens


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Jeff Evans
Whoa - maybe I've had too much wine with dinner, but:

Is it really true what Jens says,  that [[NSArray alloc]init] always 
returns the same pointer?
If that is the case, how can one declare two separate arrays?

Jeff

On Sep 21, 2016, at 8:50 PM, Jens Alfke wrote:


> On Sep 21, 2016, at 6:36 PM, Graham Cox  wrote:
> 
> Which is yet another reason why void* is such a shitty concept. Apple could 
> easily have insisted that parameter was id without any real 
> problems, so void*… sheesh.

It’s not an object! It’s just an opaque ‘cookie’ that you can use to recognize 
which observer is being invoked, and specify which one to remove.

The point of using a void* is that it’s easy to generate guaranteed-unique 
values by taking the address of a static variable. If the context were an 
object, people would be likely to assume they should use -isEqual: to compare 
them (as half the people on this thread seem to be doing), but that’s not a 
good idea because it can result in false positives comparing 
equal-but-different objects.

Moreover, it can be hard to be sure whether you’re getting distinct objects in 
Obj-C, since initializers will often return unique singletons for common cases. 
For instance, [[NSArray alloc] init] will always return the same pointer every 
time it’s called, making it a terrible choice for a context.

—Jens

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Doug Hill
> On Sep 21, 2016, at 8:33 PM, Quincey Morris 
>  wrote:
> 
> On Sep 21, 2016, at 19:00 , Doug Hill  > wrote:
>> 
>> Just to be clear, the original question was specifically about comparing an 
>> Objective-C string literal. For this case, you definitely want to use 
>> -[NSString isEqualToString:]
> 
> Actually, no. A couple of similar comments in this thread have slightly 
> missed the point about the original question.
> 
> The “cleverness” of that original approach was that the contents of the 
> string really had nothing to do with anything. As long as the string being 
> used for the current observer scenario was different from strings being used 
> by other scenarios, the pointers to the string would be different, and every 
> context would be different.
> 
> You could as easily have used (void*)1, (void*)2, (void*)3, etc in the 
> various places in your app, but using meaningful strings instead is a fairly 
> easy way of not mixing the pointers up.
> 
> Thus, there was never any intent to compare string values, just pointers, and 
> that’s what made the ‘==‘ comparison crash-proof.
> 
> It wouldn’t be *illogical* to use string value comparisons instead, except 
> that then, yes, you’d have to code around the cases where the context is not 
> a pointer to a NSString object.

I believe the original question was why you can compare a string literal to 
another object pointer using the == operator and it somehow works. The contents 
of the string in this case would be very important because the compiler does 
some magic to make duplicates of strings all have the same address. As was 
mentioned, this is a quirk of string pooling/merging by the compiler and that 
it might happen in some cases but maybe not in others. For example, I think you 
can control this behavior in GCC and LLVM with a compiler setting. Just to make 
it clear, CLang calls this undefined behavior:

NSString *foo = @"xyz123";
if( foo == @"xyz123" )
NSLog(@"YES");

warning: direct comparison of a string literal has undefined behavior 
[-Wobjc-string-compare]

Again, in general (i.e. not just for observing scenarios) you probably 
shouldn’t rely on identical strings, especially literals.

But as we’ve now verified from Apple documentation, comparing to a static 
variable address is the way to handle the context parameter in key path 
observation, so we shouldn’t be involving literals.

>> As to the context type, I would be interested to know of cases where the 
>> observer doesn't have control over the context. My understanding is that the 
>> context is something that the observer sets itself when calling addObserver, 
>> and it is passed back to itself in the above method call. So the observer 
>> should know what kind of entity the context is, and can determine the best 
>> way to compare this value.
> 
> 
> If you were the sole author of all observations in your app, you wouldn’t 
> absolutely need a context parameter at all, since you can identify the 
> observation** from the object and keypath. But you’re not.
> 
> The observer doesn’t have control over the context when the superclass or a 
> subclass also does observations, and those other classes aren’t written as 
> part of the project. For example, a view controller is a class that’s often 
> going to want to observe things, but NSViewController may itself be observing 
> things too, possible some of the same things. That’s one reason why the 
> observer method must always call super for notifications that it cannot 
> recognize *specifically* as resulting from observations it *specifically* 
> added.
> 
> ** Except in the case where observations from various sources are funneled 
> through a common observer method, which doesn’t happen a lot, but does happen.

This makes sense. I’m glad I’m getting this figured out after all these years. 
:)

Doug Hill

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Jens Alfke

> On Sep 21, 2016, at 7:00 PM, Doug Hill  wrote:
> 
> As to the context type, I would be interested to know of cases where the 
> observer doesn't have control over the context. My understanding is that the 
> context is something that the observer sets itself when calling addObserver, 
> and it is passed back to itself in the above method call. So the observer 
> should know what kind of entity the context is, and can determine the best 
> way to compare this value.

Subclasses or superclasses can register observers, so it’s possible for your 
observer method to get called for observations that you didn’t create.

(The subclass case is less likely, because the subclass’s observer method 
should be handling that call and not calling super, but it’s good defensive 
coding practice to not rely 100% on that.)

—Jens
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Jens Alfke

> On Sep 21, 2016, at 6:36 PM, Graham Cox  wrote:
> 
> Which is yet another reason why void* is such a shitty concept. Apple could 
> easily have insisted that parameter was id without any real 
> problems, so void*… sheesh.

It’s not an object! It’s just an opaque ‘cookie’ that you can use to recognize 
which observer is being invoked, and specify which one to remove.

The point of using a void* is that it’s easy to generate guaranteed-unique 
values by taking the address of a static variable. If the context were an 
object, people would be likely to assume they should use -isEqual: to compare 
them (as half the people on this thread seem to be doing), but that’s not a 
good idea because it can result in false positives comparing 
equal-but-different objects.

Moreover, it can be hard to be sure whether you’re getting distinct objects in 
Obj-C, since initializers will often return unique singletons for common cases. 
For instance, [[NSArray alloc] init] will always return the same pointer every 
time it’s called, making it a terrible choice for a context.

—Jens
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Quincey Morris
On Sep 21, 2016, at 19:00 , Doug Hill  wrote:
> 
> Just to be clear, the original question was specifically about comparing an 
> Objective-C string literal. For this case, you definitely want to use 
> -[NSString isEqualToString:]

Actually, no. A couple of similar comments in this thread have slightly missed 
the point about the original question.

The “cleverness” of that original approach was that the contents of the string 
really had nothing to do with anything. As long as the string being used for 
the current observer scenario was different from strings being used by other 
scenarios, the pointers to the string would be different, and every context 
would be different.

You could as easily have used (void*)1, (void*)2, (void*)3, etc in the various 
places in your app, but using meaningful strings instead is a fairly easy way 
of not mixing the pointers up.

Thus, there was never any intent to compare string values, just pointers, and 
that’s what made the ‘==‘ comparison crash-proof.

It wouldn’t be *illogical* to use string value comparisons instead, except that 
then, yes, you’d have to code around the cases where the context is not a 
pointer to a NSString object.

> As to the context type, I would be interested to know of cases where the 
> observer doesn't have control over the context. My understanding is that the 
> context is something that the observer sets itself when calling addObserver, 
> and it is passed back to itself in the above method call. So the observer 
> should know what kind of entity the context is, and can determine the best 
> way to compare this value.


If you were the sole author of all observations in your app, you wouldn’t 
absolutely need a context parameter at all, since you can identify the 
observation** from the object and keypath. But you’re not.

The observer doesn’t have control over the context when the superclass or a 
subclass also does observations, and those other classes aren’t written as part 
of the project. For example, a view controller is a class that’s often going to 
want to observe things, but NSViewController may itself be observing things 
too, possible some of the same things. That’s one reason why the observer 
method must always call super for notifications that it cannot recognize 
*specifically* as resulting from observations it *specifically* added.


** Except in the case where observations from various sources are funneled 
through a common observer method, which doesn’t happen a lot, but does happen.

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Wim Lewis
On Sep 21, 2016, at 7:00 PM, Doug Hill  wrote:
> As to the context type, I would be interested to know of cases where the 
> observer doesn't have control over the context. My understanding is that the 
> context is something that the observer sets itself when calling addObserver, 
> and it is passed back to itself in the above method call. So the observer 
> should know what kind of entity the context is, and can determine the best 
> way to compare this value.

The main use of the context parameter, I think, is to to keep your 
*de*registrations from clobbering the wrong registration. It's also useful to 
make sure you're looking at the observation you think you are. If a superclass 
or subclass also observes some things, then your -observeValueForKeyPath can be 
called for all sorts of things other than the things you requested. The 
'context' parameter supplies an opaque value that supports comparison but 
nothing else- that's why it's a (void *).

Unlike other context pointers in the API, you don't usually need to pass data 
in to your observation method, because it has access to self.

I usually use either the "address of a static variable" technique that Quincey 
Morris described, or [TheClassThatMyCodeIsIn class]. The latter will, like the 
static variable, be a pointer value that is unique to the set of observations 
you've registered (superclasses and subclasses will have to register using 
their own class, of course), and sometimes it's easier to examine in the 
debugger. I think the static-variable approach is better in general though.



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Doug Hill

> On Sep 21, 2016, at 6:36 PM, Graham Cox  wrote:
> 
> 
>> On 22 Sep 2016, at 10:40 AM, Quincey Morris 
>>  wrote:
>> 
>> On Sep 21, 2016, at 17:01 , Graham Cox  wrote:
>>> 
>>> This should be: if([(NSString*)context 
>>> isEqualToString:@“mediaLibraryLoaded”])…
>> 
>> Actually, this is not a good idea either, because *other* observations — 
>> ones you don’t control — might use a value that’s not an object, or not even 
>> a valid pointer.
> 
> 
> Fair point.
> 
> Which is yet another reason why void* is such a shitty concept. Apple could 
> easily have insisted that parameter was id without any real 
> problems, so void*… sheesh.
> 
> So Gabriel’s alternative is basically to use a global address, as you 
> otherwise suggested.
> 
> void* tsk… *goes away muttering*
> 
> —Graham

Just to be clear, the original question was specifically about comparing an 
Objective-C string literal. For this case, you definitely want to use 
-[NSString isEqualToString:]

As to the context type, I would be interested to know of cases where the 
observer doesn't have control over the context. My understanding is that the 
context is something that the observer sets itself when calling addObserver, 
and it is passed back to itself in the above method call. So the observer 
should know what kind of entity the context is, and can determine the best way 
to compare this value.

But hey, always check the documentation first. Here's a nice little tidbit from

https://developer.apple.com/library/prerelease/content/documentation/Cocoa/Conceptual/KeyValueObserving/Articles/KVOBasics.html
 


"The address of a uniquely named static variable within your class makes a good 
context. Contexts chosen in a similar manner in the super- or subclass will be 
unlikely to overlap. You may choose a single context for the entire class and 
rely on the key path string in the notification message to determine what 
changed. Alternatively, you may create a distinct context for each observed key 
path, which bypasses the need for string comparisons entirely, resulting in 
more efficient notification parsing."

So, instead of using a string literal, create a static object and do pointer 
comparisons is what Apple recommends.

Hope this helps.

Doug Hill
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Graham Cox

> On 22 Sep 2016, at 10:40 AM, Quincey Morris 
>  wrote:
> 
> On Sep 21, 2016, at 17:01 , Graham Cox  wrote:
>> 
>> This should be: if([(NSString*)context 
>> isEqualToString:@“mediaLibraryLoaded”])…
> 
> Actually, this is not a good idea either, because *other* observations — ones 
> you don’t control — might use a value that’s not an object, or not even a 
> valid pointer.


Fair point.

Which is yet another reason why void* is such a shitty concept. Apple could 
easily have insisted that parameter was id without any real problems, 
so void*… sheesh.

So Gabriel’s alternative is basically to use a global address, as you otherwise 
suggested.

void* tsk… *goes away muttering*

—Graham



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Quincey Morris
On Sep 21, 2016, at 18:00 , Slipp Douglas Thompson 
 wrote:
> 
> isEqualToString: could cause issues here so isEqual: is the most sure-fire 
> solution

Er, no. If the context is not an object, [context isEqual: … anything …] is 
going to crash in objc_msgSend before execution gets to the ‘isEqual’ method.

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Slipp Douglas Thompson

> On Sep 21, 2016, at 8:00 PM, Slipp Douglas Thompson 
>  wrote:
> 
>> On Sep 21, 2016, at 17:01 , Graham Cox  wrote:
>>> 
>>> This should be: if([(NSString*)context 
>>> isEqualToString:@“mediaLibraryLoaded”])…
>> 
>> Actually, this is not a good idea either, because *other* observations — 
>> ones you don’t control — might use a value that’s not an object, or not even 
>> a valid pointer.
> 

I see your point about context plausibly not being neither an NSObject nor nil. 
 While you could check if context is an NSObject beforehand (is there even a 
reliable way to do this?  CocoaWithLove 

 couldn't find a great approach ;-/)— I think coding consistently against all 
other addObserver: calls in your app is a good-enough solution.  I.E. If you 
implement observeValueForKeyPath: with [context isEqual: …] checks, make sure 
all the other addObserver: calls (for those same keys, at least) are using nil 
or NSObjects.

Thoughts?

— Slipp
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Slipp Douglas Thompson
> On Sep 21, 2016, at 17:01 , Graham Cox  wrote:
>> 
>> This should be: if([(NSString*)context 
>> isEqualToString:@“mediaLibraryLoaded”])…
> 
> Actually, this is not a good idea either, because *other* observations — ones 
> you don’t control — might use a value that’s not an object, or not even a 
> valid pointer.


Looking over a couple of open-source implementations of Foundation (cocotron 
, 
PureFoundation 
), the 
first check done in both isEqual: & isEqualToString: is a pointer == check.  

So yes, isEqualToString: could cause issues here so isEqual: is the most 
sure-fire solution (IMHO)— it shouldn't be any less performant than 
isEqualToString: and only marginally less performant than a == (due to 
objc_msgSend overhead).

— Slipp
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Quincey Morris
On Sep 21, 2016, at 17:01 , Graham Cox  wrote:
> 
> This should be: if([(NSString*)context 
> isEqualToString:@“mediaLibraryLoaded”])…

Actually, this is not a good idea either, because *other* observations — ones 
you don’t control — might use a value that’s not an object, or not even a valid 
pointer.
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Slipp Douglas Thompson
> Whenever I have two string literals @"XYZ" at different places in the same 
> compilation unit,
> and the XYZ are identical, then the compiler (or the Objective-C standard) 
> make sure that
> the pointers to those literals are identical?
> 
> In other words, the compiler unifies the two occurrences of the two literals, 
> thus effectively storing only one literal?

Yes that's why it works in your test, but as Graham Cox said, you “are taking 
advantage of undocumented implementation details”.  This behavior is not a 
standard at all.


> So what would be the proper way to do it?  Should I just define my own string 
> constant?

As others have suggested, always use isEqual: or isEqualToString: when doing 
NSString comparisons, never ==.  The Obj-C implementation does a pointer 
comparison first, so isEqual:/isEqualToString: do not incur a significant 
performance cost in this situation.

— Slipp



> On Sep 21, 2016, at 7:05 PM, Gabriel Zachmann  wrote:
> 
> 
>>> 
>>> how can the compiler know that '==' in this case is a NSString comparison?
>> 
>> It can’t because it isn't. What’s being compared are raw pointers. The 
>> string value is irrelevant.
> 
> Let me try to paraphrase, in order to check whether I am understanding 
> correctly.
> 
> Whenever I have two string literals @"XYZ" at different places in the same 
> compilation unit,
> and the XYZ are identical, then the compiler (or the Objective-C standard) 
> make sure that
> the pointers to those literals are identical?
> In other words, the compiler unifies the two occurrences of the two literals, 
> thus effectively storing only one literal?
> 
> 
>> So, this technique is generally Not A Good Idea™.
> 
> 
> If my understanding is correct, then I wholeheartedly agree.
> 
> That brings me to another question.  I've got this piece of code from an 
> example on MLMediaLibrary.
> 
> This is how I start the whole thing:
> 
>  [mediaLibrary_ addObserver: self
>  forKeyPath: @"mediaSources"
> options: 0
> context: (__bridge void *) @"mediaLibraryLoaded"];
> 
> And this is the beginning of the corresponding KVO:
> 
> - (void) observeValueForKeyPath: (NSString *) keyPath   ofObject: (id) object
>   change: (NSDictionary *) change context: (void *) 
> context
> {
>  MLMediaSource * mediaSource = [mediaLibrary_.mediaSources objectForKey: 
> MLMediaSourcePhotosIdentifier];
>  if ( context == (__bridge void *) @"mediaLibraryLoaded" )
>  {
> 
> 
> So what would be the proper way to do it?  Should I just define my own string 
> constant?
> 
> 
> 
> Best regards, 
> Gabriel.
> 
> 
> 
> ___
> 
> Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
> 
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
> 
> Help/Unsubscribe/Update your Subscription:
> https://lists.apple.com/mailman/options/cocoa-dev/apple%2Bcocoa-dev%40slippyd.com
> 
> This email sent to apple+cocoa-...@slippyd.com

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Quincey Morris
On Sep 21, 2016, at 17:05 , Gabriel Zachmann  wrote:
> 
> In other words, the compiler unifies the two occurrences of the two literals, 
> thus effectively storing only one literal?

Correct.

> So what would be the proper way to do it?

A global variable has a fixed, unique memory address, so you can do this:

static int MyContext; 
// does not need to be extern, just defined at the top level scope of 
some file, usually the relevant class implementation .m file
// type doesn’t matter, because the value is never used

But you can take advantage of a C quirk and actually write this:

static void* MyContext = 

This has the interesting property that MyContext == , which means you 
don’t have to worry about remembering the “&" operator when passing or testing 
the “context” parameter.

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Jens Alfke

> On Sep 21, 2016, at 4:44 PM, Gabriel Zachmann  wrote:
> 
> My question is: how can the compiler know that '==' in this case is a 
> NSString comparison?

It doesn’t. In Obj-C, “==“ is always a pointer comparison even if it’s applied 
to objects. It is NOT the same as -isEqual:.

This idiom with the `context` parameter of -observeValueForKeyPath: works 
because the context is just an opaque pointer. You register the context when 
you start observing, and the same exact pointer gets passed back to you when 
you’re called. So you can use the context to identify which observation this 
is, and since it’s just an opaque pointer value, you compare it using ‘==‘.

I’ve also seen people use C strings for this, i.e.
if (context == “mediaLibraryLoaded”) …
or just integers cast to void*:
if (context = (void*)1) …

The only danger when using string constants (NSString or char*) is that it’s 
only safe to do this if all the code is being linked into the same binary. The 
linker ensures that all references to “foo” refer to the same string constant 
in memory. (Same with @“foo”.) If you have some code in the app and some other 
code in a plugin library, though, they will almost certainly have different 
pointer values for “foo” or @“foo”.

—Jens
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Gabriel Zachmann

>> 
>> how can the compiler know that '==' in this case is a NSString comparison?
> 
> It can’t because it isn't. What’s being compared are raw pointers. The string 
> value is irrelevant.

Let me try to paraphrase, in order to check whether I am understanding 
correctly.

Whenever I have two string literals @"XYZ" at different places in the same 
compilation unit,
and the XYZ are identical, then the compiler (or the Objective-C standard) make 
sure that
the pointers to those literals are identical?
In other words, the compiler unifies the two occurrences of the two literals, 
thus effectively storing only one literal?


> So, this technique is generally Not A Good Idea™.


If my understanding is correct, then I wholeheartedly agree.

That brings me to another question.  I've got this piece of code from an 
example on MLMediaLibrary.

This is how I start the whole thing:

  [mediaLibrary_ addObserver: self
  forKeyPath: @"mediaSources"
 options: 0
 context: (__bridge void *) @"mediaLibraryLoaded"];

And this is the beginning of the corresponding KVO:

- (void) observeValueForKeyPath: (NSString *) keyPath   ofObject: (id) object
   change: (NSDictionary *) change context: (void *) context
{
  MLMediaSource * mediaSource = [mediaLibrary_.mediaSources objectForKey: 
MLMediaSourcePhotosIdentifier];
  if ( context == (__bridge void *) @"mediaLibraryLoaded" )
  {


So what would be the proper way to do it?  Should I just define my own string 
constant?



Best regards, 
Gabriel.



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Doug Hill

> On Sep 21, 2016, at 4:52 PM, Steve Mills  wrote:
> 
>> On Sep 21, 2016, at 18:44, Gabriel Zachmann  wrote:
>> 
>> I've got a stupid, curious question regarding a code snippet that I have 
>> found on the net (I tried it, it works).
>> 
>> Here is the code snippet:
>> 
>> - (void) observeValueForKeyPath: (NSString *) keyPath   ofObject: (id) object
>>   change: (NSDictionary *) change context: (void *) 
>> context
>> {
>>  if ( context == (__bridge void *) @"mediaLibraryLoaded" )
>>  {
>>// ...
>> 
>> 
>> My question is: how can the compiler know that '==' in this case is a 
>> NSString comparison?
>> Or is some other magic going on here? if so, which?
>> Does the compiler know it should perform some kind of dynamic method 
>> dispatch?
> 
> My guess, without seeing the code that set up the observer, is that it was 
> also set up with @"mediaLibraryLoaded", and the compiler collects and reuses 
> string constants, so the address is the same. I'd guess that if you ensure 
> that the string is a unique variable, it won't work.
> 
> NSString* s = [NSString stringWithFormat:@"%@%@%@", @"media", @"Library", 
> @"Loaded"];
> if(context == (__bridge void*)s)
> 
> Steve via iPad

For the above test, you could also try turning off the LLVM code-gen setting 
"gcc_reuse_strings".
(Which parenthetically, you probably wouldn't want to do in shipping code, 
particularly if you have a lot of strings.)

But yeah, as everyone says, it's generally not a good thing to rely upon this 
behavior, and just use -[NSString isEqual:]

Doug Hill
___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Graham Cox

> On 22 Sep 2016, at 9:44 AM, Gabriel Zachmann  wrote:
> 
> I have found on the net 

That isn’t always a recommendation ;)


>   if ( context == (__bridge void *) @"mediaLibraryLoaded" )


Don’t do this, even if it appears to work. You got lucky, or are taking 
advantage of undocumented implementation details.

This should be: if([(NSString*)context isEqualToString:@“mediaLibraryLoaded”])…

I expect the first thing -isEqualToString: does is a pointer comparison, so 
it’s unlikely to be significantly less performant for the case of when the 
pointers are literally identical.


—Graham



___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Daniel Stenmark
It’s doing a pointer comparison while making poor assumptions about how the 
compiler will optimize the storage of string constants.  This is bad; DO NOT DO 
THIS.

Dan

> On Sep 21, 2016, at 4:44 PM, Gabriel Zachmann  wrote:
> 
> I've got a stupid, curious question regarding a code snippet that I have 
> found on the net (I tried it, it works).
> 
> Here is the code snippet:
> 
> - (void) observeValueForKeyPath: (NSString *) keyPath   ofObject: (id) object
>change: (NSDictionary *) change context: (void *) 
> context
> {
>   if ( context == (__bridge void *) @"mediaLibraryLoaded" )
>   {
> // ...
> 
> 
> My question is: how can the compiler know that '==' in this case is a 
> NSString comparison?
> Or is some other magic going on here? if so, which?
> Does the compiler know it should perform some kind of dynamic method dispatch?
> 
> 
> Thanks a million for all kinds of enlightenment.
> 
> Best regards, 
> Gabriel.
> 
> 
> 
> 
> 
> 
> ___
> 
> Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
> 
> Please do not post admin requests or moderator comments to the list.
> Contact the moderators at cocoa-dev-admins(at)lists.apple.com
> 
> Help/Unsubscribe/Update your Subscription:
> https://lists.apple.com/mailman/options/cocoa-dev/dstenmark%40opentable.com
> 
> This email sent to dstenm...@opentable.com


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Steve Mills
> On Sep 21, 2016, at 18:44, Gabriel Zachmann  wrote:
> 
> I've got a stupid, curious question regarding a code snippet that I have 
> found on the net (I tried it, it works).
> 
> Here is the code snippet:
> 
> - (void) observeValueForKeyPath: (NSString *) keyPath   ofObject: (id) object
>change: (NSDictionary *) change context: (void *) 
> context
> {
>   if ( context == (__bridge void *) @"mediaLibraryLoaded" )
>   {
> // ...
> 
> 
> My question is: how can the compiler know that '==' in this case is a 
> NSString comparison?
> Or is some other magic going on here? if so, which?
> Does the compiler know it should perform some kind of dynamic method dispatch?

My guess, without seeing the code that set up the observer, is that it was also 
set up with @"mediaLibraryLoaded", and the compiler collects and reuses string 
constants, so the address is the same. I'd guess that if you ensure that the 
string is a unique variable, it won't work.

NSString* s = [NSString stringWithFormat:@"%@%@%@", @"media", @"Library", 
@"Loaded"];
if(context == (__bridge void*)s)

Steve via iPad


___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com

Re: Stupid objective-c question

2016-09-21 Thread Quincey Morris
On Sep 21, 2016, at 16:44 , Gabriel Zachmann  wrote:
> 
> how can the compiler know that '==' in this case is a NSString comparison?

It can’t because it isn't. What’s being compared are raw pointers. The string 
value is irrelevant.

> Or is some other magic going on here? if so, which?

No magic, but a (not very good) assumption, that literal strings are unique at 
run time, so a pointer to a particular literal string is a globally unique 
identifier.

Incidentally, this assumption is true only within a target. Literal strings in 
different targets may have different pointers.

So, this technique is generally Not A Good Idea™.

___

Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)

Please do not post admin requests or moderator comments to the list.
Contact the moderators at cocoa-dev-admins(at)lists.apple.com

Help/Unsubscribe/Update your Subscription:
https://lists.apple.com/mailman/options/cocoa-dev/archive%40mail-archive.com

This email sent to arch...@mail-archive.com