2012-01-12 62 views
0

请看看这两个简单的代码段。这UIImage神秘地转换为NSData

- (void)testMethod 
{ 

NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:@"myEncodedObjectKey"]; 
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 
} 

这:

[currentProfile testMethod]; 

if ([[currentProfile.avatar objectAtIndex:0] isKindOfClass:[NSData class]]) 
    NSLog(@"NSData");//Moment later it is NSData 

在第一个我从取NSUserDefaults的一个自定义对象,并使用名为“阿凡达”一NSMutableArray的变量工作。我将它的每个对象从NSData转换为UIImage。然后我通过使用NSLog检查我已经得到了什么。这是UIImage。在第二段代码中,您可以看到一会儿UIImage是如何根据自己的意愿回到NSData的。好像我描述我的问题很清楚。你明白发生了什么事?我不。非常感谢您的关注

回答

2

为什么要改变-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 
+0

你真是太棒了!非常感谢,哥们! – 2012-01-13 08:16:15

+0

这是写在您的个人资料中的内容:“如果您有任何有关编程或请求的问题,请不要犹豫与我联系”。我总是有很多关于编码的问题,比如现在的问题,所以如果你不是在开玩笑,我会打扰你一下。 – 2012-01-13 08:21:52

+0

没问题。我总是乐于提供帮助 – v1Axvw 2012-01-13 16:57:56