美文网首页
iOS--可变数组、归解档、UISwich

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

作者: 乐逍遥的笔记 | 来源:发表于2018-08-28 20:02 被阅读44次

    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 <objc/runtime.h>
    
    @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

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