美文网首页
归档archive

归档archive

作者: 喵喵粉 | 来源:发表于2020-07-02 11:43 被阅读0次

更新swift版本

fileprivate let filePath: String = {
        
        ///每个账号对应一个文件
        let path = NSTemporaryDirectory() + "\(kUserInfo.userId)-history.hs"
        
        return path
    }()
  • 加载
func loadHistory() {
        
        if #available(iOS 11.0, *) {
            let url = URL(fileURLWithPath: filePath)
            
            guard let data = try? Data(contentsOf: url) else {
                return
            }
            
            guard let list = try? NSKeyedUnarchiver.unarchiveTopLevelObjectWithData(data) as? [String] else {
                DebugLog("加载历史记录失败")
                return
            }
            DebugLog(list)
            lists = list
        } else {
            guard let list = NSKeyedUnarchiver.unarchiveObject(withFile: filePath) as? [String] else {
                DebugLog("加载历史记录失败")
                return
            }
            DebugLog(list)
            lists = list
        }
    }
  • 保存
fileprivate func saveAction() -> Bool {
        if #available(iOS 11.0, *) {
            guard let data = try? NSKeyedArchiver.archivedData(withRootObject: lists, requiringSecureCoding: false) else {
                return false
            }
            
            let url = URL(fileURLWithPath: filePath)
            
            guard ((try? data.write(to: url)) != nil) else { return false }
        }
        return NSKeyedArchiver.archiveRootObject(lists, toFile: filePath)
    }

自定义对象的归档,使用iOS11API

+archivedDataWithRootObject:requiringSecureCoding:error:
+unarchivedObjectOfClasses:fromData:error:
+unarchivedObjectOfClass:fromData:error:

自定义类Book,遵守NSSecureCoding协议

  • Book.h
@interface Book : NSObject<NSSecureCoding>

@property (nonatomic, strong) NSString *bookName;

@end

实现supportsSecureCoding、- initWithCoder:、 -encodeWithCoder:方法

supportsSecureCoding
+ (BOOL)supportsSecureCoding {
    return YES;
}

- (id)initWithCoder:(NSCoder *)coder { ... }
- (void)encodeWithCoder:(NSCoder *)coder { ... }
  • Book.m
    SERIALIZER_CODER_DECODER宏贴在末尾
#import "Book.h"
#import "Runtime+CoderDeCoder.h"

@implementation Book

SERIALIZER_CODER_DECODER

@end

1. 单个Book对象的归档

Book *book = [Book new];
book.bookName = @"book";
    
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:book requiringSecureCoding:NO error:nil];
Book *unarchiverBook = [NSKeyedUnarchiver unarchivedObjectOfClass:[Book class] fromData:data error:nil];

2. Book数组的归档

当修改数组的Book对象时,归档的数据不会受到影响

Book *book1 = [Book new];
book1.bookName = @"book1";

Book *book2 = [Book new];
book2.bookName = @"book2";

NSArray *books = @[book1, book2];

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:books requiringSecureCoding:NO error:nil];

//修改book2
Book *nb = books.lastObject;
nb.bookName = @"new bookName 2";

//打印原来的books
for (Book *book in books) {
    NSLog(@"1---%@", book.bookName);
}

NSArray *unarchivers = [NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithArray:@[Book.class, NSArray.class]] fromData:data error:nil];

//打印解档的books
for (Book *book in unarchivers) {
    NSLog(@"2---%@", book.bookName);
}

打印结果

1---book1
1---new bookName 2 //数据变动
2---book1
2---book2  //数据未变

3. Book字典的归档

- (void)dictionaryDemo {
    Book *book1 = [Book new];
    book1.bookName = @"book1";
    Book *book2 = [Book new];
    book2.bookName = @"book2";
    
    //1. 原始数据
    NSDictionary *dic = @{@"a": book1, @"b": book2};
    for (Book *book in dic.allValues) {
        NSLog(@"1---%@", book.bookName);
    }
    
    //2.归档
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:dic requiringSecureCoding:NO error:nil];
    
    //3.修改原始数据
    Book *nb = dic.allValues.lastObject;
    nb.bookName = @"new bookName";
    
    for (Book *book in dic.allValues) {
        NSLog(@"2---%@", book.bookName);
    }
    
    //4.解档
    NSDictionary *unarchiver = [NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithArray:@[Book.class, NSDictionary.class]] fromData:data error:nil];
    for (Book *book in unarchiver.allValues) {
        NSLog(@"3---%@", book.bookName);
    }
}
  • 打印
