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

Stupid objective-c question

2016-09-21 Thread Gabriel Zachmann
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/archive%40mail-archive.com

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

Re: Objective-C Question about Categories and Subclasses

2015-11-30 Thread Jens Alfke

> On Nov 30, 2015, at 5:18 AM, Dave  wrote:
> 
> I’m guessing it overrides it? Right?

Right. A category method is a normal method. It just isn’t declared in the same 
@interface.

—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: Objective-C Question about Categories and Subclasses

2015-11-30 Thread Dave
Thanks for the confirmation, I wanted to double check because if it didn’t I’d 
waste a lot of time…...



___

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

Objective-C Question about Categories and Subclasses

2015-11-30 Thread Dave
Hi,

If I have a category on a class (call it LTWClassX) with a method called 
-(void) foo;

If I then subclass from LTWClassX - call it LTWClassY. What happens if I now 
define foo in the Subclass?

I’m guessing it overrides it? Right?

Thanks a lot
Dave


___

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: Objective-C Question

2013-03-15 Thread Dave


On 13 Mar 2013, at 09:24, Markus Spoettl wrote:


On 3/13/13 9:36 AM, Dave wrote:


On 12 Mar 2013, at 21:34, Graham Cox wrote:



On 13/03/2013, at 6:53 AM, Dave d...@looktowindward.com wrote:

If that is the case, then how do you signal to the compiler/ 
analyzer that you

are returning a retained object?


In general you shouldn't return a retained object (unless it's  
temporarily

retained and will be autoreleased of course)


Why? Where does it say this?


https://developer.apple.com/library/mac/#documentation/Cocoa/ 
Conceptual/MemoryMgmt/Articles/mmRules.html


I've looked at this, it doesn't say anything about it - where exactly  
are you looking?


What I did see:

You own any object you create
You create an object using a method whose name begins with “alloc”,  
“new”, “copy”, or “mutableCopy” (for example, alloc, newObject, or  
mutableCopy).


So, newDict as a name to return a retained object is fine, at least I  
can't see anywhere it says it isn't!


Besides all this, it just plain makes sense to (to me and many  
others) do it this way. It keeps everything sweet, the Analyser works  
fine, no lurking autorelease issues and much less fear that you will  
over or under release the object in question.


All the Best
Dave


___

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: Another Gnarly Objective-C Question!

2013-03-15 Thread Dave


On 13 Mar 2013, at 09:13, Jean-Daniel Dupas wrote:



Le 13 mars 2013 à 01:55, Wim Lewis w...@omnigroup.com a écrit :



On 12 Mar 2013, at 2:08 AM, Graham Cox wrote:
in a + method, [self class] === self. Once you've got that,  
you've got it.




You're overthinking this.

A class method is just an instance method of the class object. No  
magic at all. So all this confusion you've caused yourself about  
[super class] and so on is wholly unnecessary to correctly use  
class methods.


To be very slightly pedantic, the only magic here is 'super' ---  
sending a message to super (which you can only do from a method  
implementation) is special syntax that searches for the method  
starting with the implementation's class's superclass, rather than  
at the receiver's actual class. Everything else is non-magic. (In  
general, that's been one of the strengths of ObjC: very little  
magic.)




To be ever more pedantic, there is other magic involved when  
sending a message to a class.
If there is no class method that matches the selector, the runtime  
will then search for instance methods of the root class. So you can  
use NSObject instance (like performSelector:) method on all  
NSObject subclasses.


http://www.sealiesoftware.com/blog/archive/2009/04/14/ 
objc_explain_Classes_and_metaclasses.html


-- Jean-Daniel


Yes, I've noticed this, it also works if you put an app-wide  
(via .pch file) Category on NSObect, so you can define your own Catch  
All + methods, which is very cool IMO!


All the Best
Dave



___

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: Objective-C Question

2013-03-14 Thread Richard Heard
Your logic is clearly flawed. This only seems to replace occurrences of $ with 
the word DOLLAR. 

Also, if you are dealing with large strings, you could always use one of the 
below idioms to reduce memory pressure.


@autoreleasepool { }
or 

NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
[pool drain];

-R


On 13/03/2013, at 3:07:30 AM, Dave d...@looktowindward.com wrote:

 
 On 13 Mar 2013, at 09:24, Markus Spoettl wrote:
 
 On 3/13/13 9:36 AM, Dave wrote:
 
 On 12 Mar 2013, at 21:34, Graham Cox wrote:
 
 
 On 13/03/2013, at 6:53 AM, Dave d...@looktowindward.com wrote:
 
 If that is the case, then how do you signal to the compiler/analyzer that 
 you
 are returning a retained object?
 
 In general you shouldn't return a retained object (unless it's temporarily
 retained and will be autoreleased of course)
 
 Why? Where does it say this?
 
 https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html
 
 And Autorelease is evil and should never be used if it can be avoided!
 
 Nonsense.
 
 
 Obviously, it isn't evil, but from experience of working on 5 or more major 
 iOS applications, I've found most bugs were caused as a consequence of 
 autorelease, that's why I avoid it if possible. I don't have a problem with 
 memory management, it's simple as long as you follow the rules.
 
 Avoiding autorelease makes it run faster anyway and makes the whole app more 
 robust in general. Autorelease in the wrong hands can cause massive 
 inefficiencies that you'd never code otherwise, here are some examples of 
 what I mean:
 
 -(NSString*) processString:(NSString*) theString
 {
 NSString* myWorkString;
 
 myWorkString = [theString stringByReplacingOccurencesOfSting:@/b 
 with:@BOLD]; //1
 myWorkString = [theString stringByReplacingOccurencesOfSting:@/i 
 with:@ITALICS];  //2
 myWorkString = [theString stringByReplacingOccurencesOfSting:@/u 
 with:@UNDERLINE];//3
 myWorkString = [theString stringByReplacingOccurencesOfSting:@* 
 with:@ASTERISK];  //4
 myWorkString = [theString stringByReplacingOccurencesOfSting:@ 
 with:@AMPERSAND]; //5
 myWorkString = [theString stringByReplacingOccurencesOfSting:@$ 
 with:@DOLLAR];//6
 
 and so on
 
 return myWorkString;
 }
 
 This code creates 5 strings that are not needed and will clog up memory until 
 the runloop is called or the pool is drained. Imagine there were 30 such 
 replacements going on and the initial theString is large ( 100K) and there 
 are 100's of these strings.
 
 You don't need a degree in applied meta physics to see where this is going. 
 It's not the fault of autorelease I know, it's the fault on inexperienced 
 developers or people that blindly follow rules.
 
 The underlying problem is that it makes the above method data dependent 
 without really drawing much attention to this fact. I actually had a bug that 
 was caused by this. I worked on an iPad app for an International Newspaper. 
 The App was working ok, until one day it crashed a 5 AM when the new edition 
 was published and the iPad client software downloaded and processed it. When 
 it got to the sports section a method similar to the above (although a lot 
 more complex with a LOT more autorealsed objects) crashed. I got in a 6 AM 
 and it took me a good while to figure out what was wrong. On that particular 
 day, the paper published the football (soccer) league tables for the whole of 
 the UK. Apart from there being a loads of data, it was also heavily 
 attrubuted, bold, italics, colours etc. Well it was too much for the method 
 and when it had built up around 80 to 100 MB of useless autoreleased strings, 
 it crashed!!
 
 There are loads of other problems I come across as a side effect of junior 
 (and sometimes senior) developers using autorelease, but I think the above 
 described above was the worst.
 
 That's why I say it's evil and I avoid it with a vengeance. So why do you 
 think it's a force for good?
 
 Besides all this, is it really so hard to add:
 
 [ release];
 
 It's less typing than autorelease anyway!!!
 
 All the Best
 Dave
 
 
 ___
 
 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/heardrwt%40gmail.com
 
 This email sent to heard...@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:

Re: Objective-C Question

2013-03-14 Thread Jean-Daniel Dupas
Le 14 mars 2013 à 11:12, Richard Heard heard...@gmail.com a écrit :

 Your logic is clearly flawed. This only seems to replace occurrences of $ 
 with the word DOLLAR. 
 
 Also, if you are dealing with large strings, you could always use one of the 
 below idioms to reduce memory pressure.
 
 
 @autoreleasepool { }
 or 
 
 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 [pool drain];
 
 -R
 

