UIImage 神秘地转换为 NSData

Posted

技术标签:

【中文标题】UIImage 神秘地转换为 NSData【英文标题】:UIImage converts to NSData mysteriously 【发布时间】:2012-01-12 17:50:18 【问题描述】:

请看一下这两个简单的代码。这个

- (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 中获取一个自定义对象,并使用一个名为“avatar”的 NSMutableArray 变量。我将其每个对象从 NSData 转换为 UIImage。然后我使用 NSLog 检查我得到了什么。它是 UIImage。在第二段代码中,您可以看到 UIImage 是如何按照自己的意愿返回到 NSData 的。好像我清楚地描述了我的问题。你明白发生了什么吗?我不。非常感谢您的关注

【问题讨论】:

【参考方案1】:

为什么要更改 -testMethod 方法中的 self 对象?这是非常违法的。

您实际上正在做的是将作为参数传递给您的方法的局部变量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

【讨论】:

你真是个天才!非常感谢,伙计! 这是您个人资料中的内容:“如果您对编程有任何疑问或要求,请随时与我联系”。我总是有很多关于像现在这样的编码的问题,所以如果你不是在开玩笑,我会打扰你一点。 没问题。我总是乐于助人

以上是关于UIImage 神秘地转换为 NSData的主要内容,如果未能解决你的问题,请参考以下文章

如何将 JSON Image-String(不是 url)转换为 UIImage 以供查看

将 UIImage 转换为 NSData 并在 Swift 中转换回 UIImage?

将UIImage转换为NSData并在Swift中转换回UIImage?

UIImage 在将其转换为 CIImage,然后转换为 CGImage 并返回 UIImage 时失去其方向

将UIImage转换为NSData并返回UIImage

将 jpg UIImage 转换为位图 UIImage?