1---book1
1---book2
2---book1
2---new bookName
3---book1
3---book2

4. 非自定义对象的归档

NSArray *strings = @[@"book1", @"book2"];

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:strings requiringSecureCoding:NO error:nil];
NSArray *unarchiverStrs = [NSKeyedUnarchiver unarchivedObjectOfClass:[NSArray class] fromData:data error:nil];
for (NSString *str in unarchiverStrs) {
    NSLog(@"%@", str);
}

5. 归档宏SERIALIZER_CODER_DECODER

  • Runtime+CoderDeCoder.h
#import <objc/runtime.h>

//https://blog.csdn.net/longlongValue/article/details/81060583

#define SERIALIZER_CODER_DECODER     \
\
- (id)initWithCoder:(NSCoder *)coder    \
{   \
    Class cls = [self class];   \
    while (cls != [NSObject class]) {   \
        /*判断是自身类还是父类*/    \
        BOOL bIsSelfClass = (cls == [self class]);  \
        unsigned int iVarCount = 0; \
        unsigned int propVarCount = 0;  \
        unsigned int sharedVarCount = 0;    \
        Ivar *ivarList = bIsSelfClass ? class_copyIvarList([cls class], &iVarCount) : NULL;/*变量列表,含属性以及私有变量*/   \
        objc_property_t *propList = bIsSelfClass ? NULL : class_copyPropertyList(cls, &propVarCount);/*属性列表*/   \
        sharedVarCount = bIsSelfClass ? iVarCount : propVarCount;   \
\
        for (int i = 0; i < sharedVarCount; i++) {  \
            const char *varName = bIsSelfClass ? ivar_getName(*(ivarList + i)) : property_getName(*(propList + i)); \
            NSString *key = [NSString stringWithUTF8String:varName];   \
            id varValue = [coder decodeObjectForKey:key];   \
            NSArray *filters = @[@"superclass", @"description", @"debugDescription", @"hash"]; \
            if (varValue && [filters containsObject:key] == NO) { \
                [self setValue:varValue forKey:key];    \
            }   \
        }   \
        free(ivarList); \
        free(propList); \
        cls = class_getSuperclass(cls); \
    }   \
    return self;    \
}   \
\
- (void)encodeWithCoder:(NSCoder *)coder    \
{   \
    Class cls = [self class];   \
    while (cls != [NSObject class]) {   \
        /*判断是自身类还是父类*/    \
        BOOL bIsSelfClass = (cls == [self class]);  \
        unsigned int iVarCount = 0; \
        unsigned int propVarCount = 0;  \
        unsigned int sharedVarCount = 0;    \
        Ivar *ivarList = bIsSelfClass ? class_copyIvarList([cls class], &iVarCount) : NULL;/*变量列表,含属性以及私有变量*/   \
        objc_property_t *propList = bIsSelfClass ? NULL : class_copyPropertyList(cls, &propVarCount);/*属性列表*/ \
        sharedVarCount = bIsSelfClass ? iVarCount : propVarCount;   \
        \
        for (int i = 0; i < sharedVarCount; i++) {  \
            const char *varName = bIsSelfClass ? ivar_getName(*(ivarList + i)) : property_getName(*(propList + i)); \
            NSString *key = [NSString stringWithUTF8String:varName];    \
            /*valueForKey只能获取本类所有变量以及所有层级父类的属性,不包含任何父类的私有变量(会崩溃)*/  \
            id varValue = [self valueForKey:key];   \
            NSArray *filters = @[@"superclass", @"description", @"debugDescription", @"hash"]; \
            if (varValue && [filters containsObject:key] == NO) { \
                [coder encodeObject:varValue forKey:key];   \
            }   \
        }   \
        free(ivarList); \
        free(propList); \
        cls = class_getSuperclass(cls); \
    }   \
}\
\
+ (BOOL)supportsSecureCoding {\
    return YES;\
}

