PFObject values may not have class: UIImage

2019-02-15 09:03发布

问题:

I have a subclass of PFObject called PFGiveItem.

@interface PFGiveItem : PFObject <PFSubclassing>

+(NSString *)parseClassName;
@property (strong, nonatomic) NSString *giveItemName;
@property (strong, nonatomic) UIImage *giveItemImage;

@end

When I try to query for images I have saved to Parse, and then save the images to each of my GiveItems, I get an error. This is part of a larger loop which includes its own PFQuery; I'm just isolating this part to keep it simple because the rest of it works.

PFQuery *queryForRelatedImages = [PFQuery queryWithClassName:@"giveItemPhoto"];
[queryForRelatedImages whereKey:@"objectId" equalTo:@"pAwHU2e7aw"];
[queryForRelatedImages findObjectsInBackgroundWithBlock:^(NSArray *photos, NSError *error) {
    PFFile *imageFile = photos[0][@"imageFile"];
    NSLog(@"%@", imageFile);
    [imageFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
        if (!error){
            newGiveItem.giveItemImage = [UIImage imageWithData:data];
        }
    }];
}];

When I run this code I get the error

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: 'PFObject values may not have class: UIImage'

Which doesn't seem to make sense since the given property of the PFGiveItem class is in fact of the type UIImage.

回答1:

You must use PFFile, at least for now. It seems PFObjectSubclassing, can't dynamically process a UIImage to PFFile. A simple way of handling this is to use a UIImage public property, and then a PFFile private property.

#import "PFObject.h"

@interface PFGiveItem : PFObject <PFSubclassing>
 @property (retain) UIImage *image;
@end

.m

#import "PFGiveItem.h"
@interface PFGiveItem()
 @property (retain) PFFile *imageFile;
@end

@implementation PFGiveItem
 @dynamic imageFile;
 @synthesize image = _image;
-(UIImage *)image
{
    if (!_image){
        [self fetchIfNeeded];
        _image = [UIImage imageWithData:[self.imageFile getData]];
    }
    return _image;
}
-(void)setImage:(UIImage *)image
{
    _image = image;
    self.imageFile = [PFFile fileWithData:UIImagePNGRepresentation(image)];
}
@end

Implementation of the subclassed item is simple, you just work with the UIImage like any other local variable. It helps to fetchInbackground and THEN use the image to keep parse off the main thread:

PFGiveItem *giveItem = (PFGiveItem *)[PFObject objectWithoutDataWithClassName:@"TableName" objectId:@"objectId"];
[giveItem fetchInBackgroundWithBlock:^(PFObject *object, NSError *error) {
    if (!error && object) {
        self.backgroundImageView.image = giveItem.image;
    }
}];