2012-01-12 87 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