6. 给NSObject分类添加归档方法

  • NSObject+Archiver.h
#import <Foundation/Foundation.h>

NS_ASSUME_NONNULL_BEGIN

@interface NSObject (Archiver)

/**
 object: 自定义对象、自定义对象数组/字典、基本数据类型/数组/字典
 classTypes: 自定义对象1个 自定义对象数组/字典2个
 custom:是否自定义对象
 */
- (id)extArchivierObjectClassType:(Class)classType customType:(BOOL)custom;

@end

NS_ASSUME_NONNULL_END
  • NSObject+Archiver.m
#import "NSObject+Archiver.h"

@implementation NSObject (Archiver)

- (id)extArchivierObjectClassType:(Class)classType customType:(BOOL)custom {
    
    //1. 判断objcect的类型 数组/字典/非集合
    
    //1.1 数组
    if ([self isKindOfClass:[NSArray class]]) {
        
        NSArray *items = (NSArray *)self;
        
        //2. 判断是否是自定义对象
        if (custom) {
            
            //归档对象未遵守 NSSecureCoding 协议
            if (![items.firstObject conformsToProtocol:@protocol(NSSecureCoding)]) {
                NSLog(@"-----自定义类 未遵守 NSSecureCoding 协议-----");
                return nil;
            }
            
            NSData *data = [NSKeyedArchiver archivedDataWithRootObject:items requiringSecureCoding:NO error:nil];
            NSArray *unarchiver = [NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithArray:@[classType, NSArray.class]] fromData:data error:nil];
            return unarchiver;
        } else {
            NSData *data = [NSKeyedArchiver archivedDataWithRootObject:items requiringSecureCoding:NO error:nil];
            NSArray *unarchiver = [NSKeyedUnarchiver unarchivedObjectOfClass:[NSArray class] fromData:data error:nil];
            return unarchiver;
        }
    }
    //1.2 字典
    else if ([self isKindOfClass:[NSDictionary class]]) {
        
        NSDictionary *dic = (NSDictionary *)self;
        
        //2. 判断是否是自定义对象
        if (custom) {
            
            //归档对象未遵守 NSSecureCoding 协议
            if (![dic.allValues.firstObject conformsToProtocol:@protocol(NSSecureCoding)]) {
                NSLog(@"-----自定义类 未遵守 NSSecureCoding 协议-----");
                return nil;
            }
            
            NSData *data = [NSKeyedArchiver archivedDataWithRootObject:dic requiringSecureCoding:NO error:nil];
            NSDictionary *unarchiver = [NSKeyedUnarchiver unarchivedObjectOfClasses:[NSSet setWithArray:@[classType, NSDictionary.class]] fromData:data error:nil];
            return unarchiver;
        } else {
            NSData *data = [NSKeyedArchiver archivedDataWithRootObject:dic requiringSecureCoding:NO error:nil];
            NSDictionary *unarchiver = [NSKeyedUnarchiver unarchivedObjectOfClass:[NSDictionary class] fromData:data error:nil];
            return unarchiver;
        }
    }
    
    //1.3 非集合的
    if (custom) {
        //归档对象未遵守 NSSecureCoding 协议
        if (![self conformsToProtocol:@protocol(NSSecureCoding)]) {
            NSLog(@"-----自定义类 未遵守 NSSecureCoding 协议-----");
            return nil;
        }
    }
        
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self requiringSecureCoding:NO error:nil];
    return [NSKeyedUnarchiver unarchivedObjectOfClass:classType fromData:data error:nil];
}

@end
  • 测试
- (void)extStringDemo {
        //字符串数组归档
    NSMutableArray *strs = [NSMutableArray arrayWithArray:@[@"book1", @"book2"]];
    id archive = [strs extArchivierObjectClassType:NSString.class customType:NO];
//    for (NSString *ss in unarchiverss) {
//        NSLog(@"ss---%@", ss);
//    }
    
    strs[0] = @"new book1";
}