Or simply work on a mutable string when you plan to mutate it. 

 On 13/03/2013, at 3:07:30 AM, Dave d...@looktowindward.com wrote:
 
 
 On 13 Mar 2013, at 09:24, Markus Spoettl wrote:
 
 On 3/13/13 9:36 AM, Dave wrote:
 
 On 12 Mar 2013, at 21:34, Graham Cox wrote:
 
 
 On 13/03/2013, at 6:53 AM, Dave d...@looktowindward.com wrote:
 
 If that is the case, then how do you signal to the compiler/analyzer 
 that you
 are returning a retained object?
 
 In general you shouldn't return a retained object (unless it's temporarily
 retained and will be autoreleased of course)
 
 Why? Where does it say this?
 
 https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html
 
 And Autorelease is evil and should never be used if it can be avoided!
 
 Nonsense.
 
 
 Obviously, it isn't evil, but from experience of working on 5 or more major 
 iOS applications, I've found most bugs were caused as a consequence of 
 autorelease, that's why I avoid it if possible. I don't have a problem with 
 memory management, it's simple as long as you follow the rules.
 
 Avoiding autorelease makes it run faster anyway and makes the whole app more 
 robust in general. Autorelease in the wrong hands can cause massive 
 inefficiencies that you'd never code otherwise, here are some examples of 
 what I mean:
 
 -(NSString*) processString:(NSString*) theString
 {
 NSString*myWorkString;
 
 myWorkString = [theString stringByReplacingOccurencesOfSting:@/b 
 with:@BOLD];//1
 myWorkString = [theString stringByReplacingOccurencesOfSting:@/i 
 with:@ITALICS]; //2
 myWorkString = [theString stringByReplacingOccurencesOfSting:@/u 
 with:@UNDERLINE];   //3
 myWorkString = [theString stringByReplacingOccurencesOfSting:@* 
 with:@ASTERISK]; //4
 myWorkString = [theString stringByReplacingOccurencesOfSting:@ 
 with:@AMPERSAND];//5
 myWorkString = [theString stringByReplacingOccurencesOfSting:@$ 
 with:@DOLLAR];   //6
 
 and so on
 
 return myWorkString;
 }
 
 This code creates 5 strings that are not needed and will clog up memory 
 until the runloop is called or the pool is drained. Imagine there were 30 
 such replacements going on and the initial theString is large ( 100K) and 
 there are 100's of these strings.
 
 You don't need a degree in applied meta physics to see where this is going. 
 It's not the fault of autorelease I know, it's the fault on inexperienced 
 developers or people that blindly follow rules.
 
 The underlying problem is that it makes the above method data dependent 
 without really drawing much attention to this fact. I actually had a bug 
 that was caused by this. I worked on an iPad app for an International 
 Newspaper. The App was working ok, until one day it crashed a 5 AM when the 
 new edition was published and the iPad client software downloaded and 
 processed it. When it got to the sports section a method similar to the 
 above (although a lot more complex with a LOT more autorealsed objects) 
 crashed. I got in a 6 AM and it took me a good while to figure out what was 
 wrong. On that particular day, the paper published the football (soccer) 
 league tables for the whole of the UK. Apart from there being a loads of 
 data, it was also heavily attrubuted, bold, italics, colours etc. Well it 
 was too much for the method and when it had built up around 80 to 100 MB of 
 useless autoreleased strings, it crashed!!
 
 There are loads of other problems I come across as a side effect of junior 
 (and sometimes senior) developers using autorelease, but I think the above 
 described above was the worst.
 
 That's why I say it's evil and I avoid it with a vengeance. So why do you 
 think it's a force for good?
 
 Besides all this, is it really so hard to add:
 
 [ release];
 
 It's less typing than autorelease anyway!!!
 
 All the Best
 Dave
 
 
 ___
 
 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/heardrwt%40gmail.com
 
 This email sent to heard...@gmail.com
 
 ___
 
 Cocoa-dev mailing list (Cocoa-dev@lists.apple.com)
 
 Please do not post admin requests or 

Re: Objective-C Question

2013-03-14 Thread Fritz Anderson
And run the thing under Instruments, which would undoubtedly have shown memory 
usage spiking even with modest data sets.

— F

On 14 Mar 2013, at 5:40 AM, Jean-Daniel Dupas devli...@shadowlab.org wrote:

 Le 14 mars 2013 à 11:12, Richard Heard heard...@gmail.com a écrit :
 
 Your logic is clearly flawed. This only seems to replace occurrences of $ 
 with the word DOLLAR. 
 
 Also, if you are dealing with large strings, you could always use one of the 
 below idioms to reduce memory pressure.
 
 
 @autoreleasepool { }
 or 
 
 NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
 [pool drain];
 
 -R
 
 
 Or simply work on a mutable string when you plan to mutate it. 
 
 On 13/03/2013, at 3:07:30 AM, Dave d...@looktowindward.com wrote:
 
 
 On 13 Mar 2013, at 09:24, Markus Spoettl wrote:
 
 On 3/13/13 9:36 AM, Dave wrote:
 
 On 12 Mar 2013, at 21:34, Graham Cox wrote:
 
 
 On 13/03/2013, at 6:53 AM, Dave d...@looktowindward.com wrote:
 
 If that is the case, then how do you signal to the compiler/analyzer 
 that you
 are returning a retained object?
 
 In general you shouldn't return a retained object (unless it's 
 temporarily
 retained and will be autoreleased of course)
 
 Why? Where does it say this?
 
 https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html
 
 And Autorelease is evil and should never be used if it can be avoided!
 
 Nonsense.
 
 
 Obviously, it isn't evil, but from experience of working on 5 or more major 
 iOS applications, I've found most bugs were caused as a consequence of 
 autorelease, that's why I avoid it if possible. I don't have a problem with 
 memory management, it's simple as long as you follow the rules.
 
 Avoiding autorelease makes it run faster anyway and makes the whole app 
 more robust in general. Autorelease in the wrong hands can cause massive 
 inefficiencies that you'd never code otherwise, here are some examples of 
 what I mean:
 
 -(NSString*) processString:(NSString*) theString
 {
 NSString*   myWorkString;
 
 myWorkString = [theString stringByReplacingOccurencesOfSting:@/b 
 with:@BOLD];   //1
 myWorkString = [theString stringByReplacingOccurencesOfSting:@/i 
 with:@ITALICS];//2
 myWorkString = [theString stringByReplacingOccurencesOfSting:@/u 
 with:@UNDERLINE];  //3
 myWorkString = [theString stringByReplacingOccurencesOfSting:@* 
 with:@ASTERISK];//4
 myWorkString = [theString stringByReplacingOccurencesOfSting:@ 
 with:@AMPERSAND];   //5
 myWorkString = [theString stringByReplacingOccurencesOfSting:@$ 
 with:@DOLLAR];  //6
 
 and so on
 
 return myWorkString;
 }
 
 This code creates 5 strings that are not needed and will clog up memory 
 until the runloop is called or the pool is drained. Imagine there were 30 
 such replacements going on and the initial theString is large ( 100K) and 
 there are 100's of these strings.
 
 You don't need a degree in applied meta physics to see where this is going. 
 It's not the fault of autorelease I know, it's the fault on inexperienced 
 developers or people that blindly follow rules.
 
 The underlying problem is that it makes the above method data dependent 
 without really drawing much attention to this fact. I actually had a bug 
 that was caused by this. I worked on an iPad app for an International 
 Newspaper. The App was working ok, until one day it crashed a 5 AM when the 
 new edition was published and the iPad client software downloaded and 
 processed it. When it got to the sports section a method similar to the 
 above (although a lot more complex with a LOT more autorealsed objects) 
 crashed. I got in a 6 AM and it took me a good while to figure out what was 
 wrong. On that particular day, the paper published the football (soccer) 
 league tables for the whole of the UK. Apart from there being a loads of 
 data, it was also heavily attrubuted, bold, italics, colours etc. Well it 
 was too much for the method and when it had built up around 80 to 100 MB of 
 useless autoreleased strings, it crashed!!
 
 There are loads of other problems I come across as a side effect of junior 
 (and sometimes senior) developers using autorelease, but I think the above 
 described above was the worst.
 
 That's why I say it's evil and I avoid it with a vengeance. So why do you 
 think it's a force for good?
 
 Besides all this, is it really so hard to add:
 
 [ release];
 
 It's less typing than autorelease anyway!!!
 
 All the Best
 Dave
 
 
 ___
 
 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:
 

Re: Objective-C Question

2013-03-13 Thread Dave


On 12 Mar 2013, at 21:34, Graham Cox wrote:



On 13/03/2013, at 6:53 AM, Dave d...@looktowindward.com wrote:

If that is the case, then how do you signal to the compiler/ 
analyzer that you are returning a retained object?


In general you shouldn't return a retained object (unless it's  
temporarily retained and will be autoreleased of course)


Why? Where does it say this? And Autorelease is evil and should never  
be used if it can be avoided!


. If you are routinely doing this then your design is flawed. The  
reason it's hard to signal to the compiler that you're returning a  
retained object is that you shouldn't be doing it. When you have to  
do it, use the word 'new' in the method.


