iOS--可变数组、归解档、UISwich

1、可变数组:

1.最近在使用可变数组用copy修饰的时候,向数组中添加或者移除元素会导致崩溃。在查看原因的时候会发现可变数组已经变成了不可变数组。
NSMutableArray *thirdArray = [@[@"可变数组用copy修饰"] copy];
NSLog(@"thirdArray = %@", [thirdArray class]);
打印结果:
thirdArray = __NSSingleObjectArrayI
此时想要这样使用可变数组的话,如果是数组是属性,那么就要用strong关键字来修饰了。如果数组是局部变量,可以用mutableCopy来实现:
NSMutableArray *thirdArray = [@[@"可变数组用copy修饰"] mutableCopy];
2.将一个可变数组保存到本地,再次取值使用的时候,也会变为不可变数组,同样的向数组中添加或者移除元素会导致崩溃。
NSMutableArray *thirdArray = [@[@"可变数组用copy修饰"] mutableCopy];
    
    [[NSUserDefaults standardUserDefaults] setValue:thirdArray forKey:@"Array"];
    
    NSMutableArray *forthArray = [[NSUserDefaults standardUserDefaults] valueForKey:@"Array"];
forthArray = __NSSingleObjectArrayI

总结:所以在对可变数组做以上操作的时候,要注意他已经变成了不可变数组。

2、关于NSArray:

关于NSArray
一般在我们打印数组的class的时候,会看到如下四种情形,__NSArray0,__NSSingleObjectArrayI,__NSArrayI,__NSArrayM。
__NSArray0:表示该数组类型为不可变数组,数组中的元素个数为0。
__NSSingleObjectArrayI:表示该数组类型为不可变数组,数组中的元素个数为1。
__NSArrayI:表示该数组类型为不可变数组,数组中的元素个数至少是2个。
__NSArrayM:表示该数组类型为可变数组。

3、归档解档遇到的问题:

归档解档在数据持久化中,也是比较常用的。遵守NSCoding协议,实现
-(void)encodeWithCoder:(NSCoder *)aCoder、- (instancetype)initWithCoder:(NSCoder *)aDecoder两个方法即可。了解到的归档解档方法有两种,一种是正常的归档解档方式,另一种是使用runtime进行归档解档。两种方法都有用处,一般来说,一个类中如果只有常规的数据的话,那么使用runtime是最好的选择,但是如果一个类中,如果有引用自定义的类作为其属性的话,那么使用runtime进行归档解档就会报错。以一个Person类为例:Person.h文件
#import "MyModel.h"
#import "Head.h"
#import "Body.h"
#import "Leg.h"

@interface Person : MyModel

@property (nonatomic, strong) Head *head;

@property (nonatomic, strong) Body *body;

@property (nonatomic, strong) Leg *leg;

@property (nonatomic, copy) NSString *age;

@property (nonatomic, copy) NSString *name;

@end
Person.m文件:
//  自定义对象作为一个对象的属性时,无法使用runtime进行归解档

#import "Person.h"

@implementation Person

- (instancetype)initWithDictionary:(NSDictionary *)dic
{
    if (self = [super init]) {
        self.head = [[Head alloc] initWithDictionary:dic[@"head"]];
        self.body = [[Body alloc] initWithDictionary:dic[@"body"]];
        self.leg = [[Leg alloc] initWithDictionary:dic[@"leg"]];
        self.name = dic[@"name"];
        self.age = dic[@"age"];
    }
    return self;
}

- (instancetype)initWithCoder:(NSCoder *)aDecoder{
    if (self = [super init]) {
        if (self = [super init]) {
            self.head = [aDecoder decodeObjectForKey:@"head"];
            self.body = [aDecoder decodeObjectForKey:@"body"];
            self.leg = [aDecoder decodeObjectForKey:@"leg"];
            self.name = [aDecoder decodeObjectForKey:@"name"];
            self.age = [aDecoder decodeObjectForKey:@"age"];
        }
        
        return self;
    }
    
    return self;
}

