Why are you changing the self object in your -testMethod
method? This is highly illegal.
What you're actually doing is setting a local variable self
, which is passed as a parameter to your method, to a new value. This means you're not editing the receiver of the method, you're just editing your parameter.
When your method is called at runtime the C function objc_msgSend()
is called:
// Declaration of objc_msgSend
id objc_msgSend(id receiver, SEL selector, ...);
Now when you call your method ...
[myInst testMethod];
... this is what actually gets called at runtime:
objc_msgSend(myInst, @selector(testMethod));
Do you already see what's happening? In your method implementation the self
variable is set to the first argument of objc_msgSend
. When you're reassigning self
, your not editing what the variable myInst
contains and thus you're not editing your the original instance you passed. You're just setting myInst
, aka self
, a local variable, to your knew pointer. The caller of the function will not notice the change.
Compare you're code to the following C code:
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
The above code does the same you do:
// 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
And finally this is what you do:
- (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