先奉上demo的地址
https://github.com/MyHZ/HZCoding.git
使用cocoapods
pod 'NSObject+HZCoding'
我們?cè)陂_發(fā)中存儲(chǔ)數(shù)據(jù)的時(shí)候,經(jīng)常要用的就是歸檔和解檔,我們會(huì)在需要操作的對(duì)象所在的類中實(shí)現(xiàn)兩個(gè)方法粉铐。
-(void)encodeWithCoder:(NSCoder *)aCoder;
-(instancetype)initWithCoder:(NSCoder *)aDecoder;
在這兩個(gè)方法中乃摹,我們會(huì)分別調(diào)用如下兩個(gè)方法對(duì)每個(gè)屬性進(jìn)行操作
- (void)encodeObject:(nullable id)objv forKey:(NSString *)key;
- (nullable id)decodeObjectForKey:(NSString *)key;
當(dāng)然還有其他類型的
- (void)encodeBool:(BOOL)boolv forKey:(NSString *)key;
- (void)encodeInt:(int)intv forKey:(NSString *)key;
然后將需要存儲(chǔ)的屬性 一個(gè)一個(gè)的寫進(jìn)去,而且其中的key又是NSString類型勇劣,我們還要保證 歸檔和解檔時(shí) key是一致的。
上面的方法,是我們一貫的做法拥诡。
開發(fā)中,當(dāng)有一兩個(gè)屬性的時(shí)候(如下)氮发,很簡單渴肉,幾句話復(fù)制一下,再改屬性和key值爽冕。
@property(nonatomic,copy) NSString *name;
@property(nonatomic,assign) int age;
但是我們?cè)趯?shí)際開發(fā)中仇祭,當(dāng)然不止有這一兩個(gè)屬性,也不只是NSString和int類型颈畸,我們難道要復(fù)制 屬性個(gè)數(shù) * 2 遍嗎乌奇?
@property(nonatomic,assign) int age;
@property(nonatomic,assign) int age1;
@property(nonatomic,assign) int age2;
@property(nonatomic,assign) int age3;
當(dāng)然没讲,有人愿意做,那這也是沒辦法礁苗,有耐心爬凑,但是出錯(cuò)了,就有的受了寂屏。
接下來贰谣,我們就用runtime來實(shí)現(xiàn) 歸檔解檔
1.我們新建一個(gè)Person類,最重要的當(dāng)然是需要
<NSCoding>協(xié)議了
@interface Person : NSObject<NSCoding>
@property(nonatomic,copy) NSString *name;
@property(nonatomic,assign) int age;
@property(nonatomic,assign) int age1;
@property(nonatomic,assign) int age2;
@property(nonatomic,assign) int age3;
@end
重點(diǎn)在于:runtime
首先是 歸檔
Peroson.m中
-(void)encodeWithCoder:(NSCoder *)aCoder
{
unsigned int count = 0;
Ivar *ivars = class_copyIvarList([Person class], &count);
for (int i = 0; i < count; i++) {
Ivar ivar = ivars[i];
const char *name = ivar_getName(ivar);
NSString *key = [[NSString alloc]initWithUTF8String:name];
[aCoder encodeObject:[self valueForKey:key] forKey:key];
}
}
class_copyIvarList 獲的所有的屬性
我們通過runtime獲取到所有的屬性名(name)迁霎,
然后得到我們需要?dú)w檔時(shí)用到的key(NSString *key)吱抚,
再使用 KVC 獲得歸檔時(shí)用到的encodeObject ([self valueForKey:key] key在剛才已經(jīng)得到了),
//歸檔:
[aCoder encodeObject:[self valueForKey:key] forKey:key];
解檔
-(instancetype)initWithCoder:(NSCoder *)aDecoder
{
self = [super init];
if (self) {
unsigned int count = 0;
Ivar *ivars = class_copyIvarList([Person class], &count);
for (int i = 0; i < count; i++) {
Ivar ivar = ivars[i];
const char *name = ivar_getName(ivar);
NSString *key = [[NSString alloc]initWithUTF8String:name];
id value = [aDecoder decodeObjectForKey:key];
[self setValue:value forKey:key];
}
}
return self;
}
核心部分(獲取屬性名 key)都是和歸檔是一樣的考廉,在接檔的時(shí)候秘豹,同樣是使用KVC 獲得屬性值 [self setValue:value forKey:key];
接下來,我們就可以直接使用Person 類了
歸檔
Person *person = [Person new];
person.name = @"zhangsan";
person.age = 18;
NSString *temp = NSTemporaryDirectory();
temp = [temp stringByAppendingPathComponent:@"zhangsan.plist"];
[NSKeyedArchiver archiveRootObject:person toFile:temp];
解檔
NSString *temp = NSTemporaryDirectory();
temp = [temp stringByAppendingPathComponent:@"zhangsan.plist"];
Person *person = (Person *)[NSKeyedUnarchiver unarchiveObjectWithFile:temp];
NSLog(@"%@ %d",person.name,person.age);
到此昌粤,就算是完成了Person的歸檔和解檔既绕。
好吧,我又該但是了涮坐,我們肯定也不只是Person 這一個(gè)類吧凄贩,然后每個(gè)類再復(fù)制一次?那當(dāng)然不是了袱讹。
我們會(huì)有更簡單的方法
1.首先
我們新建一個(gè)NSObject的類別
寫兩個(gè)方法
NSObject+HZCoding
@interface NSObject (HZCoding)
-(void)HZ_encode:(NSCoder *)aCoder;
-(void)HZ_decode:(NSCoder *)aDecoder;
@end
2.接下來 我們?cè)?m中導(dǎo)入
#import <objc/message.h>
3.然后我們實(shí)現(xiàn)上面的兩個(gè)方法
-(void)HZ_encode:(NSCoder *)aCoder
{
unsigned int count = 0;
Ivar *ivars = class_copyIvarList([self class], &count);
for (int i = 0; i < count; i++) {
Ivar ivar = ivars[i];
const char *name = ivar_getName(ivar);
NSString *key = [[NSString alloc]initWithUTF8String:name];
[aCoder encodeObject:[self valueForKey:key] forKey:key];
}
}
-(void)HZ_decode:(NSCoder *)aDecoder
{
unsigned int count = 0;
Ivar *ivars = class_copyIvarList([self class], &count);
for (int i = 0; i < count; i++) {
Ivar ivar = ivars[i];
const char *name = ivar_getName(ivar);
NSString *key = [[NSString alloc]initWithUTF8String:name];
id value = [aDecoder decodeObjectForKey:key];
[self setValue:value forKey:key];
}
}
@end
4.把我們之前寫的Person的那段代碼刪掉疲扎,我們重新搞Person
-(void)encodeWithCoder:(NSCoder *)aCoder
{
}
-(instancetype)initWithCoder:(NSCoder *)aDecoder
{
}
畢竟我們?cè)贜SObject+HZCoding已經(jīng)定義了那些個(gè)實(shí)現(xiàn)的方法,而我們的類 都是繼承自NSObject的捷雕,那我們直接在自己的類中調(diào)用NSObject的方法椒丧,不是更方便嘛。
上代碼
導(dǎo)入
#import "NSObject+HZCoding.h"
-(void)encodeWithCoder:(NSCoder *)aCoder
{
[self HZ_encode:aCoder];
}
-(instancetype)initWithCoder:(NSCoder *)aDecoder
{
if (self = [super init]) {
[self HZ_decode:aDecoder];
}return self;
}
好了救巷,這樣子又方便了一些壶熏,幾句話就完成了,我們每個(gè)類只需要導(dǎo)入之前的類別(NSObject+HZCoding)浦译,調(diào)用里面的方法棒假,就可以完成了。
你們猜精盅,有但是沒有帽哑?
還有
但是 我們還是嫌麻煩,每個(gè)類還是要重新寫這幾行字渤弛,我不想寫啊。
接下來也不算是黑魔法甚带,也不是什么高大上的萬一她肯,我們用宏定義佳头,把這段話給定義好,用到的時(shí)候晴氨,直接宏定義調(diào)用不就好了康嘉。
在NSObject+HZCoding.h里面 我們定義下面的內(nèi)容
#define HZCodingImplementation \
-(void)encodeWithCoder:(NSCoder *)aCoder\
{\
[self HZ_encode:aCoder];\
}\
-(instancetype)initWithCoder:(NSCoder *)aDecoder\
{\
if (self = [super init]) {\
[self HZ_decode:aDecoder];\
}return self; \
}
接下來就是關(guān)鍵的代碼了
重新回到我們的Person類
導(dǎo)入 #import "NSObject+HZCoding.h"
實(shí)現(xiàn):HZCodingImplementation
然后Person.m的代碼就變了這樣子
#import "Person.h"
#import "NSObject+HZCoding.h"
@implementation Person
HZCodingImplementation
@end
使用的方法,是不是越來越簡單了籽前。
總結(jié) 總結(jié) 總結(jié)
總結(jié) 總結(jié) 總結(jié)
用到的時(shí)候直接新建一個(gè)NSObject的類別亭珍,將NSObject+HZCoding里面的內(nèi)容復(fù)制進(jìn)去就好了。
寫的有點(diǎn)亂了枝哄,記住用法就好了
協(xié)議 <NSCoding>
導(dǎo)入 #import "NSObject+HZCoding.h"
宏定義HZCodingImplementation
OK 就是這么多了
講的麻煩 肄梨,不如直接看demo了
利用runtime獲取對(duì)象的所有屬性(值),所有方法
http://www.reibang.com/p/24ff360c0e94