一 IOS的内存管理数组
1.再IOS中对于每个对象都会有一个对象计数器性能
2.IOS内存管理分为三种(MRC:手动释放内存 autorelaese:自动释放内存 ARC:自动引用计数)编码
(1)MRC 黄金法则: 一旦对象被建立(new alloc init copy retain),那么就由建立者释放。总结:谁建立,谁释放,谁retain,谁release。其中 retain 计数器加一 release 计数器减一。atom
使用方式:Target-> 搜索auto -> 找到Automatic Reference Counting 将其修改为NOspa
如状况一.net
//实例化Person对象 此时计数器为 13d
Person *person1 = [[Person alloc]init];指针
//计数器加一rest
[person1 retain];code
//计数器减一
[person1 release];
//打印当前计数器的值
NSLog(@"%li",[person1 retainCount]);
如状况二
//若只是建立一个person的指针 则计数器为 0
Person *person;
// 由于计数器的release是针对于对象计数器而言的,此时没有对象,因此即便[person retain] 打印出的计数器的值永远为0
如状况三
//建立了一个Dog对象
Dog *dog = [[Dog alloc]init];
//给人设置狗对象后,狗被引用一次 , 此时dog的retainCount为2
[person1 setDog:dog];
//类的类属性,设置和获取,set和get,如今能够简便化:
//@property \ @synthesize
//noatomic 高性能 atomic 低性能
//retain 表明针对于这个对象计数器+1
//readonly 表明对象只读
//setter 、getter 更改这个方法的名字
//assign 赋值经过针对于简单的数据类型
//3.释放内存用dealloc,通常在.m文件中实现 [super dealloc],只要调用对象的release方法,就会进入dealloc;
//4.类的类属性,set和get,如今能够简化为:@property @synthesize
//noatomic 高性能 atomic 低性能 readonly 表明对象只读
//setter 、getter 更改这个方法的名字
//5.有内存管理,用retain OC语言的数据类型可内存管理
// 如 @property( nonatomic , retain ) Dog *dog;
无内存管理 用assign c语言的基础数据类型无内存管理
//如 @property( nonatomic , assign ) int age;
3.关于retainCount为1,-1,0,无穷大的条件
(1)为1时 是对象计数 当建立对象时或者对象即将释放时为1,即对象计数器最小为1.
(2)为0时 当一个指针的值为空时。
(3)为-1或无穷大时 当一个数据类型被赋值时。
不可变对象一般被称为静态常量,这类对象通常不能用于计数,而可变的对象是能够用来计数的
二.浅拷贝和深拷贝
1.浅拷贝 copy 一般指针对于指针进行拷贝,特色为:经过多个指针指向同一片内存地址。
如 NSString *string = @"123";
NSString *stringI = [string copy];
这时string和stringI输出的内存地址相同
2.深拷贝 mutableCopy 指的是赋值内容而且从新建立一块内存地址
如 NSString *stringII = [string mutableCopy];
这时string和stringII输出的内存地址不相同
三.自动释放池(autorelease)
1.autorelease一般有做用域,当在做用域范围内的建立特定的对象时,出去做用域计数器就会-1
如 @autorelease{
Person *personP = [[Person alloc]autorelease];
//特定的autorelease建立的对象才在出去做用域的时候release 计数器 -1
此时也能够在做用域里面对person retain或release,可是无论怎样,出做用域时计数器只会减一
}
四.ARC(自动引用计数)
1.ARC会追踪你的对象并决定哪个仍会使用而哪个不 会再用到
• 若是启用了ARC,编译器会自动插入retain和release 语句
• 经过Xcode启用或禁用可
2.ARC的特色
(1)不容许调用release,retain,retainCount
(2)容许重写dealloc,可是不容许调用[super dealloc]
(3)@property的参数:
• strong:至关于原来的retain(适用于OC对象),成员变量是强指针
• weak:至关于原来的assign,(适用于OC对象类型),成员变量是弱指针
• assign:适用于非OC对象类型(基础类型)
相互引用时注意的问题:
1.在一方的.h文件中要导入另外一方的头文件,另外一方的.h文件要引用@class name
如 #import <Foundation/Foundation.h>
#import "MicroBlog.h"
@interface Person : NSObject
#import <Foundation/Foundation.h>
@class Person;
@interface MicroBlog : NSObject
2.一方使用强指针,另外一方使用弱指针
3.引用@class的一方若要在.m文件中实现相应的方法,要在.m文件中再次导入另外一方的头文件
如 #import "MicroBlog.h"
#import "Person.h"
@implementation MicroBlog
ARC实例:
person.h
#import <Foundation/Foundation.h>
#import "MicroBlog.h"
@interface Person : NSObject
@property (nonatomic ,strong)MicroBlog *microBlog;
@property (nonatomic,strong) NSString *name;
@property (nonatomic,weak) NSString *comment;
-(void)printf;
@end
person.m
#import "Person.h"
@implementation Person
-(void)printf
{
NSLog(@"%@在%@发布了第%i条微博,内容是:%@",_name, [_microBlog time],[_microBlog second],[_microBlog content]);
}
@end
microBlog.h
#import <Foundation/Foundation.h>
@class Person;
@interface MicroBlog : NSObject
@property(nonatomic,weak) Person *person;
@property(nonatomic,weak) Person *commentPerson;
@property(nonatomic,weak) NSString *content;
@property(nonatomic,weak) NSString *time;
@property(nonatomic,assign) int second;
-(void)printComment;
@end
microBlog.m
#import "MicroBlog.h"
#import "Person.h"
@implementation MicroBlog
-(void)printComment
{
NSLog(@"%@评论了你的微博:%@",[_commentPerson name],[_commentPerson comment]);
}
@end
main.m
#import <Foundation/Foundation.h>
#import "MicroBlog.h"
#import "Person.h"
int main(int argc, const char * argv[]) {
Person *person = [[Person alloc]init];
person.name = @"小明";
Person *personI = [[Person alloc]init];
personI.name = @"小花";
personI.comment = @"赞👍";
MicroBlog *microBlog = [[MicroBlog alloc]init];
microBlog.content = @"暑假去旅游";
microBlog.second = 2;
NSDate *date = [NSDate date];
NSDateFormatter *dateformatter = [[NSDateFormatter alloc]init];
[dateformatter setDateFormat:@"yyyy-MM-dd HH-mm-ss"];
NSString *nowTime = [dateformatter stringFromDate:date];
microBlog.time = nowTime;
microBlog.commentPerson = personI;
//这是容易忘记的一步,要给person对象设置microBlog
person.microBlog = microBlog;
[person printf];
[microBlog printComment];
return 0;
}
五 KVC: key value coding 键值编码。
能够将对象属性变为一个键从而去设置属性的值
一.KVC的四种方法
1.setValue:forKey: 设置类属性的值
如: [hunter setValue:"光头强" forKey:"name"];
2.valueForKey: 取相对应的属性的值
如: [person valueForKey:@"name"]
3.setValue:forKeyPath: 根据键路径设置类属性的值
4.valueForKeyPath: 根据键路径取相对应的属性的值(对象属性是另外一个的类属性)
如: [person valueForKeyPath:@"hunterPig.weight"]
二.KVC中经常使用的几种计算方式
如:
//建立森林对象
Forest *forest = [[Forest alloc]init];
//把三只猪放到同一个数组中
NSArray *array = [boarI,boarIII,boarII,boarII];
//将存放猪的数组放入到森林数组(是森里类的一个属性)里 即完成了
[forest setValue:array forKey:"forestArray"];
1.count: 计算数量
//求猪的个数
NSLog("猪的个数是:%",[forest valueForKeyPath:"forestArray.@count"])
2.max: 计算最大值
//求猪重量的最大值
NSLog("猪的重量的最大值是:%",[forest valueForKeyPath:"forestArray.@max.weight"]);
3.min: 计算最小值
//求猪重量的最小值
NSLog("猪的重量的最小值是:%",[forest valueForKeyPath:"forestArray.@min.weight"]);
4.sum: 计算总和
//求猪重量的总和
NSLog("猪的重量的总值是:%",[forest valueForKeyPath:"forestArray.@sum.weight"]);
5.avg: 计算平均值
//求猪重量的平均值
NSLog("猪的重量的平均值是:%",[forest valueForKeyPath:"forestArray.@avg.weight"]);
三.针对数组
1. 自动去除数组重复的元素 distinctUnionOfObjects
NSArray *arr = [1,@2,@3,@2];
NSLog("数组里的元素有%@",[arr valueForKeyPath:"@distinctUnionOfObjects.self"]);
2. 不会自动去除数组多余的元素 @unionOfObjects
NSLog(@"数组里的元素有%@",[arrvalueForKeyPath:@"@unionOfObjects.self"]);
六 KVO: key value observing 当类属性的值发生改变时,会自动调用监听回调方法进行提醒
一:KVO中必有的三种方法
1.给对象添加监听者
[被监听者 addObserver:监听者 forKeyPath:@“类属性” options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
注意:被监听者和监听者能够是同一类实例化出的两个相同或不一样的对象,也能够是不一样类分别实例化出的对象
类属性能够是本身类的属性,也能够是对象类属性里面的属性
2.给对象移除监听者
[被监听者 removeObserver:监听者 forKeyPath:@"类属性"];
3.一旦类属性的值发生改变,监听回调如下方法
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
其中的四个属性:
keyPath :监听的key
object: 监听的对象
change: 返回新值和旧值(在添加监听者时须要设置)
context:上下文内容
它们的输出方式为:
NSLog("keyPath :%",keyPath);
NSLog("object :%",[object valueForKey:“类属性”]);
NSLog("change :%",change);
取出旧值:[change valueForKey:“old”];
取出新值:[change valueForKey:@“new”];
类属性值发生改变时是发生在添加和移除监听者之间的
举例说明KVO
人监听帐户里的帐户名和帐户余额属性
main.m
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Account.h"
int main(int argc, const char * argv[]) {
//实例化person对象
Person *person = [[Person alloc]init];
//实例化一个帐户
Account *account = [[Account alloc]init];
//给帐户设置余额和帐户名
[account setValue:@"200" forKey:@"money"];
[account setValue:@"123456" forKey:@"name"];
//给帐户添加监听者来监听它的余额
[account addObserver:person forKeyPath:@"money" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
//给帐户添加监听者来监听它的zhanghum
[account addObserver:person forKeyPath:@"name" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
//给帐户从新设置余额和帐户名
[account setValue:@"500" forKey:@"money"];
[account setValue:@"678954" forKey:@"name"];
//移除监听者
[account removeObserver:person forKeyPath:@"money"];
[account removeObserver:person forKeyPath:@"name"];
return 0;
}
person.m
#import "Person.h"
@implementation Person
//一旦被监听者的属性值发生改变,当即进入此方法
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
// NSLog(@"keyPath :%@",keyPath);
// NSLog(@"object :%@",[object valueForKey:@"money"]);
// NSLog(@"change :%@",change);
//当同时监听对象的多个属性时,输出改变值时须要进行判断
if ([keyPath isEqualToString:@"money"]) {
NSLog(@"您的帐户余额发生改变,当前金额为%@元",[object valueForKey:keyPath]);
NSLog(@"您当前余额总共有%i元",[[change valueForKey:@"old"]intValue] + [[change valueForKey:@"new"]intValue]);
}
else
if ([keyPath isEqualToString:@"name"]) {
NSLog(@"您的帐户名发生改变,当前帐户名为:%@",[object valueForKey:keyPath]);
}
}
@end