How many years experience do you have writing applications and OS  
level software? I've been doing it since that late 70's. And, in all  
that time, I have never (well rarely it's a long time!) heard a more  
silly statement then  If you are routinely doing this then your  
design is flawed. (this meaning returning a retained object). In  
that case Unix, MacOS X and most software on the market has a flawed  
design according to this logic! I've never seen anything about this  
written down in any Apple document. In fact see below - Apple seems  
to disagree with you!


The reason it's hard to signal to the compiler that you're  
returning a retained object is that you shouldn't be doing it. When  
you have to do it, use the word 'new' in the method.



So, the design is flawed because it's hard to signal to the compiler  
that you are retuning a retain object? Do you realize how silly that  
sounds? How can a compiler option/feature affect a design? Also, are  
you saying that ARC is a flawed design? With ARC you do nothing BUT  
return retained objects!


So lets say we have a number of fairly complex (non ARC) iPad  
Applications that work wonderfully with no memory leaks. The code is  
well written, commented and easy to understand and maintain, but  
these Apps contained methods that routinely return retained objects.  
Would you then say these apps have a Flawed Design simply for this  
reason?


The fact of the matter is that this *is* routinely done in many  
commercial applications that I have worked on and by many developers,  
both on the Mac and iOS. Originally, I don't think there was a new  
prefix, so older code has lots of methods beginning with alloc. The  
new was added later to make it easier to signal to the compiler the  
the method is returning a retained object. Most developers I worked  
with think that using new as a prefix when returning a retained  
object.



Besides all this, it isn't hard to signal to the compiler you are  
returning a retained object, you just prefix the name with new,  
alloc, retain  etc.  As per:


http://clang.llvm.org/docs/LanguageExtensions.html#related-result-types

Unless there is another prefix to use, they I am going to continue  
ignore it too!


Again, no offence intended but when a person doesn't follow a rule  
because they think it doesn't apply to them, it's just a sign of  
inexperience and/or lack of understanding. Sorry, but there it is.


I don't think the rule doesn't apply to just me, I think it's  
doesn't apply to *anyone* and that it either isn't a rule and you are  
mistaken or if it is a rule, it's a stupid one and I don't follow  
stupid rules.


The only reason you have given me is that this is bad is that hard  
to signal to the compiler that you're returning a retained object  
but it isn't hard, you just prefix with new. If there are other  
reasons, then please do let me know and I will consider what you say,  
but so far you've not given one reference to an Apple doc that  
categorically states this and no real reason why its bad apart from  
it's hard to signal the compiler what you are doing, which is isn't!  
So, pardon me if I take no notice of what you say!


There are loads of rules in life that no one pays any attention to!  
There are load of rules that Apple have made that are routinely  
broken. A few that spring to mind are, using _ in iVar names, have  
getters/setters with non-standard names,



For instance, there is a law in England that dates back hundreds of  
year that states that a Male may urinate on the public highway as  
long as he alerts people to this fact uses the offside of his cab to  
shield passers by from this unsightly spectacle! How many men do you  
hear announcing in Oxford street that that are going to Urinate and  
then doing it against the offside of their car! Not Many!


There is another that says perambulated baby carriages much be  
wheeled off the pavement and on the road! How many people do you see  
wheeling their offspring along the slow lane side of the A40? Not many.


However, according to you, these rules must be obeyed! So next time  
you need to relieve yourself while wheeling your baby buggy along a  
public highway, just announce the fact that you are about to urinate  
and 

Re: Another Gnarly Objective-C Question!

2013-03-13 Thread Jean-Daniel Dupas

Le 13 mars 2013 à 01:55, Wim Lewis w...@omnigroup.com a écrit :

 
 On 12 Mar 2013, at 2:08 AM, Graham Cox wrote:
 in a + method, [self class] === self. Once you've got that, you've got it.
 
 
 
 You're overthinking this.
 
 A class method is just an instance method of the class object. No magic at 
 all. So all this confusion you've caused yourself about [super class] and so 
 on is wholly unnecessary to correctly use class methods.
 
 To be very slightly pedantic, the only magic here is 'super' --- sending a 
 message to super (which you can only do from a method implementation) is 
 special syntax that searches for the method starting with the 
 implementation's class's superclass, rather than at the receiver's actual 
 class. Everything else is non-magic. (In general, that's been one of the 
 strengths of ObjC: very little magic.)
 

To be ever more pedantic, there is other magic involved when sending a message 
to a class.
If there is no class method that matches the selector, the runtime will then 
search for instance methods of the root class. So you can use NSObject instance 
(like performSelector:) method on all NSObject subclasses.

http://www.sealiesoftware.com/blog/archive/2009/04/14/objc_explain_Classes_and_metaclasses.html

-- Jean-Daniel





___

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: Objective-C Question

2013-03-13 Thread Markus Spoettl

On 3/13/13 9:36 AM, Dave wrote:


On 12 Mar 2013, at 21:34, Graham Cox wrote:



On 13/03/2013, at 6:53 AM, Dave d...@looktowindward.com wrote:


If that is the case, then how do you signal to the compiler/analyzer that you
are returning a retained object?


In general you shouldn't return a retained object (unless it's temporarily
retained and will be autoreleased of course)


Why? Where does it say this?


https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html


And Autorelease is evil and should never be used if it can be avoided!


Nonsense.

Regards
Markus
--
__
Markus Spoettl
___

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: Objective-C Question

2013-03-13 Thread Dave


On 12 Mar 2013, at 21:25, Graham Cox wrote:



On 13/03/2013, at 2:41 AM, Dave d...@looktowindward.com wrote:


So, what is it? Wind up merchant or Moron?



I don't think there's any need for this. If I caused offence, it  
was unintended (I sometimes have trouble anticipating how others  
might receive statements I make, that's just something I have to  
live with).


The further discussion doesn't really convince me that you've  
really understood it, but if you have, great. Personally I have no  
stake in whether you succeed or not, so if you choose to ignore  
advice or insult the adviser, it makes no difference to me.



Look, you made a number of silly and wild comments, all I did was to  
ask you do back them up. Perhaps I could have been kinder, but to be  
honest, from your comments it showed you didn't even bother to read  
the original post and the code contained therein, so again:


@interface BaseClass
+(NSMutableDictionary*) newDict;
@end

@implementation BaseClass

+(NSMutableDictionary*) newDict
{
return [[NSMutableDictionary alloc] init];
}

@class NewClass;

@interface NewClass : BaseClass
+(NSMutableDictionary*) newDict;
@end

#import BaseClass.h
@implementation NewClass

+(NSMutableDictionary*) newDict
{
NSMutableDictionary*myDict;

myDict = [[super class] newDict];   
//** bug
[myDict setObject:@Some Data forKey:@someKey];

return myDict;  
}

You said of this code:


Why not state you goals instead of give us a lump of incoherent code?



How is the above code incoherent? The text from that email:

I had assumed (and I thought I'd done something like this before)  
that the:


myDict = [[super class] newDict];

statement would call newDict in BaseClass Instead it calls the  
version in NewClass and goes into an infinite loop!!


How is this not stating my goals?

The attempts you made show a clear lack of understanding about  
inheritance, which is what others were trying to tell you.



In what way does the above code show a clear lack of understanding  
about inheritance ? To me and many others on this list, it just  
showed a typeo/bug in one line of newly added code.


Then you post some other code, that was slower and didn't even do the  
same job! Then you argued that it did do the same job and made light  
of the fact that is was slower and even questioned the fact that it  
might be slower. From that I could have said the attempts you made,  
showed a clear lack of understanding abut memory management and how  
container objects work in Cocoa.


The fact of the matter is that allocating a read-only array and then  
copying it's contents into a mutable array is slower, but worse than  
this, doesn't do the same thing at all. When I pointed out how it's  
different, you went quiet and then had a go about something else!


The latest post really takes the cake though:

In general you shouldn't return a retained object (unless it's  
temporarily retained and will be autoreleased of course). If you  
are routinely doing this then your design is flawed. The reason  
it's hard to signal to the compiler that you're returning a  
retained object is that you shouldn't be doing it. When you have to  
do it, use the word 'new' in the method.



According to you, many, many Apps have design flaws because they  
contain methods that return retained objects! What a croc! rofl!


So, lets explore this stupidity a little!  This is the Non-ARC case,  
obviously. I need to create an Object that has a different class type  
than the class I am working in. I want to retain the object locally  
in the current method. Normally I would write


-(Obj*) newObject
{
Obj*myObj;

myObj = [[Obj alloc] init];

// setup some fields in myObj

return myObj;
}

//  Calling method:

Obj*myObj;

myObj = [self newObj];

// use myObj

[myObj release];


You are saying that this is a flawed design? Worse than that, you  
seem to be saying that:


-(Obj*) getObject
{
Obj*myObj;

myObj = [[Obj alloc] init];

// setup some fields in myObj

return [myOb autorelease]j;
}


//  Calling method:

Obj*myObj;

myObj = [self getObject];
[myObj retain];

// use myObj

[myObj release];


Is a better design? Is this really what you are saying? Because if it  
is, I don't care about what any rule says. the second example is  
Flawed over the first for obvious reasons. If you really do think  
this, then justify it and I don't mean point me to some Apple Doc of  
rules that was written years ago and has no real relevance to the  
real world. Tell me in technical terms why example 2 is better than  
example 1 or come up with a better way altogether.


So far AFAIAC you have been wrong on most of what you have said. I've  
pointed out the reasons why I think you are wrong but you just ignore  
them and pick on something else to be wrong about.


If you don' justify your reasoning, then regardless of 

Moderator - Re: Objective-C Question

2013-03-13 Thread Scott Anguish
Moderator

I've had a number of complaints about this thread.

This thread has gone beyond all reasonable value and the behavior is not 
acceptable.

Nobody has a requirement to read and answer questions. The questions have been 
answered politely by posters who have a long history on the list of helping 
people.

Do not respond to this on the list.



___

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: Objective-C Question

2013-03-13 Thread Dave


On 13 Mar 2013, at 09:24, Markus Spoettl wrote:


On 3/13/13 9:36 AM, Dave wrote:


On 12 Mar 2013, at 21:34, Graham Cox wrote:



On 13/03/2013, at 6:53 AM, Dave d...@looktowindward.com wrote:

If that is the case, then how do you signal to the compiler/ 
analyzer that you

are returning a retained object?


In general you shouldn't return a retained object (unless it's  
temporarily

retained and will be autoreleased of course)


Why? Where does it say this?


https://developer.apple.com/library/mac/#documentation/Cocoa/ 
Conceptual/MemoryMgmt/Articles/mmRules.html


And Autorelease is evil and should never be used if it can be  
avoided!


Nonsense.



Obviously, it isn't evil, but from experience of working on 5 or more  
major iOS applications, I've found most bugs were caused as a  
consequence of autorelease, that's why I avoid it if possible. I  
don't have a problem with memory management, it's simple as long as  
you follow the rules.


