Ios 将自定义对象存储和加载到NSUserDefaults Objective-C时出现问题

Ios 将自定义对象存储和加载到NSUserDefaults Objective-C时出现问题,ios,objective-c,nsuserdefaults,Ios,Objective C,Nsuserdefaults,我一直试图在我的项目中存储和恢复NSUserDefaults自定义对象数组,但似乎出了问题。关于这个问题,我做了很多研究,但我找不到任何答案 似乎存储工作已经完成,因为我在NSUserDefaults中保存数据时没有收到任何错误,当我试图取回这些数据时,问题出现了:应用程序将在libc++abi.dylib时完全崩溃:以NSException类型的未捕获异常终止 这是我的密码: Wine.h #import <Foundation/Foundation.h> @import UIKi

我一直试图在我的项目中存储和恢复
NSUserDefaults
自定义对象数组,但似乎出了问题。关于这个问题,我做了很多研究,但我找不到任何答案

似乎存储工作已经完成,因为我在
NSUserDefaults
中保存数据时没有收到任何错误,当我试图取回这些数据时,问题出现了:应用程序将在
libc++abi.dylib时完全崩溃:以NSException类型的未捕获异常终止

这是我的密码:

Wine.h

#import <Foundation/Foundation.h>
@import UIKit;

#define NO_RATING -1

      @interface WineModel  : NSObject <NSCoding>
        @property(copy, nonatomic) NSString *type; 
        @property(strong, nonatomic) UIImage *photo;
        @property(strong, nonatomic) NSURL *photoURL;
        @property(strong, nonatomic) NSURL *wineCompanyWeb;
        @property(copy, nonatomic) NSString *notes;
        @property(copy, nonatomic) NSString *origin;
        @property(nonatomic) int rating;
        @property(strong, nonatomic) NSArray *grapes;
        @property(copy, nonatomic) NSString *name;
        @property(copy, nonatomic) NSString *wineCompanyName;

        - (id) initWithCoder: (NSCoder *) decoder;
        - (void) encodeWithCoder: (NSCoder *) encoder;

//SOME OTHER METHODS...//

-(id) initWithName: (NSString *) aName
   wineCompanyName: (NSString *) aWineCompanyName
              type: (NSString *) aType
            origin: (NSString *) anOrigin
            grapes: (NSArray *) arrayOfGrapes
    wineCompanyWeb: (NSURL *) aURL
             notes: (NSString *) aNotes
            rating: (int) aRating
          photoURL: (NSURL *) aPhotoURL;

//For JSON
-(id) initWithDictionary: (NSDictionary *) aDict;

@end
这是葡萄酒课。它有
协议和两种方法
(id)initWithCoder:(NSCoder*)解码器
(void)编码器与编码器:(NSCoder*)编码器。到目前为止,我看起来还不错,让我们继续下一节课:

Winery.h

#import <Foundation/Foundation.h>
#import "Wine.h"

#define RED_WINE_KEY @"Red"
#define WHITE_WINE_KEY @"White"
#define OTHER_WINE_KEY @"Others"

@interface WineryModel : NSObject

@property (strong, nonatomic) NSMutableArray *redWines;
@property (strong, nonatomic) NSMutableArray *whiteWines;
@property (strong, nonatomic) NSMutableArray *otherWines;

@property(readonly, nonatomic) int redWineCount;
@property(readonly, nonatomic) int whiteWineCount;
@property(readonly, nonatomic) int otherWineCount;


-(WineModel *) redWineAtIndex: (NSUInteger) index; 
-(WineModel *) whiteWineAtIndex: (NSUInteger) index;
-(WineModel *) otherWineAtIndex: (NSUInteger) index;

@end
因此,第一次启动应用程序时,它将从web中的JSON文件下载数据,然后将信息存储在NSUserDefaults中。看起来这一步做得很正确(至少在这一点上没有崩溃)。问题出现在第二次启动应用程序之后。它将检查NSUserDefault下是否有本地数据存储,如果有,它将尝试加载数据并存储到NSMutableAtray中。不幸的是,它不会这样做,它在这里崩溃
self.redWines=[NSKeyedUnarchiver unarchiveObjectWithData:decodedRedWines]和我以前写的错误代码。在调试时,我可以看到在检索
redWines
键时有数据,但它似乎出了问题

请注意,我正在使用自定义的初始值设定项(
initWithDictionary
)来创建wines对象,而不是默认的
init
方法。我不知道这是否是坠机的原因

以下是完整的日志:

