编写一个复杂的自定义结构数组到文件 Objective C

Posted

技术标签:

【中文标题】编写一个复杂的自定义结构数组到文件 Objective C【英文标题】:Write a complex array of custom structs to file Objective C 【发布时间】:2012-06-28 15:53:57 【问题描述】:

我需要保存和加载结构数组的内容,但我知道 Objective C 对可以读取/写入的数据类型非常挑剔。

这是我的结构:

struct SCourse 

    NSMutableArray* holes; // holds integers (pars)
    NSString*       name;
    int             size;
    BOOL            inUse; 
;

@interface CoursesManager : NSObject

    struct SCourse courses[5];

我需要使用哪些数据类型?他们每个人都需要不同的方法来读/写吗?我只是在寻找一种简单的方法来获取我需要的所有数据以及从文件中获取的所有数据。我可以用我更熟悉的语言 (C++) 轻松做到这一点,但我仍然忘记了 Objective-c 的一些细节。

编辑:解决方案(感谢大家的帮助)

-(void)applicationWillResignActive:(UIApplication *)application  

    // save the courses
    NSMutableArray* totalWriteArray = [[NSMutableArray alloc] initWithCapacity:MAX_COURSES];

    for (int i = 0; i < MAX_COURSES; ++i) 
    
        struct SCourse saveCourse = [coursesManager GetCourseAtIndex:i];

        NSNumber* nInUse = [NSNumber numberWithBool:saveCourse.inUse];      
        NSNumber* nSize = [NSNumber numberWithInt:saveCourse.size];

        NSMutableArray* writeArray = [[NSMutableArray alloc] initWithCapacity:4];
        [writeArray addObject:nInUse];
        [writeArray addObject:nSize];
        [writeArray addObject:saveCourse.name];
        [writeArray addObject:saveCourse.holes];
        [totalWriteArray addObject:writeArray];
    

    [totalWriteArray writeToFile:[self saveFilePath] atomically:YES]; 

为了重新加载...

-(void)loadFile 

    NSString *myPath = [self saveFilePath];
    BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:myPath];
    if (fileExists) 
        NSMutableArray* totalReadArray = [[NSMutableArray alloc] initWithContentsOfFile:[self saveFilePath]];

        for (int i = 0; i < MAX_COURSES; ++i) 
        
            struct SCourse loadCourse = [coursesManager GetCourseAtIndex:i];

            NSMutableArray* loadArray = [totalReadArray objectAtIndex:i];

            NSNumber* nInUse = [loadArray objectAtIndex:0];
            loadCourse.inUse = [nInUse boolValue];           

            NSNumber* nSize = [loadArray objectAtIndex:1];
            loadCourse.size = [nSize integerValue];

            NSString* inName = [loadArray objectAtIndex:2];
            loadCourse.name = inName;

            NSMutableArray* inHoles = [loadArray objectAtIndex:3];
            loadCourse.holes = inHoles;

            [coursesManager ReplaceCourseAtIndex:i With:loadCourse];
        
     

【问题讨论】:

这与在 C/C++ 中做这件事并没有真正的不同,是吗?从NSMutableArray 中提取值与从std::vector 中提取值并没有太大区别是吗... 我不同意。我想过为这个小项目编写自己的 std::vector 版本,但我真的没有时间。 NSMutable 数组要求您在转换为 int 之前将其转换为 NSNumber(毫无意义的浪费时间,恕我直言)。大多数(包括这个)操作与他们喜欢的数据类型之间有太多的小步骤,我没有时间去追捕它们。我希望在一个小时内完成,而不是 6 个。 你不必写std::vector;只需将源文件重命名为 .mm 即可正常使用。 Cocoa 集合类要求您使用NSNumber 是有原因的;它们只包含对象,而不是原始类型。 【参考方案1】:

第一件事。您不应该使用普通的旧 C 结构。 ARC 内存管理将不受欢迎。

如果您熟悉 C++,您可能应该使用 C++ 类,这将取悦编译器和运行时。取决于你想做什么。

数组。使用 NSArray 或 std::vector 但请不要使用纯 C 数组。不知道 ARC 将如何处理这个问题,但我想它不会很感激。 Objective-C 和 C++ 都提供了处理任何集合所需的所有工具。

序列化。您有多种可能性,其中之一是 NSCoder。