Avoiding autorelease makes it run faster anyway and makes the whole  
app more robust in general. Autorelease in the wrong hands can cause  
massive inefficiencies that you'd never code otherwise, here are some  
examples of what I mean:


-(NSString*) processString:(NSString*) theString
{
NSString*   myWorkString;

myWorkString = [theString stringByReplacingOccurencesOfSting:@/b  
with:@BOLD]; 	//1
myWorkString = [theString stringByReplacingOccurencesOfSting:@/i  
with:@ITALICS];	//2
myWorkString = [theString stringByReplacingOccurencesOfSting:@/u  
with:@UNDERLINE];			//3
myWorkString = [theString stringByReplacingOccurencesOfSting:@*  
with:@ASTERISK];//4
myWorkString = [theString stringByReplacingOccurencesOfSting:@  
with:@AMPERSAND];			//5
myWorkString = [theString stringByReplacingOccurencesOfSting:@$  
with:@DOLLAR];//6


and so on

return myWorkString;
}

This code creates 5 strings that are not needed and will clog up  
memory until the runloop is called or the pool is drained. Imagine  
there were 30 such replacements going on and the initial theString is  
large ( 100K) and there are 100's of these strings.


You don't need a degree in applied meta physics to see where this is  
going. It's not the fault of autorelease I know, it's the fault on  
inexperienced developers or people that blindly follow rules.


The underlying problem is that it makes the above method data  
dependent without really drawing much attention to this fact. I  
actually had a bug that was caused by this. I worked on an iPad app  
for an International Newspaper. The App was working ok, until one day  
it crashed a 5 AM when the new edition was published and the iPad  
client software downloaded and processed it. When it got to the  
sports section a method similar to the above (although a lot more  
complex with a LOT more autorealsed objects) crashed. I got in a 6 AM  
and it took me a good while to figure out what was wrong. On that  
particular day, the paper published the football (soccer) league  
tables for the whole of the UK. Apart from there being a loads of  
data, it was also heavily attrubuted, bold, italics, colours etc.  
Well it was too much for the method and when it had built up around  
80 to 100 MB of useless autoreleased strings, it crashed!!


There are loads of other problems I come across as a side effect of  
junior (and sometimes senior) developers using autorelease, but I  
think the above described above was the worst.


That's why I say it's evil and I avoid it with a vengeance. So why  
do you think it's a force for good?


Besides all this, is it really so hard to add:

[ release];

It's less typing than autorelease anyway!!!

All the Best
Dave


___

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: Another Gnarly Objective-C Question!

2013-03-13 Thread John McCall
On Mar 13, 2013, at 2:13 AM, Jean-Daniel Dupas devli...@shadowlab.org wrote:
 Le 13 mars 2013 à 01:55, Wim Lewis w...@omnigroup.com a écrit :
 On 12 Mar 2013, at 2:08 AM, Graham Cox wrote:
 in a + method, [self class] === self. Once you've got that, you've got it.
 
 
 
 You're overthinking this.
 
 A class method is just an instance method of the class object. No magic at 
 all. So all this confusion you've caused yourself about [super class] and 
 so on is wholly unnecessary to correctly use class methods.
 
 To be very slightly pedantic, the only magic here is 'super' --- sending a 
 message to super (which you can only do from a method implementation) is 
 special syntax that searches for the method starting with the 
 implementation's class's superclass, rather than at the receiver's actual 
 class. Everything else is non-magic. (In general, that's been one of the 
 strengths of ObjC: very little magic.)
 
 
 To be ever more pedantic, there is other magic involved when sending a 
 message to a class.
 If there is no class method that matches the selector, the runtime will then 
 search for instance methods of the root class.

Note that this isn't magic really;  it's a quirk of the type system (both 
formal and dynamic).  The root metaclass is a subclass of the root class.

This can be problematic if you really want your root class to have a layout 
that's bigger than just an isa field, because the ABI and runtime just hardcode 
the layout of classes and there is no room for extra fields there — thus you 
need to be sure that anything using your extra fields is never invoked on a 
class object.

John.
___

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: Another Gnarly Objective-C Question!

2013-03-13 Thread Jean-Daniel Dupas

Le 13 mars 2013 à 18:13, John McCall rjmcc...@apple.com a écrit :

 On Mar 13, 2013, at 2:13 AM, Jean-Daniel Dupas devli...@shadowlab.org wrote:
 Le 13 mars 2013 à 01:55, Wim Lewis w...@omnigroup.com a écrit :
 On 12 Mar 2013, at 2:08 AM, Graham Cox wrote:
 in a + method, [self class] === self. Once you've got that, you've got it.
 
 
 
 You're overthinking this.
 
 A class method is just an instance method of the class object. No magic at 
 all. So all this confusion you've caused yourself about [super class] and 
 so on is wholly unnecessary to correctly use class methods.
 
 To be very slightly pedantic, the only magic here is 'super' --- sending a 
 message to super (which you can only do from a method implementation) is 
 special syntax that searches for the method starting with the 
 implementation's class's superclass, rather than at the receiver's actual 
 class. Everything else is non-magic. (In general, that's been one of the 
 strengths of ObjC: very little magic.)
 
 
 To be ever more pedantic, there is other magic involved when sending a 
 message to a class.
 If there is no class method that matches the selector, the runtime will then 
 search for instance methods of the root class.
 
 Note that this isn't magic really;  it's a quirk of the type system (both 
 formal and dynamic).  The root metaclass is a subclass of the root class.

Yes, nothing is magic if the magician reveals its tricks, that's why he should 
not do that  ;-)

 This can be problematic if you really want your root class to have a layout 
 that's bigger than just an isa field, because the ABI and runtime just 
 hardcode the layout of classes and there is no room for extra fields there — 
 thus you need to be sure that anything using your extra fields is never 
 invoked on a class object.

I usually avoid this kind of issue by not writing root class. The extra fields 
issue is not the only one that a root class can have. Even methods that do not 
access ivars should take care of the Class case (retain/release/autorelease for 
instance).

-- Jean-Daniel




___

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: Objective-C Question

2013-03-12 Thread Dave


On 11 Mar 2013, at 21:45, John McCall wrote:



On Mar 11, 2013, at 2:02 PM, Dave d...@looktowindward.com wrote:



On 11 Mar 2013, at 20:53, John McCall wrote:


On Mar 11, 2013, at 1:33 PM, Dave d...@looktowindward.com wrote:

On 11 Mar 2013, at 20:26, Mike Abdullah wrote:


I had assumed (and I thought I'd done something like this  
before) that the:


myDict = [[super class] newDict];

statement would call newDict in BaseClass Instead it calls  
the version in NewClass and goes into an infinite loop!!


Yes. [super class] calls super's implementation of the -class  
method. You haven't overridden -class, so it does the same  
thing as [self class].


People often make the same mistake in trying to do [super  
respondsToSelector…


I'm guessing what you're really after is [[self superclass]  
newDict]




Thanks a Million, yes that's what I wanted!


Are you sure?  This will indeed call the superclass's 'newDict',  
but the 'self' object will be the superclass, not your class.   
That means it'll (almost certainly) create an instance of your  
class's superclass.  The easier way to do this is just [Foo  
newDict], where Foo is the name of your superclass.


If you want to invoke your superclass method, but with your class  
as 'self' — i.e. if you want to create an instance of your class  
— you should use [super newDict].


I don't know what you mean by:


i.e. if you want to create an instance of your class


I don't want to create an instance of my class, I want the class  
to return a dictionary, that gets things added from the current  
class down through the inheritance hierarchy,


BaseClass alloc's a dict and puts in some data,
Subclass1 calls base class and it's it own data.
Subclass2 calls subclass1.

How is this creating an instance of any object except the NSDict?


Where do you think Subclass1's own data goes if the object  
allocated is actually a BaseClass?


I'm not allocating a base class or any other kind of class except a  
dictionary. Did I say anything about instance data? No. The data I  
mean is NOT instance data, how could it be? There is no object  
allocated in this example (except the dictionary). I am using class +  
methods and they work on the Class,


I could just say [BaseClass newDict], but the reason I didn't is  
so the code is not dependent on knowing the base class, e.g. it  
can move position in the hierarchy and still call the correct  
class method.


Do you want the created dictionary to have the instance variables  
and methods you've defined in your subclass or not?  If so, you  
need to create an instance of your subclass.


There are no instance variables as I keep saying, this no instance,  
so how can there be instance variables?


I think you are having basic conceptual problems with inheritance  
here.


I don't think you understand the difference between class methods and  
instance methods. Here is an example of what I mean:


BaseClass  (Class not an instance of a class).
+(MSMutableDictionary*) newDict
{
MSMutableDictionary*myDict;

myDict = [[MSMutableDictionary alloc] init];
[myDIct setObect:@SomeaValueX forKey:@someKeyX];

return myDict;
}

Subclass1:

+(MSMutableDictionary*) newDict
{
MSMutableDictionary*myDict;

myDict = [super newDict];
[myDIct setObect:@SomeValueY forKey:@someKeyY];

return myDict;
}


Subclass2:

+(MSMutableDictionary*) newDict
{
MSMutableDictionary*myDict;

myDict = [super newDict];
[myDIct setObect:@SomeValueZ forKey:@someKeyZ];

return myDict;
}


No instance data in site and no instances of the objects in question,  
just class methods.


All the Best
Dave



___

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: Objective-C Question