2017-05-22 20:31:30.354640+0200 App[1905:891526] -[NSTaggedPointerString objectForKey:]: unrecognized selector sent to instance 0xa5c064950b08843b
2017-05-22 20:31:30.354932+0200 App[1905:891526] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSTaggedPointerString objectForKey:]: unrecognized selector sent to instance 0xa5c064950b08843b'
*** First throw call stack:
(0x18e0bafe0 0x18cb1c538 0x18e0c1ef4 0x18e0bef54 0x18dfbad4c 0x1000591d8 0x100057dec 0x18eb0a430 0x18eb10f10 0x18eaa684c 0x18eb0a430 0x18eb09b68 0x18eb08d94 0x100061118 0x1000621d0 0x10005c120 0x19425d204 0x194469738 0x19446f1e0 0x194483d18 0x19446c474 0x18fc63884 0x18fc636f0 0x18fc63aa0 0x18e06942c 0x18e068d9c 0x18e0669a8 0x18df96da4 0x194256384 0x194251058 0x100060b90 0x18cfa559c)
libc++abi.dylib: terminating with uncaught exception of type NSException
有什么想法吗


提前谢谢

您的initWithCoder方法中有一个输入错误:

self.wineCompanyName=[decoder decodeObjectForKey:@“comapny


如果这还不能解决问题,我会更仔细地查看NSUserDefaults文档,它说“从NSUserDefaults返回的值是不可变的,即使您将可变对象设置为值。”您的redWines属性被定义为NSMutableArray。

要使不可变对象可变,只需调用
mutableCopy

@property (strong, nonatomic) NSMutableArray *redWines;

...

self.redWines = [[NSKeyedUnarchiver unarchiveObjectWithData: decodedRedWines] mutableCopy];

谢谢你的评论。我修正了打字错误(我讨厌这个愚蠢的错误),我还尝试添加三个新的不可变NSArray来检查这是否是问题所在,但我仍然得到相同的结果。。。我将更新线程以向您展示它现在是什么样子。我也会尝试一下,但我不确定问题是否在于我使用的是不可变数组而不是可变数组。这两种类型的代码看起来都很混乱。如果您确实需要可变对象,请删除不可变对象。添加异常的实际原因会很有帮助。谢谢,你是对的,这两种类型都会让它有点混乱。我将再次更新线程,以便您可以看到更改,但我仍然遇到相同的崩溃:(添加断点并调试代码或打印未归档对象的输出。我添加了以下断点:1.if([[[[userDefault dictionaryRepresentation]allKeys]containsObject:@“redWines]”)和&(…)2.NSData*decodedRedWines=[userDefault objectForKey:@“redWines”];3.self.redWines=[[NSKeyedUnarchiver unarchiveObjectWithData:decodedRedWines]可变表复制];4.NSData*encodedRedWines=[NSKeyedArchiver archivedDataWithRootObject:_redWines];5.[userDefault setObject:encodedRedWines:@“redWines”];您是否尝试过在libobjc.a.dylib中的
objc\u exception\u throw
或CoreFoundation中的
[NSException raise]
上设置断点?如果您可以将问题追溯到它阻塞的确切元素,我怀疑您会很快发现问题。是否可以记录
[NSKeyedUnarchiver unarchiveObjectWithData:decodedRedWines]
这一行并告诉我返回对象的类型?如下:
NSLog(@“%@,[NSKeyedUnarchiver unarchiveObjectWithData:decodedRedWines])
这将有助于了解您在
NSUserDefaults
中存储的确切内容。嗨,Hemang,谢谢您的评论。我尝试了您的建议,但没有在NSLog中得到输出,而是出现以下错误:[NSTaggedPointerString objectForKey:]:未识别的选择器发送到实例0xa5c064950b08843b应用程序[3437:1872740]***由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:'-[NSTaggedPointerString objectForKey:]:发送到实例0xa5c064950b08843b的无法识别的选择器'***第一次抛出调用堆栈:(0x18e0bafe0 0x18cb1c538 0x18e0c1ef4…0x194251058 0x1000c4acc 0x18cfa559c)libc++abi.dylib:以NSException类型的未捕获异常终止
2017-05-22 20:31:30.354640+0200 App[1905:891526] -[NSTaggedPointerString objectForKey:]: unrecognized selector sent to instance 0xa5c064950b08843b
2017-05-22 20:31:30.354932+0200 App[1905:891526] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSTaggedPointerString objectForKey:]: unrecognized selector sent to instance 0xa5c064950b08843b'
*** First throw call stack:
(0x18e0bafe0 0x18cb1c538 0x18e0c1ef4 0x18e0bef54 0x18dfbad4c 0x1000591d8 0x100057dec 0x18eb0a430 0x18eb10f10 0x18eaa684c 0x18eb0a430 0x18eb09b68 0x18eb08d94 0x100061118 0x1000621d0 0x10005c120 0x19425d204 0x194469738 0x19446f1e0 0x194483d18 0x19446c474 0x18fc63884 0x18fc636f0 0x18fc63aa0 0x18e06942c 0x18e068d9c 0x18e0669a8 0x18df96da4 0x194256384 0x194251058 0x100060b90 0x18cfa559c)
libc++abi.dylib: terminating with uncaught exception of type NSException
@property (strong, nonatomic) NSMutableArray *redWines;

...

self.redWines = [[NSKeyedUnarchiver unarchiveObjectWithData: decodedRedWines] mutableCopy];