如何使用objective-c从CloudKit中的资产字段中检索图像
Posted
技术标签:
【中文标题】如何使用objective-c从CloudKit中的资产字段中检索图像【英文标题】:How to retrieve an image from an asset field in CloudKit using objective-c 【发布时间】:2016-02-07 15:44:25 【问题描述】:我在 CloudKit 中有一个记录类型。它存储一个字符串字段和一个资产字段。使用仪表板,我将图像上传到资产字段。
我可以检索字符串字段。我现在需要检索资产字段的内容并使用objective-c 将其存储到图像中。有人可以帮忙吗?
我正在尝试在表格视图中显示记录类型。我有一个名为 TJKCategoriesViewController 的类,它继承自 UIViewController。
我在 TJKCategoriesViewController 类的 viewDidLoad 方法中有这段代码:
// get all categories
_jokeCategories = [[NSMutableArray alloc] init];
CKDatabase *jokePublicDatabase = [[CKContainer containerWithIdentifier:JOKE_CONTAINER] publicCloudDatabase];
NSPredicate *predicateCategory = [NSPredicate predicateWithFormat:@"CategoryName != %@", CATEGORY_TO_REMOVE_OTHER];
CKQuery *queryCategory = [[CKQuery alloc] initWithRecordType:CATEGORY_RECORD_TYPE predicate:predicateCategory];
NSSortDescriptor *sortCategory = [[NSSortDescriptor alloc] initWithKey:CATEGORY_FIELD_NAME ascending:YES];
queryCategory.sortDescriptors = [NSArray arrayWithObjects:sortCategory, nil];
[jokePublicDatabase performQuery:queryCategory inZoneWithID:nil completionHandler:^(NSArray<CKRecord*>* results, NSError * error)
if (!error)
// add all categories to array
for (CKRecord* jokeCategory in results)
TJKCategories *categories = [TJKCategories initWithCategory:[jokeCategory valueForKey:CATEGORY_FIELD_NAME] categoryImage:[jokeCategory valueForKey:@"CategoryImage"]];
[_jokeCategories addObject:categories];
NSLog(@"Categories = %@",_jokeCategories);
// setup table
[self setupTableContents];
else
// display alert message and pop the view controller from the stack
GHSAlerts *alert = [[GHSAlerts alloc] initWithViewController:self];
errorActionBlock errorBlock = ^void(UIAlertAction *action) [self closeCategories:self];;
[alert displayErrorMessage:@"Oops!" errorMessage:@"The joke categories failed to load. This screen will close. Just try again!" errorAction:errorBlock];
];
这是“setupTableContents”方法
// setup the array that will hold the table's contents
-(void)setupTableContents
// store to property and reload the table contents
dispatch_async(dispatch_get_main_queue(), ^
[self.categoriesTableView reloadData];
);
TJKCategories 是一个将两个字段存储在记录类型中的类。这是 TJKCategories.h 文件:
#import <UIKit/UIKit.h>
@interface TJKCategories : NSObject
#pragma Properties
@property (nonatomic, copy) UIImage *categoryImage;
@property (nonatomic, copy) NSString *categoryName;
#pragma Initializers
+(instancetype)initWithCategory:(NSString *)categoryName
categoryImage:(UIImage *)categoryImage;
-(instancetype)initWithCategory:(NSString *)categoryName
categoryImage:(UIImage *)categoryImage;
@end
这是 TJKCategories.m 文件:
// designated initializer
-(instancetype)initWithCategory:(NSString *)categoryName categoryImage:(UIImage *)categoryImage
self = [super init];
if (self)
self.categoryImage = categoryImage;
self.categoryName = categoryName;
return self;
// class level initializer
+(instancetype)initWithCategory:(NSString *)categoryName categoryImage:(UIImage *)categoryImage
TJKCategories *category = [[self alloc]initWithCategory:categoryName categoryImage:categoryImage];
return category;
// override default initializer
-(instancetype)init
return [self initWithCategory:@"" categoryImage:nil];
在我使用的 viewDidLoad 方法中:[jokePublicDatabase performQuery:queryCategory inZoneWithID:nil completionHandler:^(NSArray* results, NSError * error)
检索记录类型的结果。然后我循环遍历结果数组,我可以检索字符串“CATEGORY_FOR_NAME”(这是“CategoryName”的常量,但是当我尝试检索图像“CategoryImage”的字段时,我得到“无法识别的选择器发送到实例" 错误。
如果你想知道常量后面的名字是什么,这里是我的联系人文件:
// declare constants
extern NSString *const DEFAULT_CATEGORY;
extern NSString *const JOKE_CONTAINER;
extern NSString *const CATEGORY_RECORD_TYPE;
extern NSString *const CATEGORY_FIELD_NAME;
extern NSString *const CATEGORY_TO_REMOVE_OTHER;
extern NSString *const CATEGORY_TO_REMOVE_RANDOM;
extern NSString *const JOKE_RECORD_TYPE;
extern NSString *const JOKE_DESCR;
extern NSString *const JOKE_SUBMITTED_BY;
extern NSString *const JOKE_TITLE;
// assign values to constants
NSString *const DEFAULT_CATEGORY = @"None";
NSString *const JOKE_CONTAINER = @"iCloud.com.glennseplowitz.Jokes";
NSString *const CATEGORY_RECORD_TYPE = @"Categories";
NSString *const CATEGORY_FIELD_NAME = @"CategoryName";
NSString *const CATEGORY_TO_REMOVE_OTHER = @"Other";
NSString *const CATEGORY_TO_REMOVE_RANDOM = @"Random";
NSString *const JOKE_RECORD_TYPE = @"Jokes";
NSString *const JOKE_DESCR = @"jokeDescr";
NSString *const JOKE_SUBMITTED_BY = @"jokeSubmittedBy";
NSString *const JOKE_TITLE = @"jokeTitle";
所以我要做的是从记录类型中检索资产类型“CategoryImage”并将其存储到 UIImage。但就像我说的那样,它给了我错误“无法识别的选择器发送到实例”,因为我相信它不能直接将资产字段转换为 UIImage 字段。
谢谢, 格伦
【问题讨论】:
用一些相关代码更新您的问题。展示你尝试过的东西。说明您遇到的问题以及您具体需要哪些帮助。 嗨 rmaddy,在我看来确实加载方法我有这个代码 嗨 rmaddy,感谢您告诉我拼写所有代码。通过这样做,它让我重新思考事情。所以你确实帮助了我。 【参考方案1】:想通了!我将 TJKCategories 类更改为接受 CKAsset 而不是 UIImage。然后我将 CKAsset 转换为 UIImage。
这是 TJKCategories.h 文件:
#import <UIKit/UIKit.h>
#import <CloudKit/CloudKit.h>
@interface TJKCategories : NSObject
#pragma Properties
@property (nonatomic, copy) UIImage *categoryImage;
@property (nonatomic, copy) NSString *categoryName;
#pragma Initializers
+(instancetype)initWithCategory:(NSString *)categoryName
categoryImage:(CKAsset *)categoryImageAsset;
-(instancetype)initWithCategory:(NSString *)categoryName
categoryImage:(CKAsset *)categoryImageAsset;
@end
这是 TJKCategories.m 文件:
#import "TJKCategories.h"
@interface TJKCategories()
#pragma Properities
@property (nonatomic, strong) CKAsset *categoryImageAsset;
@end
@implementation TJKCategories
#pragma initializers
// designated initializer
-(instancetype)initWithCategory:(NSString *)categoryName categoryImage:(CKAsset *)categoryImageAsset
self = [super init];
if (self)
self.categoryImageAsset = categoryImageAsset;
self.categoryName = categoryName;
UIImage *image = [[UIImage alloc] initWithContentsOfFile:self.categoryImageAsset.fileURL.path];
self.categoryImage = image;
return self;
// class level initializer
+(instancetype)initWithCategory:(NSString *)categoryName categoryImage:(CKAsset *)categoryImageAsset
TJKCategories *category = [[self alloc]initWithCategory:categoryName categoryImage:categoryImageAsset];
return category;
// override default initializer
-(instancetype)init
return [self initWithCategory:@"" categoryImage:nil];
我也改了行:
TJKCategories *categories = [TJKCategories initWithCategory:[jokeCategory valueForKey:CATEGORY_FIELD_NAME] categoryImage:[jokeCategory **objectForKey**:@"CategoryImage"]];
到
TJKCategories *categories = [TJKCategories initWithCategory:[jokeCategory valueForKey:CATEGORY_FIELD_NAME] categoryImage:[jokeCategory **valueForKey**:@"CategoryImage"]];
注意 CategoryImage 现在使用 valueForKey 而不是 objectForKey。
【讨论】:
以上是关于如何使用objective-c从CloudKit中的资产字段中检索图像的主要内容,如果未能解决你的问题,请参考以下文章
使用 CloudKit + CoreData,如何在没有 SwiftUI 的 @FetchRequest 的情况下从远程云更新中更新 UI?
如何使用 CloudKit 将条目从公共数据库保存到私有数据库
如何更灵活的处理 CloudKit 从云端同步到本地的 CoreData 托管对象