最后,使用所谓的现代语法,将事物转换为 ObjC 对象非常容易。

BOOL b = YES;
int i = 10;
double d = 3.14;
char* s = "Pouf pouf";

您可以通过 boxin' thingy 获得 ObjC 等价物:

NSNumber* bo = @( b );
NSNumber* io = @( i );
NSNumber* do = @( d );
NSString* so = @( s );
NSArray* ao = @[ @( i ), do ];
NSDictionary* = @ @"num" : io, @"str" : @( s ) ;

要在文件中写一些东西,一步到位:

[@ @"bool" : bo, @"array" : @[ @"string", @10, @( 10 + 20 ) ] 
    writeToFile: @"path.plist" atomically: YES];

但问题仍然存在,你想完成什么?

【讨论】:

这些都是很好的建议。我想要完成的是在游戏关闭和打开时保存并加载我的一系列课程。我已经设置了能够保存和加载的所有内容,但我对 Objective-c 数据类型有点沮丧。很多对我来说似乎是不必要的。在您的建议中不使用普通的旧 C 结构的原因是什么?我更喜欢使用数组而不是链表,以便事先分配内存。 您能否添加一些关于将 BOOL 转换为正确数据类型的内容,然后简单说明如何将每种数据类型写入文件?我已经有了文件路径。 BOOL 只是一个 NSNumber。在那里添加了一些行。 Xcode 4.4+。 BOOLsigned char不是 NSNumber 好建议。如果我使用 NSMutableArray 方法“writeToFile”它会处理它自己的大小吗?即 - 如果我只是将孔数组直接写入 plist,它会自行处理不同的大小吗?【参考方案2】:

一种简单的方法是将这些数组存储在 NSMutableDictionary 对象中并使用以下方法:

[mutableDict writeToFile:@"path/to/file" atomically:YES];

存储数据和:

NSMutableDictionary *anotherDict = [NSMutableDictionary dictionaryWithContentsOfFile:@"path/to/file"];

重新读取内容。

【讨论】:

NSMutableDictionary 和 NSMutableArray 类型在保存和加载时是否处理自己的大小?即 - 如果我使用 [myArray writeToFile:file automatically:YES];,并且我加载它,NSMutableArray 将处理它自己的大小? writeToFile:atomically: 要求数组中的对象是属性列表对象(NSStringNSArrayNSDictionaryNSDateNSNumberNSData)。这不适用于自定义对象。【参考方案3】:

以下是我的建议:

使用您想要的属性创建一个自定义类(.h 文件):

#import <Foundation/Foundation.h>

@interface CustomHolder : NSObject 
    NSString *last;
    NSString *first;
    NSString *middle;


@property (strong, nonatomic) NSString *last;
@property (strong, nonatomic) NSString *first;
@property (strong, nonatomic) NSString *middle;

@end

然后设置 .m 文件,以便您可以对对象进行编码/解码

#import "CustomHolder.h"

@implementation CustomHolder

@synthesize last, first, middle;

- (void)encodeWithCoder:(NSCoder *)encoder 

    [encoder encodeObject:first forKey:@"first"];
    [encoder encodeObject:last forKey:@"last"];
    [encoder encodeObject:middle forKey:@"middle"]; 


- (id)initWithCoder:(NSCoder *)decoder 

    if (self = [super init]) 
    
        self.first = [decoder decodeObjectForKey:@"first"];
        self.last = [decoder decodeObjectForKey:@"last"];
        self.middle = [decoder decodeObjectForKey:@"middle"]; 
    
    return self;


@end

那么你就可以 [NSKeyedArchiver archiveRootObject:obj toFile:[self saveFilePath]] 保存并 [NSKeyedUnarchiver unarchiveObjectWithFile:[self saveFilePath]] 加载

这可能最类似于使用 C 结构(尤其是因为 ARC 不允许您使用结构)。

【讨论】:

以上是关于编写一个复杂的自定义结构数组到文件 Objective C的主要内容,如果未能解决你的问题,请参考以下文章

自定义数组列表和队列

springboot~yml里的自定义配置~续

将复杂的结构(带有结构的内部数组)从 C# 传递到 C++

重用复杂的自定义UI元素 - Xcode Storyboard

基于数组的自定义数据结构1-图路径与编号二维数组

具有多个子项目的项目列表的自定义适配器?