- (void)extBookDemo {
    Book *book1 = [Book new];
    book1.bookName = @"book1";
    
    id archive = [book1 extArchivierObjectClassType:[Book class] customType:YES];

    //修改book
    book1.bookName = @"new bookName 1";
    NSLog(@"old:%@ - new:%@", book1.bookName, archive);
}

- (void)extArchiverArrayDemo {
    Book *book1 = [Book new];
    book1.bookName = @"book1";

    Book *book2 = [Book new];
    book2.bookName = @"book2";

    NSArray *books = @[book1, book2];
    NSArray *unarchivers = [books extArchivierObjectClassType:[Book class] customType:YES];

    //修改book2
    Book *nb = books.lastObject;
    nb.bookName = @"new bookName 2";

    //打印原来的books
    for (Book *book in books) {
        NSLog(@"1---%@", book.bookName);
    }

    //打印解档的books
    for (Book *book in unarchivers) {
        NSLog(@"2---%@", book.bookName);
    }
}

- (void)extArchiverDictionaryDemo {
    Book *book1 = [Book new];
    book1.bookName = @"book1";

    Book *book2 = [Book new];
    book2.bookName = @"book2";

    NSDictionary *dic = @{@"a": book1, @"b": book2};
    for (Book *book in dic.allValues) {
        NSLog(@"1---%@", book.bookName);
    }
    NSDictionary *unarchivers = [dic extArchivierObjectClassType:[Book class] customType:YES];

    //修改book2
    Book *nb = dic.allValues.lastObject;
    nb.bookName = @"new bookName";
    
    //打印原来的books
    for (Book *book in dic.allValues) {
        NSLog(@"2---%@", book.bookName);
    }

    //打印解档的books
    for (Book *book in unarchivers.allValues) {
        NSLog(@"2---%@", book.bookName);
    }
}

7. 制作静态库.a

  • 创建静态库,名称:StaticLibrary
image.png
  • 将归档的分类文件拖进来(这里将生成的StaticLibrary.hStaticLibrary.m删除了)
    build phasescopy files添加.h
image.png
  • 切换debugrelease模式
image.png
  • 编译.a
image.png

得到不同架构的.a文件

image.png
  • 合并2个.a得到ArchiveFramework.a

lipo -create 静态库1的路径 静态库2的路径 -output 要生成的静态库路径+静态库名称

lipo -create ../Release-iphoneos/libStaticLibrary.a libStaticLibrary.a -output ArchiveFramework.a
image.png
  • .h.a拖入项目就可以调用了
image.png image.png

相关文章

  • 归档archive

    更新swift版本 加载 保存 自定义对象的归档,使用iOS11的API 自定义类Book,遵守NSSecureC...

  • tar 常用语法

    Tar(Tape ARchive,磁带归档的缩写) tar [OPTION]... (1) 创建归档 tar ...

  • Oracle归档日志

    显示归档日志信息 1,使用ARCHIVE LOG LIST命令可以显示日志操作模式,归档位置,自动归档机器要归档的...

  • 浅谈Oracle归档日志

    什么是归档日志 归档日志(Archive Log)是非活动的重做日志备份.通过使用归档日志,可以保留所有重做历史记...

  • 如何让通用的Xcode归档(generic Xcode arch

    如何让通用的Xcode归档(generic Xcode archive)更改为常用的app归档 你终于把代码调好了...

  • iOS归档(转)

    按下home后使用归档保存model数据,返回应用后解档恢复 iOS archive(归档)的总结 - 苹果吧 -...

  • oracle开启归档模式

    1:查看数据库归档模式是否开启archive log list; disabled说明数据库不是归档模式,则需要将...

  • Java之jar打包

    1、jar简介 Java归档文件格式(Java Archive, JAR)能够将多个源码、资源等文件打包到一个归档...

  • xcode常用打包上传

    1、使用xcode -> product -> archive进行归档打包,打包完成之后可以在Window -> ...

  • iOS archive(归档)的总结

    一、使用archiveRootObject进行简单的归档 使用NSKeyedArichiver进行归档、NSKey...

网友评论

      本文标题:归档archive

      本文链接:https://www.haomeiwen.com/subject/vtilqktx.html