2013-03-12 Thread Dave


On 11 Mar 2013, at 21:14, Mike Abdullah wrote:


if from an instance  + Method I do:

[super someMethod], then surely it's an error because this isn't  
an instance?


It *is* an instance. An instance of the *metaclass*. This is where  
you're deep into the guts of Objective-C :)


H, I think I kind of knew this already but the details were  
fuzzy. Ok, i understand what you mean, so is the following correct:


1.  In a Instance - method, if you do [self someMethod] it will call - 
someMethod in the current class if it is defined there, or it will  
call -someMethod, in one of the parents of the current instance or  
error if -someMethod is not defined. If -someMethod is defined, and  
it calls [self -someMethod] then it will call as high up the chain as  
possible, e.g. will find -someMethod in one of the subclasses if it  
is defined or it will call it's own version?


e.g.

BaseClass   --- Subclass1   ---  Subclass2  --- Subclass3
-someMethhod---  Subclass2  --- Subclass3

___

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


Another Gnarly Objective-C Question!

2013-03-12 Thread Dave

Hi All,

Thanks for all help on the last question, here is one on a similar vein:

This is all Class methods, no instances are allocated or intended to  
be allocated at this stage.


in + Method in a subclass:

[[self class] someMethod];

This calls +someMethod in the current class, if it exists, if not, it  
calls in one of the super-classes if it exists. Is this correct?


If one of the super classes calls  [[self class] someMethod]; It will  
call as high up the chain as possible, resulting in an infinite loop  
in this case?


Is there a diagram somewhere showing how this works for the 4 cases of:

1.  [[self class] +someMethod];
2.  [[super class] +someMethod];
3.  [super +someMethod];
4. [[self superclass] +someMethod];

It does seem logical to expect that if:

[[self class] someMethod]; calls +someMethod the [[super class]  
+someMethod] would call +someMethod in the Superclass or is it just  
me??? lol


Thanks a lot
Dave

___

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: Objective-C Question

2013-03-12 Thread Graham Cox

On 12/03/2013, at 6:31 PM, Dave d...@looktowindward.com wrote:

 I don't think you understand the difference between class methods and 
 instance methods.

Are you certain you do?


 Here is an example of what I mean:


Why not state you goals instead of give us a lump of incoherent code?

As far as I can see you don't need a series of subclasses here (unless there is 
something else going on you haven't told us about). If you just want some 
factory classes to return certain prefilled dictionaries, then just do that, 
and forget about trying to mangle the meaning of inheritance and do something 
overcomplicated.

All you need is:


@interface DictionaryFactory1 : NSObject

+ (NSDictionary*) dictionary;

@end

// repeat the above with additional class names as desired, e.g. 
DictionaryFactory2, DictionaryFactory3



+ (NSDictionary*)  dictionary
{
// create the dictionary

// set some preloaded data

// return it
}


then your code just calls [DictionaryFactory1 dictionary], [DictionaryFactor2 
dictionary] etc.


what's so hard about that?

(n.b. it's NSDictionary, not MSDictionary, you may have the wrong OS in mind).



Even if Dictionary factory 2 inherits from Dictionary factory 1 for some reason 
that isn't clear from your post, it doesn't change this at all. You just 
override +dictionary and return what you want. There is no reason to call super 
at all.

If you want DF2 to add some further items to DF1's implementation, then call 
super and add the extra items to the dict:


@implementation DF2

+ (NSDictionary*) dictionary
{
NSMutableDictionary* md = [[super dictionary] mutableCopy];

// add extra items to md

return [md autorelease];
}

--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: Another Gnarly Objective-C Question!

2013-03-12 Thread Graham Cox

On 12/03/2013, at 7:39 PM, Dave d...@looktowindward.com wrote:

 Hi All,
 
 Thanks for all help on the last question, here is one on a similar vein:
 
 This is all Class methods, no instances are allocated or intended to be 
 allocated at this stage.
 
 in + Method in a subclass:
 
 [[self class] someMethod];


There's no reason to do this in a +method, just call [self someMethod];

However, it's equivalent because in a +method, [self class] simply returns self.

 This calls +someMethod in the current class, if it exists, if not, it calls 
 in one of the super-classes if it exists. Is this correct?

Yes, like any method of any class, whether an instance method or a class method.

 If one of the super classes calls  [[self class] someMethod]; It will call as 
 high up the chain as possible, resulting in an infinite loop in this case?

It will enter an infinite loop if it calls itself, like any function anywhere 
(that doesn't terminate under some condition). It's got nothing to do with how 
high in the chain, or whatever.

+ (void) method
{
[[self class] method];  // stack overflow due to infinite recursion 
because this is identical to [self method]
}

in a + method, [self class] === self. Once you've got that, you've got it.



You're overthinking this.

A class method is just an instance method of the class object. No magic at all. 
So all this confusion you've caused yourself about [super class] and so on is 
wholly unnecessary to correctly use class methods.

[super class] is a useless construction because +class returns self. That means 
that [super class] is no different from [self class] is no different from self. 
It's reasonable to call [super sameMethod] in a class method and it will do 
exactly what it does for an instance method (because it IS an instance method 
of the class object). It will call super's implementation. In general that's 
all you need - deeper introspection in class methods just to do ordinary kinds 
of work (like your dictionary case) are not required.

--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: Objective-C Question

2013-03-12 Thread Dave

Hi,

What I have works fine now, but to explain:

 Basically I have just a Class definition, e.g.

Class   theClass;

I can't instantiate the class (not that I'd consider that anyway),  
because I have no idea what side effects calling the init method of  
the class would be, it might, for instance, spawn off a millions  
worker threads or it might be a Singleton that can't be released and  
should never have been created in the first place! So, I can't call  
any Instance Methods of the Class, but, I need to know info about the  
class in order cache it and later combine it with other data, e.g. I  
take the data returned from the Class Method chain and use this along  
with other data to form a value. This system is already in place and  
I've seen it used a number of times, I think even in Apple Sample  
code. I think CoreData does something like this although I may be  
mistaken.


This is performed once at Initialization (App Launch) time.

The object chain may or may not be created at some later point, if it  
does need to be, then another method in the same class as above gets  
called, it then uses information provided to the Method and Data  
Stored from the initialization to build the object corresponding  
Class chain.


So, in a Class called something like DataManager, there are two methods:

-(void) configureClass:(Class) theClass
{
DataManagerInfo*myInfo;

myDict = [theClass newDict];
if (myDict == nil)
return;

myInfo = [[DataManagerInfo alloc] init];
[self computeInfoUsing:myInfo withSomeOtherData:otherData   
andConfigDict:myDict];


//  Store Info in Dictionary for later
[self.pClassDict setObject:myInfo forKey:NSStringFromClassName 
(theClass)];

}

-(id) createObjectForClass:(Class) theClass andOtherData:someOtherData
{
// takes info from pClassDict and data from OtherData and uses this  
to create the Object and returns it.

}


This all works fine and I think it's quite neat, it's certainly very  
fast, since a lot is pre-computed. The only problem I had was in some  
code in one of the newly added classes that called the super class  
like so:


[[super class] newDict];

Instead of [super newDict]

It was late and I was tired when I looked at the code and [[super  
class] newDict]; doesn't seem that unreasonable to expect to call the  
super class, which it did, but I hadn't realized that it in turn  
would call back up the chain. Then someone suggested:


[[self superclass] newDict];

Which also works, but so does [super newDict],

I not really sure which is the best in this case? I really don't want  
any class calling back up the chain in this case, so I think [[self  
superclass] newDict]; ?


I've got it working ok with [super newDict] but not sure if it would  
be best to change it to [[self superclass] newDict]


I don't want to hard code the class names into the code. Because I  
need it to work regardless of the order which I have no control over.  
The code that calls the DataManager class, has a network of class  
inheritance chains and hard coding (not that I can) would break that,  
for example:


BaseClass

BaseClass --- TypeAClass

TypeAClass --- TypeBClass

TypeBClass --- TypeCClass

TypeCClass --- TypeDClass

In this case 5 classes are configured and might created, BaseClass,  
A, B, C and D.


If someone changed it so that they inherited in a different order the  
code would break, by using super it avoids this problem.


On 12 Mar 2013, at 08:44, Graham Cox wrote:

All you need is:

@interface DictionaryFactory1 : NSObject

+ (NSDictionary*) dictionary;

@end

// repeat the above with additional class names as desired, e.g.  
DictionaryFactory2, DictionaryFactory3


+ (NSDictionary*)  dictionary
{
// create the dictionary

// set some preloaded data

// return it
}

then your code just calls [DictionaryFactory1 dictionary],  
[DictionaryFactor2 dictionary] etc.



what's so hard about that?


Nothing, but it doesn't do what I want it to!



(n.b. it's NSDictionary, not MSDictionary, you may have the wrong  
OS in mind).


Even if Dictionary factory 2 inherits from Dictionary factory 1 for  
some reason that isn't clear from your post,


From my original post:
Take the following example:

@interface BaseClass
+(NSMutableDictionary*) newDict;
@end

@implementation BaseClass
+(NSMutableDictionary*) newDict
{
return [[NSMutableDictionary alloc] init];
}
@class NewClass;
@interface NewClass : BaseClass
+(NSMutableDictionary*) newDict;
@end

#import BaseClass.h
@implementation NewClass

+(NSMutableDictionary*) newDict
{
NSMutableDictionary*myDict;

myDict = [[super class] newDict];//*** This was the problem,  
it now read [super newDict] as all is well.

[myDict setObject:@Some Data forKey:@someKey];

return myDict;
}

@end

How is the above not clear? Apart from the names I chose, I'd say:

@interface NewClass : BaseClass

Was a bit of a give away! lol

it doesn't change this at all. 

Re: Objective-C Question

2013-03-12 Thread Graham Cox

On 12/03/2013, at 11:45 PM, Dave d...@looktowindward.com wrote:

 Except it doesn't do what the above does!


Yes it does.


 
 @implementation DF2
 + (NSDictionary*) dictionary
 {
  NSMutableDictionary* md = [[super dictionary] mutableCopy];
  // add extra items to md
  return [md autorelease];
 }
 
 From reading the above, I cant see this is any better than what I have, it 
 fact it copies the dictionary every time, which is not what is wanted as well 
 as being slower.


Is it? Have you measured it? Does it matter?

In any case, it was only an example of how to achieve what you want, to show 
how to use class inheritance.

To be honest, the rest of your explanation doesn't make any sense to me, and I 
can't really be bothered to unravel it. Your whole I can't instantiate the 
class is incoherent at best (you *are* instantiating the class, like it or 
not). Maybe it makes sense to you, but not to me. I was trying to cut across 
all that irrelevant discussion by going back to basics and trying to get you to 
understand that:


a) [super class] is a meaningless construct, in that it doesn't do anything 
different from [self class],

