gpt4 book ai didi

objective-c - 将 NSCoding 与 Realm 模型对象一起使用

转载 作者:搜寻专家 更新时间:2023-10-30 20:16:19 26 4
gpt4 key购买 nike

几周来,我一直在用我的显示器敲打我的头,在绕过我的问题休息一下后,我发现我又遇到了同样的问题。

首先,我能找到的与我的问题最接近的东西: NSCoding / Realm in Google Groups

我正尝试在我的一些 Realm 模型对象上使用 NSCoding 协议(protocol),以便将它们变成标准的 NSData 对象,我可以在我的项目使用的一些框架中传输这些对象。但是,我收到了一些奇怪的错误,我根本找不到解决办法,而且我的经验不足,无法解决。

我正在使用一个简单的 NSKeyedArchiver,特别是 archivedDataWithRootObject。编码过程似乎进行得非常顺利,事实上我可以毫无问题地将其二进制 blob 作为 NSData 进行传输 - 字节接字节,编码的大小是解码器端接收到的大小。我的模型是这样定义的:

//
// CSTaskRealmModel.m
// CommSync
//
// Created by Ivan Lugo on 1/27/15.
// Copyright (c) 2015 AppsByDLI. All rights reserved.
//

#import "CSTaskRealmModel.h"

@implementation CSTaskRealmModel

#pragma mark - Realm modeling protocol

+ (NSDictionary *)defaultPropertyValues {

NSDictionary* defaults = nil;

defaults = @{@"taskDescription":@"",
@"taskTitle":@"",
@"taskPriority":[NSNumber numberWithInt:0],

@"UUID":@"",
@"deviceID":@"",
@"concatenatedID":@"",
@"assignedID":@"",
@"tag":@"",
@"completed":@false

};

return defaults;
}

+ (NSArray*)ignoredProperties {
return @[@"TRANSIENT_audioDataURL"];
}

+ (NSString*)primaryKey {
return @"concatenatedID";
}

#pragma mark - NSCoding Compliance

- (id) initWithCoder:(NSCoder *)aDecoder {

if(self = [super init]) {
self.UUID = [aDecoder decodeObjectForKey:kUUID];
self.deviceID = [aDecoder decodeObjectForKey:kDeviceId];
self.concatenatedID = [aDecoder decodeObjectForKey:kConcatenatedID];
self.assignedID = [aDecoder decodeObjectForKey:kAssignedID];
self.tag = [aDecoder decodeObjectForKey:kTag];

self.taskTitle = [aDecoder decodeObjectForKey:kTaskTitle];
self.taskDescription = [aDecoder decodeObjectForKey:kTaskDescription];

NSNumber* num = [aDecoder decodeObjectForKey:kCompleted];
self.completed = [num boolValue];
num = [aDecoder decodeObjectForKey:kTaskPriority];
self.taskPriority = [num integerValue];

NSMutableArray* dataArray = [aDecoder decodeObjectForKey:kRevisionDataArray];
for(CSTaskRevisionRealmModel* rev in dataArray) {
[self.revisions addObject:rev];
}

dataArray = [aDecoder decodeObjectForKey:kMediaDataArray];
for(CSTaskMediaRealmModel* media in dataArray) {
[self.taskMedia addObject:media];
}

dataArray = [aDecoder decodeObjectForKey:kCommentsDataArray];
for (CSCommentRealmModel* comment in dataArray) {
[self.comments addObject:comment];
}
}

return self;
}

- (void) encodeWithCoder:(NSCoder *)aCoder {

[aCoder encodeObject:_UUID forKey:kUUID];
[aCoder encodeObject:_deviceID forKey:kDeviceId];
[aCoder encodeObject:_concatenatedID forKey:kConcatenatedID];
[aCoder encodeObject:_assignedID forKey:kAssignedID];
[aCoder encodeObject:_tag forKey:kTag];
[aCoder encodeObject: [NSNumber numberWithBool:_completed] forKey:kCompleted];
[aCoder encodeObject: _taskTitle forKey:kTaskTitle];
[aCoder encodeObject:_taskDescription forKey:kTaskDescription];
[aCoder encodeObject:[NSNumber numberWithInteger:_taskPriority] forKey:kTaskPriority];

NSMutableArray* revArray = [NSMutableArray arrayWithCapacity:_revisions.count];
for (CSTaskRevisionRealmModel* rev in self.revisions) {
[revArray addObject:rev];
}
[aCoder encodeObject:revArray forKey:kRevisionDataArray];

NSMutableArray* mediaArray = [NSMutableArray arrayWithCapacity:_taskMedia.count];
for (CSTaskMediaRealmModel* media in self.taskMedia) {
[mediaArray addObject:media];
}
[aCoder encodeObject:mediaArray forKey:kMediaDataArray];

NSMutableArray* commentsArray = [NSMutableArray arrayWithCapacity:_comments.count];
for (CSCommentRealmModel* comment in self.comments) {
[commentsArray addObject:comment];
}
[aCoder encodeObject:commentsArray forKey:kCommentsDataArray];
}

@end

