Почему вы меняете собственный объект в вашем -testMethod
методе?Это крайне недопустимо.
На самом деле вы устанавливаете локальную переменную self
, которая передается в качестве параметра вашему методу, в новое значение.Это означает, что вы не редактируете получатель метода, вы просто редактируете свой параметр.
Когда ваш метод вызывается во время выполнения, вызывается функция C objc_msgSend()
:
// Declaration of objc_msgSend
id objc_msgSend(id receiver, SEL selector, ...);
Теперь, когда вы вызываете свой метод ...
[myInst testMethod];
... это то, что фактически вызывается во время выполнения:
objc_msgSend(myInst, @selector(testMethod));
Вы уже видите, что происходит?В реализации вашего метода переменная self
установлена на первый аргумент objc_msgSend
.Когда вы переназначаете self
, ваш не редактирует содержимое переменной myInst
и, таким образом, вы не редактируете исходный экземпляр, который вы передали.Вы просто устанавливаете myInst
, он же self
, локальную переменную, на ваш известный указатель.Вызывающий функцию не заметит изменения.
Сравните ваш код со следующим кодом C:
void myFunction(int a) {
a = 3;
}
int b = 2;
myFunction(b);
printf("%d\n", b);
// The variable b still has the original value assigned to it
Приведенный выше код делает то же, что и вы:
// Variation on objc_msgSend
void myMethodWrittenInC(id myInst) {
// Local variable changes, but will not change in the calling code
myInst = nil;
}
MyClass *myObj;
myObj = [[MyClass alloc] init];
myMethodWrittinInC(myObj);
// At this point myObj is not nil
И, наконец, вот что вы делаете:
- (void)testMethod
{
NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:@"myEncodedObjectKey"];
// You assign the local variable self (passed as an invisible argument
// to your method) to your new instance, but you do not edit the original
// instance self pointed to. The variable currentProfile does not change.
self = (Profile *) [NSKeyedUnarchiver unarchiveObjectWithData:data];
for (int i = 0; i < self.avatar.count; i++)
[self.avatar
replaceObjectAtIndex:i
withObject:[UIImage imageWithData:[self.avatar objectAtIndex:i]]];
if ([[self.avatar objectAtIndex:0] isKindOfClass:[UIImage class]])
NSLog(@"UIImage");//at this moment it's UIImage
}
// (1) Here currentProfile points to an instance of your class
[currentProfile testMethod];
// (2) it calls the method, but the local variable does not change
// and still points to the same instance.
if ([[currentProfile.avatar objectAtIndex:0] isKindOfClass:[NSData class]])
NSLog(@"NSData");//Moment later it is NSData