近期学习NSCoding
协议,发现很多小的问题,特把自己学习写的代码放到这里,供一起学习的参考一下,很简单,大神请绕过。
1. 首先定义了一Person
类,对其实现NSCoding
协议
**** .h文件 ****
#import <Foundation/Foundation.h>
@interface Person : NSObject<NSCopying>
@property(nonatomic,strong) NSString * name;
@property(nonatomic,strong) NSString * gender;
@property(nonatomic,strong) NSString * address;
@property(nonatomic) NSUInteger age;
-(instancetype)initWithName:(NSString*)name gender:(NSString*)gender address:(NSString*)adderss age:(NSUInteger)age;
+(instancetype) FactoryWithName:(NSString*)name gender:(NSString*)gender address:(NSString*)adderss age:(NSUInteger)age;
-(void)function;
**** .m文件 ****
#import "Person.h"
@implementation Person
-(instancetype)initWithName:(NSString *)name gender:(NSString *)gender address:(NSString *)adderss age:(NSUInteger)age{
if (self = [super init]) {
_name = name;
_gender = gender;
_address = adderss;
_age = age;
}
return self;
}
+(instancetype)FactoryWithName:(NSString *)name gender:(NSString *)gender address:(NSString *)adderss age:(NSUInteger)age{
return [[self alloc]initWithName:name gender:gender address:adderss age:age];
}
-(void)function{
NSLog(@"我是一个人");
}
//为了打印对象信息方便,从写了description方法
-(NSString*)description{
return [NSString stringWithFormat:@"name:%@ gender:%@ age:%lu address:%@",self.name,self.gender,(unsigned long)self.age,self.address];
}
//这里对NSCoding协议进行实现,由于返回一个对象,就需要创建一个对象并返回,
//这里使用[self class]获取类,而不是直接使用Person类进行创建,是为了它的
//子类实现协议时候,调用父类的方法,返回的是子类的对象而不是父类的对象。如果
//子类没有增加实例变量还好,如多增加,由于返回的是父类对象,由于不存在子类
//添加的属性,调用不存在或者为不存在的属性赋值会出错。下面子类再次说明本问题。
-(instancetype)copyWithZone:(NSZone *)zone{
return [[[self class] allocWithZone:zone] initWithName:[_name copy] gender:[_gender copy] address:[_address copy] age:_age];
}
@end
2.继承自Person
类创建Student
类
**** .h文件 ****
#import "Person.h"
@interface Student : Person
@property(nonatomic) NSUInteger score;
-(instancetype)initWithName:(NSString *)name gender:(NSString *)gender address:(NSString *)adderss age:(NSUInteger)age score:(NSUInteger)score;
+(instancetype)factoryWithName:(NSString *)name gender:(NSString *)gender address:(NSString *)adderss age:(NSUInteger)age score:(NSUInteger)score;
@end
**** .m文件 ****
#import "Student.h"
@implementation Student
-(instancetype)initWithName:(NSString *)name gender:(NSString *)gender address:(NSString *)adderss age:(NSUInteger)age score:(NSUInteger)score{
if (self = [super initWithName:name gender:gender address:adderss age:age]) {
_score = score;
}
return self;
}
+(instancetype)factoryWithName:(NSString *)name gender:(NSString *)gender address:(NSString *)adderss age:(NSUInteger)age score:(NSUInteger)score{
return [[self alloc]initWithName:name gender:gender address:adderss age:age score:score];
}
-(void)function{
NSLog(@"我是一名学生,我考了%lu",(unsigned long)self.score);
}
//这时候实现NSCoding协议可以继承父类的协议方法,也可以像父类那样重新
//写。如多继承父类的,如[super copyWithZone:zone],由于父类的方法使用的
//是[self class],这样[self class]结果便是Student类,[super copyWithZone:zone]
//结果便是Student的对象。
-(instancetype)copyWithZone:(NSZone *)zone{
Student* student = [super copyWithZone:zone];
student.score = _score;
return student;
}
-(NSString*)description{
return [[super description] stringByAppendingString:[NSString stringWithFormat:@" score:%lu",(unsigned long)_score]];
}
@end
3.我们创建一个School
类,里面有自定义Student
类,然后遵循NSCoding
协议
**** .h文件 ****
#import <Foundation/Foundation.h>
#import "Student.h"
@interface School : NSObject<NSCopying>
@property(nonatomic,strong) Student * student;
@property(nonatomic,strong) NSString * address;
-(instancetype)initWithAddress:(NSString*)address student:(Student*)student;
+(instancetype)factoryWithAddress:(NSString*)address student:(Student*)student;
@end
**** .m文件 ****
#import "School.h"
@implementation School
-(instancetype)initWithAddress:(NSString *)address student:(Student *)student{
if (self = [super init]) {
_address = address;
_student = student;
}
return self;
}
+(instancetype)factoryWithAddress:(NSString *)address student:(Student *)student{
return [[self alloc]initWithAddress:address student:student];
}
//这个时候由于我们的学生已经实现了本NSCoping协议,可以直接使用copy协议,
//深复制出一样的一个对象,原来对象修改,不影响复制出来的对象
-(instancetype)copyWithZone:(NSZone *)zone{
return [[[self class] allocWithZone:zone]initWithAddress:[_address copy] student:[_student copy]];
}
-(NSString*)description{
NSString* teacher = _teacher.description;
NSString* student = _student.description;
return [NSString stringWithFormat:@"\naddress:%@\nteacher:%@\nstudent:%@",_address,teacher,student];
}
@end
代码实例很简单,逻辑也是很简单的,需要注意 的地方在代码里都有注释,还有NSMutableCoping协议没有说,这个协议适合用在数组,字典等集合类型,看复制出来的对象是否可以变化。
-主要注意点
- [self class]代替直接写类
- [[[self class] allocWithZone:zone]initWithAddress:[_address copy] student:[_student copy]]
在协议里复制属性时候,使用本身的copy方法,不然会出现,复制出来的实例变量会跟随复制前对象的实例变量改变而改变。就是说一定要深复制属性,不是只复制实例变量的指针。
如果有错误的地方请指正,互相学习进步