Я пытаюсь научить себя объективному c. Я привык (~ 10 лет назад) быть довольно хорош с C++, поэтому я решил, что это не должно быть слишком сложно, но после стольких лет работы с python и различными языками математического программирования я довольно ржавый по указателям и тому подобное, которые, как я полагаю, вероятно, что вызывает это.Почему я получаю ошибки «непризнанного селектора»?
В любом случае, я продолжаю получать непризнанные ошибки селектора для методов, которые определенно существуют в документации и выводах отладки xcode (что я не очень хорошо знаю, поэтому, возможно, это неправильно) показывает, что эти объекты инициализированы. Я попытался сделать следующий пример как можно меньше. Вот класс я написал:
// Graph.h
#import <Foundation/Foundation.h>
@interface Graph : NSObject
@property NSMutableSet *myObjects;
- (id)initWithNumElements:(int)total;
- (NSMutableSet *)addOneMore:(NSMutableSet *)vertices;
- (NSMutableSet *)addTo:(NSMutableSet *)R from:(NSMutableSet *)P;
@end
и его реализации:
// Graph.m
#import "Graph.h"
@implementation Graph
// Put numbers 0, ..., total - 1 into the objects of self
- (id)initWithNumElements:(int)total {
self = [super init];
if (self) {
NSMutableSet *objects = [[NSMutableSet alloc] init];
for (int i=0; i<total; i++) {
[objects addObject:[NSNumber numberWithInt:i]];
}
_myObjects = objects;
}
return self;
}
// If possible, add one of the objects of self to set
- (NSMutableSet *)addOneMore:(NSMutableSet *)set {
NSMutableSet *allObjects = [self.myObjects copy];
for (id elt in set) {
[allObjects removeObject:elt];
}
//[allObjects minusSet:set];
return [self addTo:[set copy] from:allObjects];
}
// If possible, add one object from P to R
- (NSMutableSet *)addTo:(NSMutableSet *)R from:(NSMutableSet *)P {
if ([P count] == 0) {
return R;
}
id v = [P anyObject];
[R addObject:v];
return R;
}
@end
и я проверяю его с помощью следующего кода:
// main.m
#import <Foundation/Foundation.h>
#import "Graph.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Graph *G = [[Graph alloc] initWithNumElements:6];
NSMutableSet *results = [G addOneMore:[[NSMutableSet alloc] init]];
NSLog(@"%@", results);
}
return 0;
}
(я знаю, логически это код не имеет смысла. Он упрощен до глупости от чего-то, что когда-то делало лишь небольшое количество смысла.)
Я получаю ошибку
2014-10-27 11:19:14.936 Test[1469:303] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSSetI addObject:]: unrecognized selector sent to instance 0x100108a20'
и Xcode указывает мне точно на линии "[R AddObject: v];". Но материал отладки говорит, что R является NSMutableSet *, а v является _NFCSNumber *, в чем проблема? Насколько я могу судить, это должно быть справедливо.
Записанная строка "// [allObjects minusSet: set];" также генерирует непризнанную ошибку селектора, которая не возникает, когда я заменяю ее циклом for, который находится над ним. Опять же, эта строка должна быть действительной, насколько я могу судить, я не могу понять, что здесь не так.
Удивительно, что это исправлено. У меня есть два следующих вопроса: 1) Поскольку копия предоставляется NSObject, я просто предположил, что полученный класс будет таким же, как и объект, который вы копировали. Учитывая какой-то другой класс, как можно посмотреть, вернет ли «копия» тот же тип или нет? 2) Почему ничего не жаловалось, когда я назначил что-то, что не является NSMutableSet для переменной NSMutableSet? – Jim
'copy' - удобный метод, который делегирует реальную работу' copyWithZone: ', которая является частью' NSCopying'. Его возвращаемый тип 'id' является частью этого удобства быть на' NSObject' и, к сожалению, неизбежен. Как правило, 'copy' будет возвращать тот же класс, который вы вызываете, кроме контейнеров, которые имеют как неизменные, так и изменяемые варианты. В этом случае он всегда будет возвращать неизменяемую версию. Что касается (2), вы не получили предупреждение из-за типичного типа возврата id. Компилятор не знает реальный тип и, следовательно, не может вас предупредить. –