b) in a class method, [self class] is just self,

c) a class method is just an ordinary instance method of the class object.

If you can understand those points, the rest should follow naturally. What you 
are trying to do is very straightforward, and requires no special trickery. The 
attempts you made show a clear lack of understanding about inheritance, which 
is what others were trying to tell you.

--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: Objective-C Question

2013-03-12 Thread Dave


On 12 Mar 2013, at 13:37, Graham Cox wrote:



On 12/03/2013, at 11:45 PM, Dave d...@looktowindward.com wrote:


Except it doesn't do what the above does!



Yes it does.


Oh No it doesn't!

crowd echo's Oh Yes it does!

It creates a copy of  read only dictionary and then modifies that. If  
the underlying dictionary changes, you will not see the changes  
reflected in the copy!




@implementation DF2
+ (NSDictionary*) dictionary
{
NSMutableDictionary* md = [[super dictionary] mutableCopy];
// add extra items to md
return [md autorelease];
}


From reading the above, I cant see this is any better than what I  
have, it fact it copies the dictionary every time, which is not  
what is wanted as well as being slower.


Is it? Have you measured it? Does it matter?


Well, like anyone else I'd like it run run as fast as possible and  
anyway, it is of course slower, it would have to send a retain  
message to each Object in the dictionary.


In any case, it was only an example of how to achieve what you  
want, to show how to use class inheritance.


To be honest, the rest of your explanation doesn't make any sense  
to me, and I can't really be bothered to unravel it. Your whole I  
can't instantiate the class is incoherent at best (you *are*  
instantiating the class, like it or not).


Ok, instantiate the object that is defined by the class!, to spell it  
out do a [[theClass alloc] init];,


 I'm not sure what you mean by


 (you *are* instantiating the class, like it or not)



The class may well be being instantiated, but AFAIK, there is no  
statement in the App that does this, apart from the @interface  
definition if that''s what you mean,


Maybe it makes sense to you, but not to me. I was trying to cut  
across all that irrelevant discussion by going back to basics and  
trying to get you to understand that:


It makes sense to a whole lot more people that me and something very  
similar is done in an Apple Sample somewhere too.


a) [super class] is a meaningless construct, in that it doesn't do  
anything different from [self class],


I know that now, but it's not instantly obvious to me anyway! It's a  
language gotcha, I will remember now hopefully.



b) in a class method, [self class] is just self,

c) a class method is just an ordinary instance method of the class  
object.


If you can understand those points, the rest should follow  
naturally. What you are trying to do is very straightforward, and  
requires no special trickery.


There why not just look at the original post and say, ah you need  
to change it to use [super ], instead of all the other stuff that  
didn't even do the same thing!


The attempts you made show a clear lack of understanding about  
inheritance, which is what others were trying to tell you.


Not it doesn't! It shows that I was confused after 16 hours coding by  
the difference between [[super class] ] and [super ]. From  
reading my original and subsequent posts, only a complete moron or  
someone trying to cause upset would say The attempts you made show a  
clear lack of understanding about inheritance. If you are serious  
and not just trying to wind me up and you are a complete moron, then  
please do explain how you can say that after looking at the original  
post.


Take the following example:

@interface BaseClass
+(NSMutableDictionary*) newDict;
@end

@implementation BaseClass
+(NSMutableDictionary*) newDict
{
return [[NSMutableDictionary alloc] init];
}

@class NewClass;

@interface NewClass : BaseClass
+(NSMutableDictionary*) newDict;
@end

#import BaseClass.h

@implementation NewClass

+(NSMutableDictionary*) newDict
{
NSMutableDictionary*myDict;

myDict = [[super class] newDict];			//***  
should be [super NewDict];

[myDict setObject:@Some Data forKey:@someKey];

return [[NSMutableDictionary alloc] init];
}
@end

So, what is it? Wind up merchant or Moron?

All the Best
Dave












___

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: Objective-C Question

