【问题标题】:Reading wrong class type with NSKeyedUnarchiver使用 NSKeyedUnarchiver 读取错误的类类型
【发布时间】:2015-01-12 17:25:05
【问题描述】:

在我的应用程序中,我正在读取 NSMutableArray 并将其写入 NSUserDefaults。该数组包含如下所示的对象:

头文件:

#import <Foundation/Foundation.h>
#import <CoreLocation/CoreLocation.h>

@interface WorkLocationModel : NSObject

@property (nonatomic, strong) CLRegion *geoLocation;

@end

实现文件:

#import "WorkLocationModel.h"

@implementation WorkLocationModel

-(id)init {
// Init self
self = [super init];
if (self)
{
    // Setup
}
return self;
}

- (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:self.geoLocation forKey:@"geoLocation"];
}

-(void)initWithCoder:(NSCoder *)coder {
self.geoLocation = [coder decodeObjectForKey:@"geoLocation"];
}

@end

这就是我阅读清单的方式:

这是在我加载数组的 ViewController 中,oldArray 似乎记录了 NSKeyedUnarchiver 类型的 1 项(正确数量),而它应该是 WorkLocationModel 对象:

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *workLocationsData = [defaults objectForKey:@"workLocations"];
if (workLocationsData != nil)
{
    NSArray *oldArray = [NSKeyedUnarchiver unarchiveObjectWithData:workLocationsData];

    if (oldArray != nil)
    {
        _workLocations = [[NSMutableArray alloc] initWithArray:oldArray];
        NSLog(@"Not nil, count: %lu", (unsigned long)_workLocations.count);
    } else
    {
        _workLocations = [[NSMutableArray alloc] init];
    }
} else
{
    _workLocations = [[NSMutableArray alloc] init];
}

这就是我将 WorkLocationModel 对象添加到我的数组的方式:

NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
// Create a sample work location
WorkLocationModel *newModel = [[WorkLocationModel alloc] init];
newModel.geoLocation = currentRegion;
[_workLocations addObject:newModel];

// Save the new objects
[defaults setObject:[NSKeyedArchiver archivedDataWithRootObject:_workLocations] forKey:@"workLocations"];

// Synchronize the defaults
[defaults synchronize];

这里的 if 语句出现错误(进一步深入到我的 ViewController),我正在比较两个 CLRegions。

region 是一个函数参数。

    for (WorkLocationModel *currentWorkLocationModel in _workLocations)
{
    if ([region isEqual:currentWorkLocationModel.geoLocation])
    {
        // Found a match
    }
}

我已经浏览了代码,但我不明白为什么会这样,异常消息:

-[NSKeyedUnarchiver geoLocation]: unrecognized selector sent to instance 0x174108430
2015-01-12 18:23:20.085 myApp[1322:224462] *** Terminating app due to
uncaught exception 'NSInvalidArgumentException', reason: '-[NSKeyedUnarchiver geoLocation]:
unrecognized selector sent to instance

有人可以帮我解决这个问题吗?我迷路了

【问题讨论】:

  • 删除一个问题,然后在第二天重新作为一个新问题重新发布,这种形式真的很糟糕。
  • @rmaddy 可能看起来我这样做是因为不耐烦,但我的目的是让它更清楚。本来可以编辑的,抱歉。

标签: ios objective-c nsobject nskeyedarchiver nskeyedunarchiver


【解决方案1】:

initWithCoder: 方法与任何其他 init 方法一样 - 它必须调用 super 并返回一个实例。你的方法应该是:

- (instancetype) initWithCoder:(NSCoder *)coder
{
   self = [super init];
   if(self)
      self.geoLocation = [coder decodeObjectForKey:@"geoLocation"];
   return self;
}

如果您的超类也实现了initWithCoder:,那么super 调用将是[super initWithCoder:coder]encodeWithCoder: 也是如此)-NSObject 没有实现,所以您的编码和解码都可以。

您的编码、解码和读取方法上的断点会很快为您缩小问题范围。

HTH

【讨论】:

  • 您能否再解释一下 - 不太明白您在代码示例下方的文字中提到的内容。感谢您的解决方案!
  • 如果你有类A继承自NSObject并实现initWithCoder:/encodeWithCoder:,而类B继承自A那么是B的编码/解码方法必须调用A的编码/解码方法,处理A的状态,以及编码/解码B的状态。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2021-12-03
  • 2019-12-07
  • 2020-04-22
  • 2021-12-22
  • 2018-11-24
  • 1970-01-01
  • 2023-01-31
相关资源
最近更新 更多