我需要检查一个对象是否是NSNotification。仅仅知道它是否是子类是不够的,因为我想区分它是NSNotification还是NSNotification的子类。
因此,为了详细说明,我需要区分以下几点:
问题是,NSNotifications实际上是NSConcreteNotifications,而NSConcreteNotification是一个私有类,所以我不能使用它进行测试。
[object isMemberOfClass: [NSNotification class]] // returns NO in both cases
[object isKindOfClass: [NSNotification class]] // returns YES in both cases发布于 2011-09-28 13:45:40
没有理由像您所描述的那样对NSNotification进行子类化。首先,NSNotification已经携带了一个userInfo字典。你可以把你想要的任何数据都放进去。如果你愿意的话,你可以使用分类方法来读和写字典(我一直这么做)。例如,我想要做的一件非常常见的事情是传递某个对象,RNMessage说。因此,我创建了一个类似于这样的类别:
@interface NSNotificationCenter (RNMessage)
- (void)postNotificationName:(NSString *)aName object:(id)anObject message:(RNMessage *)message;
@end
@interface NSNotification (RNMessage)
- (RNMessage *)message;
@endstatic NSString * const RNMessageKey = @"message";
@implementation NSNotificationCenter (RNMessage)
- (void)postNotificationName:(NSString *)aName object:(id)anObject message:(RNMessage *)message {
[self postNotificationName:aName object:anObject userInfo:[NSDictionary dictionaryWithObject:message forKey:RNMessageKey];
}
@end
@implementation NSNotification (RNMessage)
- (RNMessage *)message {
return [[self userInfo] objectForKey:RNMessageKey];
}正如@hypercrypt所指出的,您也可以使用关联的引用将数据附加到任何任意对象,而不需要创建ivar,但是对于NSNotification,使用userInfo字典要简单得多。使用NSLog打印通知要容易得多。更容易序列化它们。更容易复制。等。相关的引用是很好的,但是它们确实增加了很多小的角落案例,如果你可以避免的话,你应该避免它。
发布于 2011-09-28 12:54:51
要测试id对象,需要使用NSNotification:
[object isMemberOfClass:[NSNotification class]];`来测试它是否是NSConcreteNotifications使用。
[object isMemberOfClass:NSClassFromString(@"NSConcreteNotifications")];根据需要将字符串更改为不同类的名称.
然后,您可以将“NSNotification的一个子类(但不是NSConcreteNotification)”的两个检查组合起来。
以下任一项:
if ([object isMemberOfClass:NSClassFromString(@"NSConcreteNotifications")])
{
// It's a NSConcreteNotifications...
}
else if ([object isKindOfClass:[NSNotification class]])
{
// It's an NSNotification (or subclass) but not an NSConcreteNotifications
}或
if ([object isKindOfClass:[NSNotification class]] && ![object isMemberOfClass:NSClassFromString(@"NSConcreteNotifications")])
{ /* ... */ }如果要向NSNotification添加属性,则应该查看联想引用。
其基本思想是:
static const char objectKey;
- (id)object
{
return objc_getAssociatedObject(self, &objectKey);
}
- (void)setObject:(id)object
{
objc_setAssociatedObject(self, &objectKey, object, OBJC_ASSOCIATION_RETAIN);
}发布于 2011-09-28 13:08:35
听起来真是个坏主意。当您第一次收到通知时,您已经知道它是什么类型了,因为它作为显式参数传递给通知回调方法。考虑将通知存储为另一个对象的强类型属性,或者如果要将通知添加到集合中,则将其插入字典中的适当键下,或者将其传递给其他不保留类型信息的方法,以便以后更容易识别。
创建对私有API的依赖(包括私有类名)将使您的代码更加脆弱,并且更有可能在以后的版本中崩溃。显然,这些课程是保密的原因之一,是为了让苹果的工程师们更容易在他们认为合适的情况下改变这些课程。例如,NSArray和NSMutableArray使用的具体子类在最近发布的SDK中发生了变化。
https://stackoverflow.com/questions/7583414
复制相似问题