Я думаю, что всем не хватает настоящей проблемы.Дело не в методах доступа, а в том, что NSOrderedSet
не является подклассом NSSet
.Поэтому, когда -interSectsSet:
вызывается с упорядоченным набором в качестве аргумента, происходит сбой.
NSOrderedSet* setA = [NSOrderedSet orderedSetWithObjects:@"A",@"B",@"C",nil];
NSSet* setB = [NSSet setWithObjects:@"C",@"D", nil];
[setB intersectsSet:setA];
завершается ошибкой с *** -[NSSet intersectsSet:]: set argument is not an NSSet
Похоже, исправление состоит в том, чтобы изменить реализацию операторов набора так,они обрабатывают типы прозрачно.Нет причин, по которым -intersectsSet:
должен работать с упорядоченным или неупорядоченным множеством.
Исключение происходит в уведомлении об изменении.Предположительно в коде, который обрабатывает обратные отношения.Так как это происходит только тогда, когда я устанавливаю обратную связь.
Следующее помогло мне
@implementation MF_NSOrderedSetFixes
+ (void) fixSetMethods
{
NSArray* classes = [NSArray arrayWithObjects:@"NSSet", @"NSMutableSet", @"NSOrderedSet", @"NSMutableOrderedSet",nil];
[classes enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSString* name = obj;
Class aClass = objc_lookUpClass([name UTF8String]);
[MF_NSOrderedSetFixes fixMethodWithSetArgument:@selector(intersectsSet:) forClass:aClass];
[MF_NSOrderedSetFixes fixMethodWithSetArgument:@selector(isSubsetOfSet:) forClass:aClass];
}];
}
typedef BOOL (*BoolNSetIMP)(id _s,SEL sel, NSSet*);
/*
Works for all methods of type - (BOOL) method:(NSSet*) aSet
*/
+ (void) fixMethodWithSetArgument:(SEL) aSel forClass:(Class) aClass
{
/* Check that class actually implements method first */
/* can't use get_classInstanceMethod() since it checks superclass */
unsigned int count,i;
Method method = NULL;
Method* methods = class_copyMethodList(aClass, &count);
if(methods) {
for(i=0;i<count;i++) {
if(method_getName(methods[i])==aSel) {
method = methods[i];
}
}
free(methods);
}
if(!method) {
return;
}
// Get old implementation
BoolNSetIMP originalImp = (BoolNSetIMP) method_getImplementation(method);
IMP newImp = imp_implementationWithBlock(^BOOL(NSSet *_s, NSSet *otherSet) {
if([otherSet isKindOfClass:[NSOrderedSet class]]) {
otherSet = [(NSOrderedSet*)otherSet set];
}
// Call original implementation
return originalImp(_s,aSel,otherSet);
});
method_setImplementation(method, newImp);
}
@end