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***********