-(void)encodeWithCoder:(NSCoder *)aCoder{
    [aCoder encodeObject:self.head forKey:@"head"];
    [aCoder encodeObject:self.body forKey:@"body"];
    [aCoder encodeObject:self.leg forKey:@"leg"];
    [aCoder encodeObject:self.name forKey:@"name"];
    [aCoder encodeObject:self.age forKey:@"age"];
}

再看Person类中的Head属性:Head.h文件
#import "MyModel.h"

@interface Head : MyModel

@property (nonatomic, copy) NSString *hair;
@property (nonatomic, copy) NSString *hairColor;

@end

Head.m文件

#import "Head.h"
#import 

@implementation Head
/**
 runtime快速归档
 */
-(void)encodeWithCoder:(NSCoder *)aCoder{
    unsigned int count;
    //获取属性列表
    Ivar *ivars = class_copyIvarList([Head class], &count);
    //遍历属性列表中的属性,并从中取值
    for (int i = 0; i < count; i++) {
        Ivar ivar = ivars[i];
        //获取属性名字
        const char *name = ivar_getName(ivar);
        NSString *propertyName = [NSString stringWithUTF8String:name];
        
        id value = [self valueForKey:propertyName];
        [aCoder encodeObject:value forKey:propertyName];
    }
    free(ivars);//释放属性列表
}
/**
 runtime快速解档
 */
- (instancetype)initWithCoder:(NSCoder *)aDecoder{
    if (self = [super init]) {
        unsigned count = 0;
        //获取属性列表
        Ivar *ivars = class_copyIvarList([Head class], &count);
        for (int i = 0;  i < count; i++) {
            //取出属性
            Ivar ivar = ivars[i];
            //获取属性的名字
            const char *name = ivar_getName(ivar);
            NSString *propertyName = [NSString stringWithUTF8String:name];
            //键取值
            id value = [aDecoder decodeObjectForKey:propertyName];
            [self setValue:value forKey:propertyName];
        }
        free(ivars);
    }
    
    return self;
}

归档解档使用方法
/**
 地址
 */
#define DocumentPath [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES)lastObject]
#define UserDataPath [DocumentPath stringByAppendingPathComponent:@"User.data"]
/**
 归解档
 */
- (void)arCharveData{
    Person *person = [[Person alloc] initWithDictionary:[self createJson]];
    person.name = @"老大";
    person.leg.leghair = @"蓝色";
    //存值
    [NSKeyedArchiver archiveRootObject:person toFile:UserDataPath];
    //取值
    Person *him = [NSKeyedUnarchiver unarchiveObjectWithFile:UserDataPath];
    //用值
    NSLog(@"him.name = %@   him.leg.leghair = %@", him.name, him.leg.leghair);
}

4、UISwich和UIButton:

我们在使用UIButton按钮点击选择和被选的时候,可以在点击事件中这样写:
- (void)buttonClick:(UIButton *)sender{
    sender.selected = !sender.selected;
}
但是在使用UISwich的时候会明显的感觉到不同:
UISwitch *swich = [[UISwitch alloc] init];
    [swich addTarget:self action:@selector(swichClick:) forControlEvents:UIControlEventValueChanged];

- (void)swichClick:(UISwitch *)swich{
//    swich.on = !swich.on;
    NSLog(@"**********%d***********", swich.on);
}

2018-08-28 20:01:22.411076+0800 UISwich[989:75422] **********1***********
在上述情况下,会打印一次,因为UIControlEventValueChanged,值只改变了一次。
- (void)swichClick:(UISwitch *)swich{
    swich.on = !swich.on;
    NSLog(@"**********%d***********", swich.on);
}
2018-08-28 20:02:11.242981+0800 UISwich[1079:106559] **********0***********
2018-08-28 20:02:11.243247+0800 UISwich[1079:106559] **********1***********
在上述情况下,会打印两次,因为UIControlEventValueChanged,值改变了2次。点击此处下载Demo。

你可能感兴趣的:(iOS--可变数组、归解档、UISwich)