• iOS OC08,09_内存管理


    //管理内存有三种方式,
        //1.是垃圾回收,java常见的管理内存的方法,系统来检測对象是否被使用,是否被释放
        //2.MRC手动管理引用计数,iOS管理内存的方式,程序猿通过手动的方式来管理对象是否被释放
        //3.ARC自己主动管理引用计数,基于MRC,系统自己主动的管理内存,以后我们还是先使用MRC,培养管理内存的习惯
    
    //
    //  Girl.h
    //  OC08,09_内存管理
    //
    //  Created by dllo on 15/7/27.
    //  Copyright (c) 2015年 zhozhicheng. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    //1.声明协议
    @protocol GirlDelegate <NSObject>
    
    @required
    -(void)married;
    
    @optional
    -(void)cook;
    @end
    
    @interface Girl : NSObject
    //2.声明代理人属性
    @property(nonatomic,assign)id<GirlDelegate>delegate;
    
    -(void)getMarry;
    
    
    @end
    
    
    
    
    
    
    
    //
    //  Girl.m
    //  OC08,09_内存管理
    //
    //  Created by dllo on 15/7/27.
    //  Copyright (c) 2015年 zhozhicheng. All rights reserved.
    //
    
    #import "Girl.h"
    
    @implementation Girl
    -(void)getMarry{
        [self.delegate cook];
    }
    
    @end
    
    //
    //  Boy.h
    //  OC08,09_内存管理
    //
    //  Created by dllo on 15/7/27.
    //  Copyright (c) 2015年 zhozhicheng. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    #import "Girl.h"
    @interface Boy : NSObject<GirlDelegate,NSCopying>
    
    -(void)dealloc;
    
    +(Boy*)boy;
    
    @property(nonatomic,retain)NSString *name;
    @property(nonatomic,copy)NSString *hobby;
    @property(nonatomic,retain)Girl *girls;
    
    //自己定义的初始化方法
    -(instancetype)initWithName:(NSString *)name
                          hobby:(NSString *)hobby;
    +(Boy *)boyWithName:(NSString *)name
                  hobby:(NSString *)hobby;
    
    @end
    
    
    
    
    //
    //  Boy.m
    //  OC08,09_内存管理
    //
    //  Created by dllo on 15/7/27.
    //  Copyright (c) 2015年 zhozhicheng. All rights reserved.
    //
    
    #import "Boy.h"
    
    @implementation Boy
    
    
    -(void)cook{
        NSLog(@"做饭吃");
    }
    
    -(void)dealloc{
        NSLog(@"对象被释放了");
    
        //把成员变量全部+1操作全部减去
        [_name release];
        [_girls release];
        [_hobby release];
    
        [super dealloc];
    }
    
    
    +(Boy*)boy{
        Boy *b=[[Boy alloc] init];
        return [b autorelease];
    }
    //id是void *
    //id是泛型指针,能够用在不论什么方法中,可是instancetype代表实例类型,用在自己定义初始化方法,便利构造器作为返回值类型使用,标识方法会返回一个对象回去
    //-(instancetype)init{
    //   Boy *b=[[Boy alloc] init];
    //    return [b autorelease];
    //}
    
    - (id)copyWithZone:(NSZone *)zone{
        Boy *b=[Boy allocWithZone:zone];
    
        b.hobby=_hobby;
        b.name=_name;
        return b;
    
    }
    
    
    
    -(instancetype)initWithName:(NSString *)name
                          hobby:(NSString *)hobby{
        [super self];
        if (self) {
            self.name=name;   //从直接赋值变成方法赋值
            _hobby=hobby;
        }return self;
    }
    
    
    +(Boy *)boyWithName:(NSString *)name
                  hobby:(NSString *)hobby{
        Boy *b=[[Boy alloc] initWithName:name hobby:hobby];
        //写便利构造器最后别忘了autorelease
        return [b autorelease];
    }
    
    
    -(void)setName:(NSString *)name{
        if(_name!=name);
        [_name release];
        _name=[name retain];
    }
    
    
    
    @end
    
    
    
    
    

    对象被创建出来之后他的引用计数retainCount就变成1

    Boy *boy=[[Boy alloc] init];
    NSLog(@"%ld",boy.retainCount);

    结果

    2015-07-27 17:47:40.331 OC08,09_内存管理[1562:152231] 1

    //对对象的引用计数进行+1的操作

    // //retain:对对象的引用计数进行+1

    Boy *boy=[[Boy alloc] init];
    NSLog(@"%ld",boy.retainCount);
    [boy retain];
    NSLog(@"%ld",boy.retainCount);
    [boy retain];
    [boy retain];
    NSLog(@"%ld",boy.retainCount);
    

    结果

    2015-07-27 17:50:13.304 OC08,09_内存管理[1571:153537] 1
    2015-07-27 17:50:13.305 OC08,09_内存管理[1571:153537] 2
    2015-07-27 17:50:13.305 OC08,09_内存管理[1571:153537] 4

    //release:对对象的引用计数进行-1的操作

    [boy release];
    NSLog(@"%ld",boy.retainCount);
    [boy release];
    [boy release];
    [boy release];
    NSLog(@"%ld",boy.retainCount);

    结果

    2015-07-27 17:54:44.714 OC08,09_内存管理[1580:155505] 1
    2015-07-27 17:54:44.715 OC08,09_内存管理[1580:155505] 对象被释放了
    2015-07-27 17:54:44.715 OC08,09_内存管理[1580:155505] 1

    凝视

    //     //假设多次对对象进行释放,会造成过度释放,过度释放也是最常见的内存问题(+1次数小于-1次数)
    //    //[boy release];
    //    //当对象的引用计数1->0时,会自己主动调用dealloc方法,dealloc才是相应对象释放的方法
    //当对象调用release的时候,他的引用计数是1,这个对象就不再对他的引用计数进行-1操作,而是直接调用dealloc方法,所以我们在訪问对象引用计数还是1

    几个不同类型retain值

    NSArray *arr=@[@"1",@"2",@"3",@"4"];
    NSLog(@"%ld",arr.retainCount);
    
    NSString *str=@"1111";
    NSLog(@"%ld",str.retainCount);
    
    NSMutableString *str2=[NSMutableString stringWithString:@"111111"];
    NSLog(@"%ld",str2.retainCount);
    
    NSDictionary *dic=@{@"1":@"2",@"3":@"4"};
    NSLog(@"%ld",dic.retainCount);
    NSLog(@"%p",str);
    NSLog(@"%p",str2);
    

    结果

    2015-07-27 17:56:31.134 OC08,09_内存管理[1587:156279] 1
    2015-07-27 17:56:31.134 OC08,09_内存管理[1587:156279] -1
    2015-07-27 17:56:31.135 OC08,09_内存管理[1587:156279] 1
    2015-07-27 17:56:31.135 OC08,09_内存管理[1587:156279] 1
    2015-07-27 17:56:31.135 OC08,09_内存管理[1587:156279] 0x100002130
    2015-07-27 17:56:31.135 OC08,09_内存管理[1587:156279] 0x100112ac0

    凝视

    NSString 的对象在全局静态区,他的引用计数是-1,代表正整数的最大值,其它的对象都在堆区,

    Boy *boy=[[Boy alloc] init];
    [boy retain];
    [boy retain];
    NSLog(@"%ld",boy.retainCount);
    //release立即会把对象的引用计数-1,可是autorelease会延迟对对象的计数-1
    [boy release];
    NSLog(@"%ld",boy.retainCount);
    [boy autorelease];
    NSLog(@"%ld",boy.retainCount);
    //自己主动释放池
    //仅仅要对象用autorelease释放会把对象放入到系统的自己主动释放池中,等出了池子范围,对象引用计数自己主动-1,这个相当于java的垃圾回收,对象释放由系统来管理
     @autoreleasepool {
     [boy autorelease];
     NSLog(@"%ld",boy.retainCount);
     }NSLog(@"%ld",boy.retainCount);

    结果

    2015-07-27 19:00:44.667 OC08,09_内存管理[1602:162429] 3
    2015-07-27 19:00:44.668 OC08,09_内存管理[1602:162429] 2
    2015-07-27 19:00:44.668 OC08,09_内存管理[1602:162429] 2
    2015-07-27 19:00:44.668 OC08,09_内存管理[1602:162429] 2
    2015-07-27 19:00:44.668 OC08,09_内存管理[1602:162429] 1

    // 内存管理原则:加多少减多少,加减做到平衡,减多了过度释放,降低了没有得到释放

    //对象的全部权:拥有全部权的对象能够对他进行release

    Boy *b=[Boy boy];
    [b retain];
    NSLog(@"%ld",b.retainCount);
    [b release];

    结果

    2015-07-27 19:05:11.838 OC08,09_内存管理[1610:164027] 2
     //便利构造器在返回对象的时候会加上一个autorelease,所以用便利构造器创建对象不须要对内存进行管理
    NSArray *arr1=[[NSArray alloc] initWithObjects:@"1",@"2", nil];
    NSArray *arr2=[NSArray arrayWithObjects:@"1",@"2",nil];
    [arr1 release];
        NSArray *arr=@[@"1",@"2",@"3",@"4"];
        NSArray *newArr=[NSArray arrayWithArray:arr];
        NSLog(@"%@",newArr);
        NSLog(@"%ld",arr.retainCount);
        NSLog(@"%ld",newArr.retainCount);
    

    结果

    2015-07-27 19:07:04.008 OC08,09_内存管理[1624:164855] (
        1,
        2,
        3,
        4
    )
    2015-07-27 19:07:04.009 OC08,09_内存管理[1624:164855] 1
    2015-07-27 19:07:04.010 OC08,09_内存管理[1624:164855] 1

    //把一个不可变的变成可变的

    NSArray *arr=@[@"1",@"2",@"3",@"4"];
    NSMutableArray *arr1=[NSMutableArray arrayWithArray:arr];
    
    NSMutableArray *arr2=[arr mutableCopy];
    [arr2 addObject:@"5"];
    NSLog(@"%@",arr2);
    
    
    NSDictionary *dic=@{@"1":@"2",@"3":@"4"};
    NSMutableDictionary *dic1=[dic mutableCopy];
    NSLog(@"%@",dic1);

    结果

    2015-07-27 19:08:34.111 OC08,09_内存管理[1633:165509] (
        1,
        2,
        3,
        4,
        5
    )
    2015-07-27 19:08:34.112 OC08,09_内存管理[1633:165509] {
        1 = 2;
        3 = 4;
    }

    凝视

    //系统的类要是实现copy功能,必须先签订拷贝NSCopying协议,然后实现相应的方法
    //不可变的数组字典能够通过mutableCopy转换成可变的数组字典
    //mutableCopy出来的对象可变,copy是不可变的

    举例

    Girl Boy文件

    //
    //  Girl.h
    //  OC08,09_内存管理
    //
    //  Created by dllo on 15/7/27.
    //  Copyright (c) 2015年 zhozhicheng. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    //1.声明协议
    @protocol GirlDelegate <NSObject>
    
    @required
    -(void)married;
    
    @optional
    -(void)cook;
    @end
    
    @interface Girl : NSObject
    //2.声明代理人属性
    @property(nonatomic,assign)id<GirlDelegate>delegate;
    
    -(void)getMarry;
    
    
    @end
    
    
    //
    //  Girl.m
    //  OC08,09_内存管理
    //
    //  Created by dllo on 15/7/27.
    //  Copyright (c) 2015年 zhozhicheng. All rights reserved.
    //
    
    #import "Girl.h"
    
    @implementation Girl
    -(void)getMarry{
        [self.delegate cook];
    }
    
    @end
    
    
    
    
    //
    //  Boy.h
    //  OC08,09_内存管理
    //
    //  Created by dllo on 15/7/27.
    //  Copyright (c) 2015年 zhozhicheng. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    #import "Girl.h"
    @interface Boy : NSObject<GirlDelegate,NSCopying>
    
    -(void)dealloc;
    
    +(Boy*)boy;
    
    @property(nonatomic,retain)NSString *name;
    @property(nonatomic,copy)NSString *hobby;
    @property(nonatomic,retain)Girl *girls;
    
    //自己定义的初始化方法
    -(instancetype)initWithName:(NSString *)name
                          hobby:(NSString *)hobby;
    +(Boy *)boyWithName:(NSString *)name
                  hobby:(NSString *)hobby;
    
    @end
    
    
    
    
    
    //
    //  Boy.m
    //  OC08,09_内存管理
    //
    //  Created by dllo on 15/7/27.
    //  Copyright (c) 2015年 zhozhicheng. All rights reserved.
    //
    
    #import "Boy.h"
    
    @implementation Boy
    
    
    -(void)cook{
        NSLog(@"做饭吃");
    }
    
    -(void)dealloc{
        NSLog(@"对象被释放了");
    
        //把成员变量全部+1操作全部减去
        [_name release];
        [_girls release];
        [_hobby release];
    
        [super dealloc];
    }
    
    
    +(Boy*)boy{
        Boy *b=[[Boy alloc] init];
        return [b autorelease];
    }
    //id是void *
    //id是泛型指针,能够用在不论什么方法中,可是instancetype代表实例类型,用在自己定义初始化方法,便利构造器作为返回值类型使用,标识方法会返回一个对象回去
    //-(instancetype)init{
    //   Boy *b=[[Boy alloc] init];
    //    return [b autorelease];
    //}
    
    - (id)copyWithZone:(NSZone *)zone{
        Boy *b=[Boy allocWithZone:zone];
    
        b.hobby=_hobby;
        b.name=_name;
        return b;
    
    }
    
    
    
    -(instancetype)initWithName:(NSString *)name
                          hobby:(NSString *)hobby{
        [super self];
        if (self) {
            self.name=name;   //从直接赋值变成方法赋值
            _hobby=hobby;
        }return self;
    }
    
    
    +(Boy *)boyWithName:(NSString *)name
                  hobby:(NSString *)hobby{
        Boy *b=[[Boy alloc] initWithName:name hobby:hobby];
        //写便利构造器最后别忘了autorelease
        return [b autorelease];
    }
    
    
    -(void)setName:(NSString *)name{
        if(_name!=name);
        [_name release];
        _name=[name retain];
    }
    
    
    @end
    

    执行

    //Boy类使用Copy的方法
     Boy *boy=[Boy boyWithName:@"张阳阳" hobby:@"玩"];
     Boy *newBoy=[boy copy];
     NSLog(@"%@",newBoy.name);
     //假设自己的类想要实现copy功能,就必须先签订NSCopying协议,然后实现相应的协议方法,initWithZone,之后就能够使用copy的功能
     NSLog(@"%ld",boy.retainCount);
     NSLog(@"%ld",newBoy.retainCount);

    结果

    2015-07-27 19:13:02.102 OC08,09_内存管理[1644:168242] 张阳阳
    2015-07-27 19:14:15.390 OC08,09_内存管理[1653:168927] 1
    2015-07-27 19:14:15.390 OC08,09_内存管理[1653:168927] 1
        Boy *boy1=[[Boy alloc] init];
        [boy1 retain];
        [boy1 retain];
        NSLog(@"%ld",boy1.retainCount);
        NSMutableArray *arr=[NSMutableArray arrayWithObjects:boy1, nil];
        NSLog(@"%ld",[arr[0] retainCount]);
    

    结果

    2015-07-27 19:14:52.821 OC08,09_内存管理[1660:169279] 3
    2015-07-27 19:14:52.822 OC08,09_内存管理[1660:169279] 4

    凝视

    // 当对象放入到容器Array或者字典中,对面会被容器进行一次持有,就是retain一次,他的引用计数会+1,主要是为了防止空指针的问题
    // //等对象从容器移除掉之后,相应的会-1

        Boy *b=[[Boy alloc] init];
        Girl *girl=[[Girl alloc]init];
        b.girls=girl;
        NSLog(@"%ld",girl.retainCount);
    
        Girl *girl2=[[Girl alloc] init];
        b.girls=girl2;
        NSLog(@"%ld",girl.retainCount);
    

    结果

    2015-07-27 19:16:00.235 OC08,09_内存管理[1667:169909] 2
    2015-07-27 19:16:00.236 OC08,09_内存管理[1667:169909] 1

    一个完整的类写法

    //
    //  Person.h
    //  OC08,09_内存管理
    //
    //  Created by dllo on 15/7/27.
    //  Copyright (c) 2015年 zhozhicheng. All rights reserved.
    //
    
    #import <Foundation/Foundation.h>
    
    @interface Person : NSObject
    
    @property(nonatomic,retain)NSMutableArray *arr;
    @property(nonatomic,copy)NSString *name;
    @property(nonatomic,assign)NSInteger age;
    
    
    -(id)initWithName:(NSString *)name
                  age:(NSInteger)age;
    
    +(Person *)personWithName:(NSString *)name
                          age:(NSInteger)age;
    
    
    @end
    
    //
    //  Person.m
    //  OC08,09_内存管理
    //
    //  Created by dllo on 15/7/27.
    //  Copyright (c) 2015年 zhozhicheng. All rights reserved.
    //
    
    #import "Person.h"
    
    @implementation Person
    
    -(id)initWithName:(NSString *)name
                  age:(NSInteger)age{
        self=[super init];
        if (self) {
            self.name=name;
            self.age=age;
            //对象创建之后,里面的数组也会创建好,不用在外面进行创建,避免由于忘了,造成问题
            self.arr=[NSMutableArray array];
        }return self;
    }
    
    +(Person *)personWithName:(NSString *)name
                          age:(NSInteger)age{
        Person *per=[[Person alloc] initWithName:name age:age];
        return [per autorelease];
    
    }
    -(void)dealloc{
        [_arr release];
        [_name release];
        //age是栈区的,我们操作的是堆区
    }
    
    
    @end
    
        Person *per=[[Person alloc] initWithName:@"张阳阳" age:20];
        [per.arr addObject:@"1" ];
        NSLog(@"%@",per.arr);

    结果

    2015-07-27 19:18:09.427 OC08,09_内存管理[1675:171354] (
        1
    )
  • 相关阅读:
    三种构建器的使用
    java class file
    JVM知识(下)
    JVM知识(上)
    初识JMM
    nginx基础配置加基础实战演示
    GitHub中webhooks的使用
    redis sentinel介绍
    redis主从复制
    【开源】.net 分布式架构之监控平台
  • 原文地址:https://www.cnblogs.com/cxchanpin/p/7257085.html
Copyright © 2020-2023  润新知