但是,当对象 正在解码时,在这些非常无害的线上...

NSData* taskData = [NSData dataWithContentsOfURL:localURL];
id newTask = [NSKeyedUnarchiver unarchiveObjectWithData:taskData];
// Where 'localURL' is just an on-disk location of the data object a device has received.

我收到这个错误;它出现在 Realm 源代码的 RLMAccessor 中.:

*** Terminating app due to uncaught exception 'RLMException', reason: 'Object has been deleted or invalidated.'

在我看来,模型的 init 方法中似乎发生了一些非常非常奇怪的事情,我无法弄清它的正反面。在某些情况下,如果我删除主键(可能试图绕过失效),错误会更改为(在同一源文件中):

'Primary key can't be changed after an object is inserted.'

我根本无法弄清楚这里发生了什么!关键是:在我设法向其添加一些属性之前,我的原始实现完美 工作:

//
// CSTaskRealmModel.m
// CommSync
//
// Created by Ivan Lugo on 1/27/15.
// Copyright (c) 2015 AppsByDLI. All rights reserved.
//

#import "CSTaskRealmModel.h"

@implementation CSTaskRealmModel

#pragma mark - Lifecycle
- (id)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super init]) {
self.UUID = [aDecoder decodeObjectForKey:@"UUID"];
self.deviceID = [aDecoder decodeObjectForKey:@"deviceID"];
self.concatenatedID = [aDecoder decodeObjectForKey:@"concatenatedID"];

self.taskTitle = [aDecoder decodeObjectForKey:@"taskTitle"];
self.taskDescription = [aDecoder decodeObjectForKey:@"taskDescripion"];
self.taskPriority = [aDecoder decodeIntForKey:@"taskPriority"];

}
return self;
}

- (void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.UUID forKey:@"UUID"];
[aCoder encodeObject:self.deviceID forKey:@"deviceID"];
[aCoder encodeObject:self.concatenatedID forKey:@"concatenatedID"];

[aCoder encodeObject:self.taskTitle forKey:@"taskTitle"];
[aCoder encodeObject:self.taskDescription forKey:@"taskDescripion"];
[aCoder encodeInteger:self.taskPriority forKey:@"taskPriority"];

// NOTE!
// This is ALL KINDS OF EXTREMELY INEFFICIENT!
// We should not rearchive and reconvert images we have already worked with
NSMutableArray* tempArrayOfImages = [NSMutableArray arrayWithCapacity:self.TRANSIENT_taskImages.count];
for(UIImage* image in self.TRANSIENT_taskImages) { // for every TRANSIENT UIImage we have on this task
NSData* thisImage = UIImageJPEGRepresentation(image, 0.3); // make a new JPEG data object with some compressed size
[tempArrayOfImages addObject:thisImage]; // add it to our container
}

NSData* archivedImages = [NSKeyedArchiver archivedDataWithRootObject:tempArrayOfImages]; // archive the data ...

[[RLMRealm defaultRealm] beginWriteTransaction];
self.taskImages_NSDataArray_JPEG = archivedImages; // and set the images of this task to the new archive
[[RLMRealm defaultRealm] commitWriteTransaction];

[aCoder encodeObject:self.taskImages_NSDataArray_JPEG forKey:@"taskImages"]; // encode the object and pray
}

+ (NSArray*)ignoredProperties {

return @[@"TRANSIENT_taskImages"];
}

请注意,我能看到的唯一重要区别是原始实现中没有 primaryKey 对象。我唯一能想到我做错的是,(a)我从根本上说我的 NSCoding 行有问题,或者我什至不应该对这些 Realm 对象进行 NSCoding,或者(b)不知何故,其他一些在将 Realm 对象打包并作为 NSData 发送出去之前,我的代码区域正在对 Realm 对象进行某些验证。

我无法准确表达(现在是凌晨 2:00,发帖时间...)我感谢您对此提供的任何见解或帮助。如果您想要更多代码上下文,我很乐意将其发布,或者为您指明我的 git 存储库的方向。

最佳答案

看起来有点中断,需要更巧妙的调试才能破解此问题。我欢迎对此答案的任何更正,或任何更深入的信息!

事实证明,访问 Realm 对象实际上不会让您获得 Realm 模型对象本身 - 或者至少,不是 NSCoding 协议(protocol)期望的方式.在调试期间,我发现未归档的类最终成为 RLMAccessor_[myClassName]。凭直觉,我决定尝试别的东西。

我不是仅仅获取我对编码感兴趣的 Realm 对象,而是实例化了一个全新的模型,并将感兴趣的模型中的所有关键属性分配给它。然后,将它添加到 Realm ,通过线路发送它的编码版本。事实证明,这非常有效。

出于某种原因,我还没有完全理解,返回的 Realm 访问器会使它从中提取数据的对象无效,这意味着它不能被重用。

我的方法可能不是最有效的,也可能不是 Realm 做事的方式,但它似乎符合我的需要:一个 Realm 模型对象,可以充当 transient 对象和持久对象。

关于objective-c - 将 NSCoding 与 Realm 模型对象一起使用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29554276/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com