Re: Crashing Problem calling postNotificationName
Re: Crashing Problem calling postNotificationName
- Subject: Re: Crashing Problem calling postNotificationName
- From: Etienne Samson <email@hidden>
- Date: Thu, 12 Sep 2013 21:24:33 +0200
Le 12 sept. 2013 à 20:11, Dave <email@hidden> a écrit :
> On 12 Sep 2013, at 18:45, Kyle Sluder <email@hidden> wrote:
>
>> On Thu, Sep 12, 2013, at 10:18 AM, Dave wrote:
>>>
>>> On 12 Sep 2013, at 17:58, Kyle Sluder <email@hidden> wrote:
>>>
>>>> Whenever I see a suggestion like “subclass NSNotificationCenter”, I recoil in horror.
Have a look at Quicksilver's source code sometimes ;-). But yes, you're right, and maybe I haven't been clear enough but you have to have a decent usage "hygiene" for that to work.
>>>> First, NSNotificationCenter is a singleton. If you subclass it, you now must have two notification centers.
>>>
>>> It has the facility to have different Centers (default etc.), so it's not
>>> a true singleton, although I see what you mean. It doesn't have to be a
>>> subclass, just a class, but I think that either subclassing
>>> NSNotificationCenter or have a Category on it is better than having an
>>> anonymous object that calls [NSNotificationCenter defaultCenter], since
>>> at least it keeps all the notification code in one place.
You can't have a Category without reimplementing the whole methods you'll replace. Good luck providing adequate replacements for framework classes you only have the machine code for ;-).
>> I'm not really sure what you're talking about with "anonymous object
>> that calls +defaultCenter." Every NSNotificationCenter call site gets a
>> reference to the notification center by calling the class method.
I think it means "any object". This describes the tight coupling between "sender/notification center" and "notification center/receiver" and the loose coupling between "sender/receiver" which is a thing to keep in mind, there is a strong coupling in the sender/NC/observer pattern : you're asking for another (hopefully common) object to receive and deliver messages on your behalf.
>>>> Which one is the right one to subscribe to? Do you only move notifications over to it that need to be cached? Or all related notifications as well?
>>>
>>> That problem exists anyway, you have to know it's the default center for
>>> instance. This is just using related ones by virtue of the fact that the
>>> rest of the code doesn't use the subclass, only those that need to.
>>
>> If you only ever use the default center, you never have to worry about
>> which notification center to listen to.
The default center doesn't provide the automatic caching mechanism the OP wants. You, as the programmer of that horror, ought to know which notifications need to be cached or not. Standard framework notifications ? Use `[NSNC defaultCenter]`. Your own framework notifications ? Use the subclass. Need to cache standard notifications ? Observe the `defaultCenter` from the subclass.
>> There is a very large gulf in software design between "one" and "many."
>> Every time you want to cross that gulf you have to make decisions. More
>> decisions lead to more bugs.
>>
>>>
>>>> This decision needs to be made on both ends of the notification.
That's true, but again you as the programmer can decide which notifications needs caching and which do not.
>>>> Congratulations, you have taken an object whose purpose is to promote loose coupling, and successfully turned it into a tool that tightly couples the sender and the listener.
I see your point, but IMHO it all fall apart if you can have more than one sender (which is as yet unspecified). And the sender/reciever (as explained above) are *already* tightly coupled with whatever notification center you've chosen because of the difference in behavior the OP wants. You can't have the receiver know where the notification came from and it ask for it's current value without killing that loose couple.
>>>> The correct approach does not put the cache in the notification center, but rather in the sender or the userInfo dictionary.
Le 12 sept. 2013 à 20:11, Dave <email@hidden> a écrit :
>
> On 12 Sep 2013, at 18:45, Kyle Sluder <email@hidden> wrote:
>
>> On Thu, Sep 12, 2013, at 10:18 AM, Dave wrote:
>>>
>>> On 12 Sep 2013, at 17:58, Kyle Sluder <email@hidden> wrote:
>>>
>>>> Whenever I see a suggestion like “subclass NSNotificationCenter”, I recoil in horror.
Have a look at Quicksilver's source code sometimes ;-). But yes, you're right, and maybe I haven't been clear enough but you have to have a decent usage "hygiene" for that to work.
>>>> First, NSNotificationCenter is a singleton. If you subclass it, you now must have two notification centers.
>>>
>>> It has the facility to have different Centers (default etc.), so it's not
>>> a true singleton, although I see what you mean. It doesn't have to be a
>>> subclass, just a class, but I think that either subclassing
>>> NSNotificationCenter or have a Category on it is better than having an
>>> anonymous object that calls [NSNotificationCenter defaultCenter], since
>>> at least it keeps all the notification code in one place.
You can't have a Category without reimplementing the whole methods you'll replace. Good luck providing adequate replacements for framework classes you only have the machine code for ;-).
>> I'm not really sure what you're talking about with "anonymous object
>> that calls +defaultCenter." Every NSNotificationCenter call site gets a
>> reference to the notification center by calling the class method.
I think it means "any object". This describes the tight coupling between "sender/notification center" and "notification center/receiver" and the loose coupling between "sender/receiver" which is a thing to keep in mind, there is a strong coupling in the sender/NC/observer pattern : you're asking for another (hopefully common) object to receive and deliver messages on your behalf.
>>>> Which one is the right one to subscribe to? Do you only move notifications over to it that need to be cached? Or all related notifications as well?
>>>
>>> That problem exists anyway, you have to know it's the default center for
>>> instance. This is just using related ones by virtue of the fact that the
>>> rest of the code doesn't use the subclass, only those that need to.
>>
>> If you only ever use the default center, you never have to worry about
>> which notification center to listen to.
The default center doesn't provide the automatic caching mechanism the OP wants. You, as the programmer of that horror, ought to know which notifications need to be cached or not. Standard framework notifications ? Use `[NSNC defaultCenter]`. Your own framework notifications ? Use the subclass. Need to cache standard notifications ? Observe the `defaultCenter` from the subclass.
>> There is a very large gulf in software design between "one" and "many."
>> Every time you want to cross that gulf you have to make decisions. More
>> decisions lead to more bugs.
>>
>>>
>>>> This decision needs to be made on both ends of the notification.
That's true, but again you as the programmer can decide which notifications needs caching and which do not.
>>>> Congratulations, you have taken an object whose purpose is to promote loose coupling, and successfully turned it into a tool that tightly couples the sender and the listener.
I see your point, but IMHO it all fall apart if you can have more than one sender (which is as yet unspecified). And the sender/reciever (as explained above) are *already* tightly coupled with whatever notification center you've chosen because of the difference in behavior the OP wants. You can't have the receiver know where the notification came from and it ask for it's current value without killing that loose couple.
>>>> The correct approach does not put the cache in the notification center, but rather in the sender or the userInfo dictionary.
That won't work. The regenerated object can't have any trace left of the old notification (since it just got initialized), so no "I was sent by *foo*" (which BTW breaks the loose coupling).
The only other approach that works (unless you consider dropping notification centers completely, or the specific use case can be moved to KVO with its Initial option) is approach I pointed out (and I agree that the subclass is the easy/hackish one) :
// mail code
@implementation NSNoticationCache
- (void)addObserver:(id)notificationObserver selector:(SEL)notificationSelector name:(NSString *)notificationName object:(id)notificationSender {
// register self with the same notification but for all objects, with -cacheNotification as the selector
// WARN: this will be wrong if your reciever uses notificationSender, because you'll have to keep track of the userInfo/notificationSender pair when you receiver regenerates
// register notificationObserver using the same parameter
// if you have cached data for the notification, call the notificationObserver *directly* with it
// WARN: you can't post that notification to NSNotificationCenter since NSNotificationCache is now also registered, else you'll get notification recursion
}
- (void)cacheNotification:(NSNotification *)notification {
// as it says on the tin
}
@end
You've just swapped tight coupling with NSNotificationCenter with tight coupling with that one but you had no other choice to get the behavior you wanted.
[major snipping]
>> And when you're scratching your head wondering why you're not getting
>> notifications delivered to your objects, because they're being sent to a
>> different notification center than the one you're listening to…
>
> But I am getting notifications delivered to me! And they get sent to the same Notification Center, there is only one OS level Center used - the default.
That's not true : you won't get notifications sent by the Cocoa framework, because it will use `[NSNotificationCenter defaultCenter]` and you have (obviously) no way to change the sender.
I feel like I'm playing the devil's advocate here Dave, but you'd have a more fool-proof solution with the cache solution I described. You won't have the problem pointed out by Kyle that you end up with 2 notification centers (and can't cache Cocoa's own notifications unless you have the subclass register with the default center). Maybe you'll have 26-or-more registerObserver: calls to change (to add the "then check cached notification" call), but in the end run, you've just removed a dependency on a subclass whose superclass you know nothing about. Again (and I speak from experience), better be safe than sorry if NSNotificationCenter semantics change and your app stop working.
Regards,
Etienne Samson
--
email@hidden
_______________________________________________
Cocoa-dev mailing list (email@hidden)
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:
This email sent to email@hidden