OC中的内存管理机制

为什么要管理内存?

在开发中,为了让程序的内存消耗低,需要及时清理无用的对象,但是还要确保清理掉的对象不是游泳的,因此ocyou自己的内存管理机制,它可以及时回收一些不用等对象,避免内存泄漏。
理范围:任何继承NSObject的对象,对其他的基本数据类型无效。
oc中,变量存储在栈中,对象存在堆中,栈中的变量(基本数据类型)会有系统自动回收,这是在堆中的对象的内存空间是动态分配的,系统很难进行处理。如此一来,
对象依然占据着内存,越积越多,势必造成内存泄漏。
oc的内存申请和释放是一个循环的过程: 申请内存——对象初始化——使用对象——使用结束——释放内存——申请内存......

引用计数的原理

新版本的ios中,使用自动引用计数。引用计数的原理还是应该了解。
每个对象都有一个计数器,计数器的初始值为0,当生成一个对象时,计数器+1、持用对象时+1、释放对象-1、废弃对象后便回到0。当为0时对象销毁。总之, 判断对象要不要回收的唯一依据就是计数器是否为0,若不为0则存在。
不同的操作在ov中对应不同的方法:
1.当通过alloc或者new生成对象时, +(id)alloc 或 +(id)new
2.持有对象, -(id)retain
3.释放对象,-(void)release 
4.废弃对象,-(void)dealloc
对象的状态和引用计数值密切相关,想要在程序中获取当前的引用计数值,可以使用 retainCount方法来实现:-(NSUInteger)retainCount   

当对象被销毁时,系统会自动向对象发送一条dealloc消息,一般会重写dealloc方法,在这里释放相关的资源,dealloc就像是对象的“临终遗言”。一旦重写了dealloc方法就必须调用[super dealloc],并且放在代码块的最后调用(不能直接调用dealloc方法)。

一旦对象被回收了,那么他所占据的存储空间就不再可用,坚持使用会导致程序崩溃(野指针错误)。

相关概念

1. 野指针:指向一个已删除的对象或未申请访问受限内存区域的指针
2.僵尸对象:对象已经被释放了,还要强行使用对象,这时会产生野指针错误,被释放的对象就叫做僵尸对象。

既然不能访问,还要继续访问这个对象,会出现EXC_BAD_ACCESS的错误提示,为了防止这个对象继续被使用,需要对该对象进行清空操作: 对象名=nil;

3.自动释放池

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        
        Person *p1 = [[Person alloc]init];
        
    }
    return 0;
}

代码片段中   auto release pool  就是自动池。 其中@autoreleasepool用于声明一个自动释放池,花括号就是它的作用域,程序执行到结尾时,该自动释放池就会被销毁,并且其中的每个对象都会收到release消息。


自动引用计数——ARC

之前归纳了引用计数的原理,Xcode4.2后,都使用arc机制,不需要手动管理内存,编译器会自动持有和释放对象。arc是编译器都特性,不同于java中的垃圾回收机制。垃圾回收机制是运行时的特性:在运行的过程中发现不需要的东西就清理。而arc是编译器的特性:在编译时,哪里需要内存管理代码,就在哪自动插入。
ARC机制在使用时遵循以下原则:
1.retain、release、autuorelease、dealloc方法的调用由编译器生成
2.dealloc方法可以在子类中重写,但是不能被调用(不可以在dealloc方法中super)

强指针和弱指针

oc中的对象都是使用指针引用的,若没有指针的引用,对象会被自动销毁。oc中分强指针和弱指针两种。

1.强指针

arc机制能够自动完成对象的计数擦做,是因为arc遵循一定的引用规则:只要没有强指针指向的对象,对象就会被自动销毁,也就是说对象在内存中存在是因为有强指针的引用。强指针变量用关键字"__strong"修饰,默认情况下,使用强指针。

示例:
#import <Foundation/Foundation.h>

@interface Person : NSObject
@property (nonatomic,assign)int age;
@end
-------#import "Person.h"

@implementation Person
-(void)dealloc
{
    NSLog(@"%@被销毁",self);
    
}
@end

#import <Foundation/Foundation.h>
#include "Person.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *p = [[Person alloc]init];
        NSLog(@"-------");
        p=nil;
        NSLog(@"-------");
    }
    return 0;
}
------------
输出结果:2016-07-14 22:06:47.296 指针[815:66934] -------
2016-07-14 22:06:47.297 指针[815:66934] <Person: 0x100600080>被销毁
2016-07-14 22:06:47.297 指针[815:66934] -------
Program ended with exit code: 0

由此看出,使用强指针的对象会在代码执行完成后或者手动释放(=nil)后才销毁。

2.弱指针

定义弱指针使用关键字"__weak":
#import <Foundation/Foundation.h>
#include "Person.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
      __weak  Person *p = [[Person alloc]init];
        NSLog(@"-------");
        p=nil;
        NSLog(@"-------");
    }
    return 0;
}
------------
输出结果2016-07-14 22:12:39.837 指针[894:83676] <Person: 0x1004012e0>被销毁
2016-07-14 22:12:39.838 指针[894:83676] -------
2016-07-14 22:12:39.838 指针[894:83676] -------
Program ended with exit code: 0

弱指针在对象创建完成后就被释放了。weak指针存在是因为weak型的指针变量自动变为nil更加方便,这样阻止了weak指针继续已释放对象,避免产生也指针,预防了bug的产生。

@property属性特性

在面向对象中,属性特性可以用retain、copy、assign等来修饰。在内存管理中可以使用strong、weak来修饰。
strong:定义的是一种从属关系,当@property属性设置新值时,之前的值将被释放,保留新的。
weak:定义一种非从属关系,为@property属性重新设置新值时,既不保留新值,也不会释放之前的值。
1.控件用weak //weak一般用于耗内存的对象,这样可以快速释放掉不必要的内存,保证程序性能。
2.属性对象用strong
3. 非对象类型用assign
4>.字符串NSString用copy
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值