2013-03-12 Thread John McCall
On Mar 12, 2013, at 12:31 AM, Dave d...@looktowindward.com wrote:
 On 11 Mar 2013, at 21:45, John McCall wrote:
 On Mar 11, 2013, at 2:02 PM, Dave d...@looktowindward.com wrote:
 On 11 Mar 2013, at 20:53, John McCall wrote:
 On Mar 11, 2013, at 1:33 PM, Dave d...@looktowindward.com wrote:
 On 11 Mar 2013, at 20:26, Mike Abdullah wrote:
 
 I had assumed (and I thought I'd done something like this before) that 
 the:
 
 myDict = [[super class] newDict];
 
 statement would call newDict in BaseClass Instead it calls the 
 version in NewClass and goes into an infinite loop!!
 
 Yes. [super class] calls super's implementation of the -class method. 
 You haven't overridden -class, so it does the same thing as [self class].
 
 People often make the same mistake in trying to do [super 
 respondsToSelector…
 
 I'm guessing what you're really after is [[self superclass] newDict]
 
 
 Thanks a Million, yes that's what I wanted!
 
 Are you sure?  This will indeed call the superclass's 'newDict', but the 
 'self' object will be the superclass, not your class.  That means it'll 
 (almost certainly) create an instance of your class's superclass.  The 
 easier way to do this is just [Foo newDict], where Foo is the name of your 
 superclass.
 
 If you want to invoke your superclass method, but with your class as 
 'self' — i.e. if you want to create an instance of your class — you should 
 use [super newDict].
 
 I don't know what you mean by:
 
 i.e. if you want to create an instance of your class
 
 I don't want to create an instance of my class, I want the class to return 
 a dictionary, that gets things added from the current class down through 
 the inheritance hierarchy,
 
 BaseClass alloc's a dict and puts in some data,
 Subclass1 calls base class and it's it own data.
 Subclass2 calls subclass1.
 
 How is this creating an instance of any object except the NSDict?
 
 Where do you think Subclass1's own data goes if the object allocated is 
 actually a BaseClass?
 
 I'm not allocating a base class or any other kind of class except a 
 dictionary. Did I say anything about instance data? No. The data I mean is 
 NOT instance data, how could it be? There is no object allocated in this 
 example (except the dictionary). I am using class + methods and they work on 
 the Class,

You seem to be assuming that this works the way it does in C# or Java.  It does 
not.

To use your example:

 BaseClass  (Class not an instance of a class).
 +(MSMutableDictionary*) newDict
 {
 MSMutableDictionary*  myDict;
 
 myDict = [[MSMutableDictionary alloc] init];
 [myDIct setObect:@SomeaValueX forKey:@someKeyX];
 
 return myDict;
 }
 
 Subclass1:
 
 +(MSMutableDictionary*) newDict
 {
 MSMutableDictionary*  myDict;
 
 myDict = [super newDict];
 [myDIct setObect:@SomeValueY forKey:@someKeyY];
 
 return myDict;
 }
 
 
 Subclass2:
 
 +(MSMutableDictionary*) newDict
 {
 MSMutableDictionary*  myDict;
 
 myDict = [super newDict];

There is exactly one difference between [[self superclass] newDict] and [super 
newDict] here:  the value of 'self'.  (This assumes the obvious behavior for 
+superclass, of course.)

[[self superclass] newDict] is exactly equivalent to [Subclass1 newDict].

[super newDict] calls the same method as [Subclass1 newDict], but using a 
'self' value that is still the Subclass1 class.

Now, if everything is implemented the way you've quoted it, the value of 'self' 
doesn't matter, because +[Subclass1 newDict] just passes it on to +[BaseClass 
newDict], and +[BaseClass newDict] ignores 'self'.

However, that wouldn't be an idiomatic implementation.  The usual expectation 
is that allocating methods, like +new methods, construct an object *of type 
self* (at least).  For example, NSObject has a +new method that looks like this:
  + (id) new {
return [[self alloc] init];
  }
This way, subclasses don't have to reimplement +new in order to make it work:  
[NSWindow new] eventually does an [[NSWindow alloc] init], just like you'd 
expect.

This is why I was talking about instance methods and fields:  because, 
generally, people introduce new classes because they expect to create instances 
of them, and [[self superclass] newDict] bypasses that in a way that might not 
be obvious.

What you're doing is introducing a ton of classes in order to create a 
delegation hierarchy of factory methods.  It's probably the most wasteful way 
of achieving this goal that I can see — why not just use functions or 
something? — but you're certainly welcome to it.  Just understand that most 
people, reading code like +[FooDictionary newDict], would reasonably assume 
that this actually creates an instance of FooDictionary.

John.
___

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:

Re: Objective-C Question

2013-03-12 Thread Dave


On 12 Mar 2013, at 16:44, John McCall wrote:


There is exactly one difference between [[self superclass] newDict]  
and [super newDict] here:  the value of 'self'.  (This assumes the  
obvious behavior for +superclass, of course.)


[[self superclass] newDict] is exactly equivalent to [Subclass1  
newDict].


[super newDict] calls the same method as [Subclass1 newDict], but  
using a 'self' value that is still the Subclass1 class.


Now, if everything is implemented the way you've quoted it, the  
value of 'self' doesn't matter, because +[Subclass1 newDict] just  
passes it on to +[BaseClass newDict], and +[BaseClass newDict]  
ignores 'self'.


However, that wouldn't be an idiomatic implementation.  The usual  
expectation is that allocating methods, like +new methods,  
construct an object *of type self* (at least).  For example,  
NSObject has a +new method that looks like this:

  + (id) new {
return [[self alloc] init];
  }
This way, subclasses don't have to reimplement +new in order to  
make it work:  [NSWindow new] eventually does an [[NSWindow alloc]  
init], just like you'd expect.


This is why I was talking about instance methods and fields:   
because, generally, people introduce new classes because they  
expect to create instances of them, and [[self superclass] newDict]  
bypasses that in a way that might not be obvious.


What you're doing is introducing a ton of classes in order to  
create a delegation hierarchy of factory methods.   It's probably  
the most wasteful way of achieving this goal that I can see


Firstly, I didn't create it, it was already there and I had/have to  
make it work faster since it is/was too slow. There was no time to  
rewrite it, and, even if there was, I really can't see a better way,  
there may be different ways, but I can't see that they would be  
substantially better.


This class I am working can receive data from the following sources:

An Object of the same Class.
PList Raw Data String.
Dictionary.
Network
PList file.
Core Data.
SQLite Database.
Other Data File.

This source is turned into Objective-C Objects using data created in  
the Class Chain, then Cached and later if necessary used to create  
the Object. The basic mechanism was already there, all I've done is  
to make it quicker by caching info so that it doesn't need to be  
regenerated each time an object is created. The .m file for each of  
the classes in the chain have specialist *instance* methods that are  
used during the object life cycle. The things that threw me I think  
was that I did two things at once, I changed the caching code and  
also added two more classes to the chain. The problem was in the  
newly added Classes, not in the caching code and was just the  
difference between [super xxx] and [[super class] xxx], a simple bug  
to fix once I realized what the problem was.


Another way to do it would be to define each Class to contain all the  
fields contained in the chain, but this would mean that there would  
loads more classes and lots of duplication of code. At present there  
are around 50 such classes, if I were to Flatten them, there would  
probably be 200+.


I thought the initial design was quite good, it was just a slow,  
fairly dumb implementation, this makes it a lot faster which is a  
good and fixes the immediate problem. If I thought this was really  
probably the most wasteful way of achieving this goal that I can  
see, I could and would ask for time to fix it. But I can't see a  
substantially better way of doing it or why you think this way of  
doing it is wasteful? Wasteful in terms of what? Code Size? Execution  
Time (bearing in mind it is done one, the class chaining I mean and  
instances allocated many times). I can't think of anything that is  
excessively wasteful and it's very flexible.


 If you can of  better, less wasteful way then please do let me know  
and I will look at your suggestions.


— why not just use functions or something? — but you're certainly  
welcome to it.


I'm not sure how functions would help me achieve anything given the  
above?


Just understand that most people, reading code like +[FooDictionary  
newDict], would reasonably assume that this actually creates an  
instance of FooDictionary.


But that is NOT how the code looks, which can be seen from my  
original post, it looks like this:


Class   myClass = [someClass class];
NSDictionarymyDict;

myDict = [myClass newDict];

Why would you think newDict returned a myClass object?

If you saw:

Class   myClass =  [NSDictionary class];
SomeObject* myObj;

myObj = [myClass newObj];

Would you think that newObj was returning an NSDictionary?

If so, why?

All the Best
Dave


___

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 

Re: Another Gnarly Objective-C Question!

2013-03-12 Thread Jens Alfke

On Mar 12, 2013, at 2:08 AM, Graham Cox graham@bigpond.com wrote:

 A class method is just an instance method of the class object. No magic at 
 all. So all this confusion you've caused yourself about [super class] and so 
 on is wholly unnecessary to correctly use class methods.

Agreed. This can be confusing to people coming from less-dynamic languages like 
C++ or Java.

* In Objective-C a class is an object. You can think of it as a singleton — so 
when “Foo” appears as the receiver in an expression (like “[Foo alloc]”) it 
means the singleton object that represents the class Foo.

* Class (“+”-prefixed) methods are instance methods of the class object.

* “super” works as it does for instances, so in the implementation of 
+[Subclass foo], calling “[super foo]” will invoke the superclass’s 
implementation of +foo, if it has one.*

* Calling +class on a class object is a no-op, because it’s already a class. 
The only reason this is useful is it allows you to say “[Foo class]” to get the 
class object of Foo, because for some syntactic reason just saying “Foo” 
doesn’t work.

—Jens

* The details of this are really weird and involve the existence of 
metaclasses, which have an even weirder relationship to each other, but 
fortunately you almost never have to think about this in Objective-C. It’s much 
more explicit in Smalltalk-80, where these concepts originate. Look up 
“metaclass” on Wikipedia if you want the gory details.
___

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: Objective-C Question

2013-03-12 Thread Jens Alfke

On Mar 12, 2013, at 9:44 AM, John McCall rjmcc...@apple.com wrote:

 However, that wouldn't be an idiomatic implementation.  The usual expectation 
 is that allocating methods, like +new methods, construct an object *of type 
 self* (at least).

Are you just quibbling about the prefix “new-“? The specific method +new is 
expected to create a new instance of the receiving class, yes. There may be a 
convention (I can’t remember?) that class methods prefixed “new-” are intended 
to do the same.

However, it’s hardly unusual to have a class method that instantiates and 
returns some other kind of object. Dave’s use case of a dictionary that 
describes metadata about the class seems reasonable.

 This is why I was talking about instance methods and fields:  because, 
 generally, people introduce new classes because they expect to create 
 instances of them, and [[self superclass] newDict] bypasses that in a way 
 that might not be obvious.

I don’t see the problem here. Presumably the class is going to be instantiated 
at some point, but the code Dave is working with is operating on metadata about 
the class, so only class methods are involved in it.

—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: Objective-C Question

2013-03-12 Thread Dave


On 12 Mar 2013, at 18:50, Jens Alfke wrote:



On Mar 12, 2013, at 9:44 AM, John McCall rjmcc...@apple.com wrote:

However, that wouldn't be an idiomatic implementation.  The usual  
expectation is that allocating methods, like +new methods,  
construct an object *of type self* (at least).


Are you just quibbling about the prefix “new-“? The specific method  
+new is expected to create a new instance of the receiving class,  
yes. There may be a convention (I can’t remember?) that class  
methods prefixed “new-” are intended to do the same.


I'm not sure if its a convention, but it does make sense, for  
instance, I've been code like this before.


-(NSDictionary) newDictForSomethingWithInfo:(Info*) theInfo
{
// returns an dictionary allocated and initialized
}

somewhere else in the same class:

myDict = [self newDictForSomethingWithInfo:myInfo];

Which keeps the compiler/analyzer happy in non-ARC and works ok with  
ARC enabled. If this isn't a convention then it should be IMO unless  
there is another prefix used? allocDict would work, but this is as  
bad or as good as new in this respect.




However, it’s hardly unusual to have a class method that  
instantiates and returns some other kind of object. Dave’s use case  
of a dictionary that describes metadata about the class seems  
reasonable.


This is why I was talking about instance methods and fields:   
because, generally, people introduce new classes because they  
expect to create instances of them, and [[self superclass]  
newDict] bypasses that in a way that might not be obvious.


I don’t see the problem here. Presumably the class is going to be  
instantiated at some point,


This is the language I used, and is another source of confusion on  
this. Apparently the language technically should be:


Presumably the class is going to be to be used to instantiate an  
Object at some point which keeps everyone happy? lol


but the code Dave is working with is operating on metadata about  
the class, so only class methods are involved in it.


Exactly!

All the Best
Dave
___

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: Objective-C Question

2013-03-12 Thread Jean-Daniel Dupas

Le 12 mars 2013 à 20:15, Dave d...@looktowindward.com a écrit :

 
 On 12 Mar 2013, at 18:50, Jens Alfke wrote:
 
 
 On Mar 12, 2013, at 9:44 AM, John McCall rjmcc...@apple.com wrote:
 
 However, that wouldn't be an idiomatic implementation.  The usual 
 expectation is that allocating methods, like +new methods, construct an 
 object *of type self* (at least).
 
 Are you just quibbling about the prefix “new-“? The specific method +new is 
 expected to create a new instance of the receiving class, yes. There may be 
 a convention (I can’t remember?) that class methods prefixed “new-” are 
 intended to do the same.
 
 I'm not sure if its a convention, but it does make sense, for instance, I've 
 been code like this before.
 
 -(NSDictionary) newDictForSomethingWithInfo:(Info*) theInfo
 {
 // returns an dictionary allocated and initialized
 }
 
 somewhere else in the same class:
 
 myDict = [self newDictForSomethingWithInfo:myInfo];
 
 Which keeps the compiler/analyzer happy in non-ARC and works ok with ARC 
 enabled. If this isn't a convention then it should be IMO unless there is 
 another prefix used? allocDict would work, but this is as bad or as good as 
 new in this respect.
 

According to the clang manual: 
http://clang.llvm.org/docs/LanguageExtensions.html#related-result-types

The related result type can also be inferred for some methods. To determine 
whether a method has an inferred related result type, the first word in the 
camel-case selector (e.g., “init” in “initWithObjects”) is considered, and the 
method will have a related result type if its return type is compatible with 
the type of its class and if:

• the first word is “alloc” or “new”, and the method is a class method, 
or
• the first word is “autorelease”, “init”, “retain”, or “self”, and the 
method is an instance method.

So new prefixed class method should return an instance of the calling class, 
but instance methods are just required to returned a retained object of any 
kind.


-- Jean-Daniel





___

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: Objective-C Question

2013-03-12 Thread Dave


On 12 Mar 2013, at 19:38, Jean-Daniel Dupas wrote:



Le 12 mars 2013 à 20:15, Dave d...@looktowindward.com a écrit :



On 12 Mar 2013, at 18:50, Jens Alfke wrote:



On Mar 12, 2013, at 9:44 AM, John McCall rjmcc...@apple.com wrote:

However, that wouldn't be an idiomatic implementation.  The  
usual expectation is that allocating methods, like +new methods,  
construct an object *of type self* (at least).


Are you just quibbling about the prefix “new-“? The specific  
method +new is expected to create a new instance of the receiving  
class, yes. There may be a convention (I can’t remember?) that  
class methods prefixed “new-” are intended to do the same.


I'm not sure if its a convention, but it does make sense, for  
instance, I've been code like this before.


-(NSDictionary) newDictForSomethingWithInfo:(Info*) theInfo
{
// returns an dictionary allocated and initialized
}

somewhere else in the same class:

myDict = [self newDictForSomethingWithInfo:myInfo];

Which keeps the compiler/analyzer happy in non-ARC and works ok  
with ARC enabled. If this isn't a convention then it should be IMO  
unless there is another prefix used? allocDict would work, but  
this is as bad or as good as new in this respect.




According to the clang manual: http://clang.llvm.org/docs/ 
LanguageExtensions.html#related-result-types


The related result type can also be inferred for some methods. To  
determine whether a method has an inferred related result type, the  
first word in the camel-case selector (e.g., “init” in  
“initWithObjects”) is considered, and the method will have a  
related result type if its return type is compatible with the type  
of its class and if if its return type is compatible with the type  
of its class and if:


That's true (incompatible result type)  in this case and in most  
cases I've seen, so ok to use newDict in this case.


	• the first word is “alloc” or “new”, and the method is a class  
method, or
	• the first word is “autorelease”, “init”, “retain”, or “self”,  
and the method is an instance method.


So new prefixed class method should return an instance of the  
calling class, but instance methods are just required to returned a  
retained object of any kind.


Well, that's one rule that sucks and I've seen it disobeyed many  
times. If that is the case, then how do you signal to the compiler/ 
analyzer that you are returning a retained object? Unless there is  
another prefix to use, they I am going to continue ignore it too!


All the Best
Dave


PS.
This lets eveyone off the hook:


if its return type is compatible with the type of its class and if:


Just seen this:

That's true (incompatible result type)  in this case and in most  
cases I've seen, so ok to use newDict in this case.



___

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: Objective-C Question

2013-03-12 Thread Graham Cox

On 13/03/2013, at 2:41 AM, Dave d...@looktowindward.com wrote:

 So, what is it? Wind up merchant or Moron?
 


I don't think there's any need for this. If I caused offence, it was unintended 
(I sometimes have trouble anticipating how others might receive statements I 
make, that's just something I have to live with).

The further discussion doesn't really convince me that you've really understood 
it, but if you have, great. Personally I have no stake in whether you succeed 
or not, so if you choose to ignore advice or insult the adviser, it makes no 
difference to me.

--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: Objective-C Question

2013-03-12 Thread Graham Cox

On 13/03/2013, at 6:53 AM, Dave d...@looktowindward.com wrote:

 If that is the case, then how do you signal to the compiler/analyzer that you 
 are returning a retained object?

In general you shouldn't return a retained object (unless it's temporarily 
retained and will be autoreleased of course). If you are routinely doing this 
then your design is flawed. The reason it's hard to signal to the compiler that 
you're returning a retained object is that you shouldn't be doing it. When you 
have to do it, use the word 'new' in the method.

 Unless there is another prefix to use, they I am going to continue ignore it 
 too!

Again, no offence intended but when a person doesn't follow a rule because they 
think it doesn't apply to them, it's just a sign of inexperience and/or lack of 
understanding. Sorry, but there it is.

--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: Another Gnarly Objective-C Question!

2013-03-12 Thread Wim Lewis

On 12 Mar 2013, at 2:08 AM, Graham Cox wrote:
 in a + method, [self class] === self. Once you've got that, you've got it.
 
 
 
 You're overthinking this.
 
 A class method is just an instance method of the class object. No magic at 
 all. So all this confusion you've caused yourself about [super class] and so 
 on is wholly unnecessary to correctly use class methods.

To be very slightly pedantic, the only magic here is 'super' --- sending a 
message to super (which you can only do from a method implementation) is 
special syntax that searches for the method starting with the implementation's 
class's superclass, rather than at the receiver's actual class. Everything else 
is non-magic. (In general, that's been one of the strengths of ObjC: very 
little magic.)

But since there's only one relevant implementation of +class (on NSObject), and 
it returns self, and self is the same object regardless of how the method 
implementation was found, [self class] and [super class] are equivalent.



___

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


Objective-C Question

2013-03-11 Thread Dave

Hi,

Take the following example:

@interface BaseClass

+(NSMutableDictionary*) newDict;

@end

@implementation BaseClass

+(NSMutableDictionary*) newDict
{


return [[NSMutableDictionary alloc] init];
}


@class NewClass;

@interface NewClass : BaseClass

+(NSMutableDictionary*) newDict;

@end

#import BaseClass.h

@implementation NewClass

+(NSMutableDictionary*) newDict
{
NSMutableDictionary*myDict;

myDict = [[super class] newDict];
[myDict setObject:@Some Data forKey:@someKey];

return [[NSMutableDictionary alloc] init];
}

@end




I had assumed (and I thought I'd done something like this before)  
that the:


myDict = [[super class] newDict];

statement would call newDict in BaseClass Instead it calls the  
version in NewClass and goes into an infinite loop!!


Any help greatly appreciated.

Cheers
Dave




___

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: Objective-C Question

2013-03-11 Thread Mike Abdullah

On 11 Mar 2013, at 20:21, Dave d...@looktowindward.com wrote:

 Hi,
 
 Take the following example:
 
 @interface BaseClass
 
 +(NSMutableDictionary*) newDict;
 
 @end
 
 @implementation BaseClass
 
 +(NSMutableDictionary*) newDict
 {
 
 
 return [[NSMutableDictionary alloc] init];
 }
 
 
 @class NewClass;
 
 @interface NewClass : BaseClass
 
 +(NSMutableDictionary*) newDict;
 
 @end
 
 #import BaseClass.h
 
 @implementation NewClass
 
 +(NSMutableDictionary*) newDict
 {
 NSMutableDictionary*  myDict;
 
 myDict = [[super class] newDict];
 [myDict setObject:@Some Data forKey:@someKey];
 
 return [[NSMutableDictionary alloc] init];
 }
 
 @end
 
 
 
 
 I had assumed (and I thought I'd done something like this before) that the:
 
 myDict = [[super class] newDict];
 
 statement would call newDict in BaseClass Instead it calls the version in 
 NewClass and goes into an infinite loop!!

Yes. [super class] calls super's implementation of the -class method. You 
haven't overridden -class, so it does the same thing as [self class].

People often make the same mistake in trying to do [super respondsToSelector…

I'm guessing what you're really after is [[self superclass] newDict]


___

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

Objective-C Question

2013-03-11 Thread Dave

Typeo:

return [[NSMutableDictionary alloc] init];

should be:

return myDict;

---
Hi,

Take the following example:

@interface BaseClass

+(NSMutableDictionary*) newDict;

@end

@implementation BaseClass

+(NSMutableDictionary*) newDict
{


return [[NSMutableDictionary alloc] init];
}


@class NewClass;

@interface NewClass : BaseClass

+(NSMutableDictionary*) newDict;

@end

#import BaseClass.h

@implementation NewClass

+(NSMutableDictionary*) newDict
{
NSMutableDictionary*myDict;

myDict = [[super class] newDict];
[myDict setObject:@Some Data forKey:@someKey];

return myDict;  //
}

@end

---

I had assumed (and I thought I'd done something like this before)  
that the:


myDict = [[super class] newDict];

statement would call newDict in BaseClass Instead it calls the  
version in NewClass and goes into an infinite loop!!


Any help greatly appreciated.

Cheers
Dave




___

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/dave% 
40looktowindward.com


This email sent to d...@looktowindward.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


  1   2   >