如何正确的自定义类

当我们自定义一个类的时候,要考虑到以下几个方面。
持久化保存、作为Hash的key、判断对象是否相等、对象的拷贝等

  • 首先持久化保存
    实现NSCoding协议,实现编码和解码的方法
    -(void)encodeWithCoder:(NSCoder *)aCoder;
    -(instancetype)initWithCoder:(NSCoder *)aDecoder;
存
 NSData *data = [NSKeyedArchiver archivedDataWithRootObject:user];
 [[NSUserDefaults standardUserDefaults] setObject:data forKey:@"user"]; 
 取
NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
NSData *data = [user objectForKey:@"user"];
User *user = [NSKeyedUnarchiver unarchiveObjectWithData:data];
  • 对象作为Dictonary的key,或者具有拷贝的功能,就要实现NSCopying协议和拷贝的方法,还要重写hash方法。
- (id)copyWithZone:(NSZone *)zone
{
    TestObj *obj = [[[self class] allocWithZone:zone] init];
    obj.identifier = self.identifier;
    obj.name = self.name;
    return obj;
}

作为字典中的key的时候,他会重新拷贝一份,所以需要遵守NSCopying协议,并实现拷贝方法,字典的value对存入的对象是强引用的,这个要注意。
-(void)setObject:(id)anObject forKey:(id )aKey;
根据这个方法可以看到akey必须遵守NSCopying协议。

  • 判断两个对象是否相等,或者要将我们自定义的对象添加到NSSet中或者作为字典的key的时候,需要经过hash计算,判断值在set中是否存在,判断值在字典中存储的位置。

重写

  • (NSUInteger)hash;
  • (BOOL)isEqual:(id)object;
- (BOOL)isEqual:(id)object {
    if (self == object) {  //  判断的是对象的地址
        return YES;
    }
    
    if (![object isKindOfClass:[Person class]]) {  //判断的是类型是否相同
        return NO; 
    }
    
    return [self isEqualToPerson:(Person *)object];
}

- (BOOL)isEqualToPerson:(Person *)person {
    if (!person) {  //  进入条件
        return NO;
    }
    
    BOOL haveEqualNames = (!self.name && !person.name) || [self.name isEqualToString:person.name];
    BOOL haveEqualBirthdays = (!self.birthday && !person.birthday) || [self.birthday isEqualToDate:person.birthday];
    
    return haveEqualNames && haveEqualBirthdays;  //  所有属性都满足相等才相等
}

- (NSUInteger)hash {
    return [self.name hash] ^ [self.birthday hash];
}

hash函数在对象被加入到set中,或者当成字典的key的时候被调用,如果两个对象的hash值是一样的,那么再进行的就是equal判断,如果两个函数返回都相等,则对象存在set或者字典中。

那么我们在实现类的时候

KeyValuePairs.h
#import   
  
@interface KeyValuePairs: NSObject   
@property (nonatomic,strong)NSString *identifier;  
@property (nonatomic,strong)NSString *name;  
  
@end 

KeyValuePairs.m
#import "KeyValuePairs.h"  
  
@implementation KeyValuePairs  
  
- (id)copyWithZone:(NSZone *)zone  
{  
    KeyValuePairs *kvp = [[[self class] allocWithZone:zone] init];  
    kvp.identifier = self.identifier;  
    kvp.name = self.name;  
    return kvp;  
}  
  
- (BOOL)isEqualToKeyValuePairs:(KeyValuePairs *)kvp{  
    if (!kvp) {  
        return NO;  
    }  
    BOOL haveEqualName = (!self.name && !kvp.name) || [self.name isEqualToString:kvp.name];  
    BOOL haveEqualIdentifier = (!self.identifier && !kvp.identifier) || [self.identifier isEqualToString:kvp.identifier];  
      
    return haveEqualName && haveEqualIdentifier;  
}  
  
#pragma mark -NSObject  
-(BOOL)isEqual:(id)object{  
    if (self == object) {  
        return YES;  
    }  
    if (![object isKindOfClass:[KeyValuePairs class]]) {  
        return NO;  
    }  
    return [self isEqualToKeyValuePairs:(KeyValuePairs *)object];  
}  
  
- (NSUInteger)hash {  
    return [self.name hash] ^ [self.identifier hash];  
}  
  -(void)encodeWithCoder:(NSCoder *)aCoder{
     
    [aCoder encodeObject:self. name forKey:@"name"];
    [aCoder encodeObject:self. identifier forKey:@"identifier"];
}

-(instancetype)initWithCoder:(NSCoder *)aDecoder{
    
    if(self = [super init]){
        
        self. identifier = [aDecoder decodeObjectForKey:@"identifier"];
        self. name = [aDecoder decodeObjectForKey:@"name"];

    }
    return self;
}
@end  
 

你可能感兴趣的:(如何正确的自定义类)