内存管理引用计数:
//
// Dog.h
// IOS150618_ObjectiveC_内存管理
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Dog : NSObject
{
NSString *_name;
NSInteger _age;
}
@property (copy,nonatomic)NSString *name;
@property (assign,nonatomic)NSInteger age;
@end
//
// Dog.m
// IOS150618_ObjectiveC_内存管理
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import "Dog.h"
@implementation Dog
@end
//
// main.m
// IOS150618_ObjectiveC_内存管理
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Dog.h"
//************************
//* *
//* 内存管理引用计数 *
//* *
//************************
//内存管理方式:
//自动引用计数 automatic reference counting
//手动引用计数 manual reference counting
//在building setting里搜索gar,-->bjective-C Automatic Reference Counting,-->yes<->no,可以修改引用类型为手动还是自动
int main(int argc, const char * argv[]) {
@autoreleasepool {
//以下是手动引用计数
Dog *dog = [[Dog alloc] init];
Dog *dog1 =[[Dog alloc ] init]; // 两个对象,不是同一块内存
NSLog(@"retainCount = %li,%p",dog.retainCount,dog);
NSLog(@"retainCount = %li,%p",dog1.retainCount,dog1);
//retain,对对象进项保留,增加对象的拥有权,使引用计数retainCount加1;
//retain的前提是该对象存在,
Dog *xiaoHei = [dog retain];
NSLog(@"retainCount = %li",xiaoHei.retainCount);
//直接指向一个对象,如Dog *xiaoHei = dog;这样的retainCount不加1,xiaoHei对该对象没有拥有权,
//有两个指针指向同一块内存,但是只有一个对象具有拥有权,释放的时候只能释放一次
Dog *xiaoBai = [xiaoHei retain];
NSLog(@"retainCount = %li,%p",dog.retainCount,xiaoHei);
NSLog(@"retainCount = %li,%p",dog1.retainCount,xiaoBai);
//release 释放对象拥有权,引用计数器的值减1
[xiaoHei release];
xiaoHei = nil;
NSLog(@"retainCount = %li",dog.retainCount);
[xiaoBai release];
xiaoBai = nil;
NSLog(@"retainCount = %li",dog.retainCount);
[dog release]; //最后一个对象释放这个对象的拥有权的时候系统会自动dealloc释放内存.(dealloc底层其实还是调用了C语言的free)
//但是不负责将内存清空,里面的值不会变,直到被其他对象重新申请这块内存.已经被释放的对象不能再向该对象发送消息
//故一般将对象释放之后会使其指向nil
dog = nil;
//该对象已经被释放了,不能再给对象发送消息
//NSLog(@"retainCount = %li",dog.retainCount);//这个做法是错误的
}
return 0;
}
setter方法的展开:
//
// Dog.h
// IOS150618_ObjectiveC_setter方法的展开
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Dog : NSObject
@end
//
// Person.m
// IOS150618_ObjectiveC_setter方法的展开
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import "Person.h"
@implementation Person
//copy展开
- (void)setName:(NSString *)name
{
if (_name != name) {
[_name release];
_name = [name copy];
}
}
//assign展开
- (void)setAge:(NSInteger)age
{
_age = age;
}
//retain展开
- (void)setDog:(Dog *)dog
{
if (_dog != dog) {
[_dog release];
_dog = [dog retain];
}
}
- (void)dealloc
{
[_name release];
[_dog release];
[super dealloc];
}
@end
//
// Person.h
// IOS150618_ObjectiveC_setter方法的展开
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Dog.h"
@interface Person : NSObject
@property (copy,nonatomic)NSString *name;
@property (assign,nonatomic)NSInteger age;
@property (retain,nonatomic)Dog *dog;
@end
// Person.m
// IOS150618_ObjectiveC_setter方法的展开
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import "Person.h"
@implementation Person
//copy展开
- (void)setName:(NSString *)name
{
if (_name != name) {
[_name release];
_name = [name copy];
}
}
//assign展开
- (void)setAge:(NSInteger)age
{
_age = age;
}
//retain展开
- (void)setDog:(Dog *)dog
{
if (_dog != dog) {
[_dog release];
_dog = [dog retain];
}
}
- (void)dealloc
{
[_name release];
[_dog release];
[super dealloc];
}
@end
dealloc方法的重写:
//
// Dog.h
// IOS150618_ObjectiveC_Dealloc
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Dog : NSObject
@end
// Dog.m
// IOS150618_ObjectiveC_Dealloc
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import "Dog.h"
@implementation Dog
//只有在手动管理的方式下才能重写dealloc
- (void)dealloc
{
NSLog(@"Dog release");
[super dealloc]; //要用父类的dealloc方法释放内存
}
@end
// main.m
// IOS150618_ObjectiveC_Dealloc
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Dog.h"
//*****************************
int main(int argc, const char * argv[]) {
@autoreleasepool {
Dog *dog = [[Dog alloc] init];
Dog *dog1 = [dog retain];
NSLog(@"retainCount = %li",dog1.retainCount);
Dog *dog2 = [dog1 retain];
NSLog(@"retainCount = %li",dog2.retainCount);
[dog release];
NSLog(@"retainCount = %li",dog1.retainCount);
[dog1 release];
NSLog(@"retainCount = %li",dog2.retainCount);
//最后一次release的时候,retainCount理论值为0,自动调用dealloc方法释放对象
//release只是释放对象的拥有权,而dealloc才是释放对象内存
[dog2 release];
//NSLog(@"retainCount = %li",dog1.retainCount);
}
return 0;
}
复合类的内存管理:
例1:
例子1:
//
// Person.h
// IOS150618_ObjectiveC复合类的内存管理
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Person : NSObject
//先release,再copy
@property (copy,nonatomic)NSString *firstName;
//先release,再retain
@property (retain,nonatomic)NSString *lastName;
//直接赋值
@property (assign,nonatomic)NSString *fullName;
@end
// Person.m
// IOS150618_ObjectiveC复合类的内存管理
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import "Person.h"
@implementation Person
//在当前类里面也要遵循内存管理法则,需要重写dealloc方法
- (void)dealloc
{
//要释放firstName和lastName,不释放会导致内存泄露.因为在@property中使用了copy和retain
NSLog(@"FirstName release!!");
[_firstName release];
NSLog(@"LastName release!!");
[_lastName release];
[super dealloc];
}
@end
// main.m
// IOS150618_ObjectiveC复合类的内存管理
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
// Person *xiaoHua = [[Person alloc] init];
// [xiaoHua release];
NSString *ss = [[NSString alloc ]initWithString:@"test"];
NSLog(@"%p",ss);
NSLog(@"retain = %li",ss.retainCount);
NSString *te = [ss copy];
NSLog(@"%p",te);
NSLog(@"retain = %li",ss.retainCount);
NSString *te1 = [ss retain];
NSLog(@"%p",te1);
NSLog(@"retain = %li",te1.retainCount);
}
return 0;
}
例2:
//
// Dog.h
// IOS150618_ObjectiveC复合类的内存管理_下
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Dog : NSObject
@property (copy,nonatomic)NSString *name;
@property (assign,nonatomic)NSInteger age;
@end
// Dog.m
// IOS150618_ObjectiveC复合类的内存管理_下
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import "Dog.h"
@implementation Dog
- (void)dealloc
{
NSLog(@"Dog is release:%@",[self class]);
[_name release];
[super dealloc];
}
@end
//
// Person.h
// IOS150618_ObjectiveC复合类的内存管理_下
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Dog.h"
@interface Person : NSObject
@property (retain,nonatomic)Dog *dog;
@end
// Person.m
// IOS150618_ObjectiveC复合类的内存管理_下
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import "Person.h"
@implementation Person
- (void)dealloc
{
NSLog(@"Person is release :%@",[self class]);
[_dog release];
[super dealloc];
}
@end
// main.m
// IOS150618_ObjectiveC复合类的内存管理_下
//
// Created by qianfeng on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *person = [[Person alloc] init];
Dog *dog1 = [[Dog alloc] init];
dog1.name = @"小黑";
person.dog = dog1;
[person release];
[dog1 release];
}
return 0;
}
例子3:
// Dog.h
// IOS150618_ObjectiveC复合类的内存管理_下1
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Dog : NSObject
@end
//
// Dog.m
// IOS150618_ObjectiveC复合类的内存管理_下1
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import "Dog.h"
@implementation Dog
@end
//
// Person.h
// IOS150618_ObjectiveC复合类的内存管理_下1
//
// Created by qianfeng on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Dog.h"
@interface Person : NSObject
{
Dog *_dog;
}
- (void)setDog:(Dog *)dog;
- (Dog *)dog;
@end
// Person.m
// IOS150618_ObjectiveC复合类的内存管理_下1
//
// Created by qianfeng on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import "Person.h"
@implementation Person
//方法一:直接赋值(不ok)
//- (void)setDog:(Dog *)dog
//{
// _dog = dog;
//}
//方法二:(不OK)
//- (void)setDog:(Dog *)dog
//{
// _dog = [dog retain]; //dog的retainCount加1,_dog之前指向的对象没有release,导致少释放一次
//}
//方法三:(不OK)
//- (void)setDog:(Dog *)dog
//{
// [_dog release]; //当dog和_dog是同一个对象时,_dog进行release时,
// //dog也被释放,则dog无法再retain
// _dog = [dog retain];
//}
//方法四:
- (void)setDog:(Dog *)dog
{
if (_dog != dog) {
[_dog release];
_dog = [dog retain];
}
}
- (Dog *)dog
{
return _dog;
}
- (void)dealloc
{
[_dog release];
[super dealloc];
}
@end
// main.m
// IOS150618_ObjectiveC复合类的内存管理_下1
//
// Created by qianfeng on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Dog.h"
#import "Person.h"
//**********************************
//* 复合类的内存管理(setter方法) *
//**********************************
int main(int argc, const char * argv[]) {
@autoreleasepool {
Dog *xiaoBai = [[Dog alloc] init];
Person *xiaoXin = [[Person alloc] init];
//方法一(不OK):xiaoXin并没有真正拥有这条狗,如果在main函数里[xiaoBai release],
//让xiaoBai的引用计数减1,就变为0,xiaoBai就销毁了.
//在Person类中的dealloc又release一次.同一个对象不能释放多次
// xiaoXin.dog = xiaoBai;
// [xiaoBai release];
// [xiaoXin release];
//方法二(不OK):如果人再持有别的狗,就会造成第一条狗得不到释放,内存泄露
// xiaoXin.dog = xiaoBai;
// NSLog(@"retainCount = %li",xiaoBai.retainCount); //retainCount = 2
// Dog *xiaoHei = [[Dog alloc] init];
// xiaoXin.dog = xiaoHei;
// [xiaoBai release];
// [xiaoHei release];
// [xiaoXin release];
//方法三(不OK):如果本来持有一条狗,又重新设置这条狗,先进行release,这个时候很可能dog就销毁了,然后就没法再次retain了.
xiaoXin.dog = xiaoBai;
Dog *xiaoHei = xiaoBai;
[xiaoXin release];
NSLog(@"xiaoHei retainCount = %li",xiaoHei.retainCount);
xiaoXin.dog = xiaoHei;
[xiaoXin release];
}
return 0;
}
字符串内存管理:
//
// main.m
// IOS150618_ObjectiveC_字符串的内存管理
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import <Foundation/Foundation.h>
//不用管计数retainCount的值,只要遵循内存管理法则就行
int main(int argc, const char * argv[]) {
@autoreleasepool {
//不可变字符串
NSString *str1 = @"Hello World";
NSLog(@"str1 retainCOunt = %li",str1.retainCount); //str1 retainCOunt = -1
NSString *str2 = [NSString stringWithString:str1];
NSLog(@"str2 retainCOunt = %li",str2.retainCount); //str2 retainCOunt = -1
NSLog(@"str1 = %p,str2 = %p",str1,str2); //str1 = 0x100001030,str2 = 0x100001030 因为两个都是不可变的常量,
//所以没必要再创建一个对象,而是直接将str1的地址传递给str2.(在数据段)
NSString *str3 = [[NSString alloc] initWithString:str1]; //alloc底层做了优化,判断是否创建一个可变的字符串对象,
//不可变的则直接将str1的地址给str3,没有创建新的对象
NSLog(@"str3 retainCount = %li",str3.retainCount);
NSLog(@"str1 = %p,str2 = %p,str3 = %p",str1,str2,str3); //str1 = 0x100001030,str2 = 0x100001030,str3 = 0x100001030
[str3 release]; //底层并没有调用free,因为其是一个常量,不在堆内存中
NSString *str4 = [str3 retain];
NSLog(@"str4 retainCOunt = %li",str4.retainCount);
[str4 release];
NSString *str5 = [str4 copy];
NSLog(@"str5 retainCOunt = %li",str5.retainCount);
NSLog(@"str4 = %p,str5 = %p",str4,str5); //str4 = 0x100001030,str5 = 0x100001030 并没有copy
[str5 release];
//可变字符串
NSMutableString *mulStr1 = [[NSMutableString alloc] initWithString:str5];
NSLog(@"nulStr1 retainCount = %li",mulStr1.retainCount);//ulStr1 retainCount = 1
NSLog(@"mulStr1 = %p,str5 = %p",mulStr1,str5); //mulStr1 = 0x100400040,str5 = 0x100001030
NSMutableString *mulStr2 = [mulStr1 retain];
NSLog(@"mulStr2 retainCount = %li",mulStr2.retainCount); //mulStr2 retainCount = 2
NSString *str6 = [[NSString alloc] initWithString:mulStr1];
NSLog(@"str6 retainCount = %li",str6.retainCount); //str6 retainCount = 1 str6被创建在堆内存
NSLog(@"str6 = %p",str6); //str6 = 0x100400820
NSString *str7 = [[NSString alloc] init];
NSLog(@"str7 retainCount = %li",str7.retainCount); //str7 retainCount = -1 str7被创建在栈内存,为空
NSLog(@"str7 = %p",str7); //str7 = 0x7fff79f35bd0
NSString *str8 = [str7 stringByAppendingString:@"Hello China"];//会在数据段查找该内容,若有相同的则直接返回该地址
NSLog(@"str8 retainCount = %li",str8.retainCount); //str8 retainCount = -1 str8被创建在数据段
NSLog(@"str8 = %p",str8); //str8 = 0x100001230
[str6 release];
[str7 release];
[str8 release];
[mulStr1 release];
[mulStr2 release];
}
return 0;
}
数组内存管理:
//
// Dog.h
// IOS150618_ObjectiveC数组的内存管理
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Dog : NSObject
@property (copy,nonatomic)NSString *name;
@end
//
// Dog.m
// IOS150618_ObjectiveC数组的内存管理
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import "Dog.h"
@implementation Dog
- (void)dealloc
{
[_name release];
[super dealloc];
}
@end
//
// main.m
// IOS150618_ObjectiveC数组的内存管理
//
// Created by qianfeng on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Dog.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
Dog *dog1 = [[Dog alloc] init];
Dog *dog2 = [[Dog alloc] init];
NSLog(@"%p",dog1); //0x1001145e0在堆内存
Dog *dog3 = [[Dog alloc] init];
Dog *dog4 = [[Dog alloc] init];
Dog *dog5 = [[Dog alloc] init];
Dog *dog6 = [[Dog alloc] init];
NSLog(@"dog1 retainCount = %li",dog1.retainCount); //dog1 retainCount = 1
NSMutableArray *dogs = [[NSMutableArray alloc] init];
//往数组中添加对象,对应对象的retainCount的值加1
[dogs addObject:dog1];
NSLog(@"dog1 retainCount = %li",dog1.retainCount); //dog1 retainCount = 2
[dogs addObject:dog1];
NSLog(@"dog1 retainCount = %li",dog1.retainCount); //dog1 retainCount = 3
[dogs addObject:dog2];
[dogs addObject:dog3];
[dogs addObject:dog4];
[dogs addObject:dog5];
[dogs addObject:dog6];
[dog1 release];
[dog2 release];
[dog3 release];
[dog4 release];
[dog5 release];
[dog6 release];
NSLog(@"dog1 retainCount = %li",dog1.retainCount); //dog1 retainCount = 2
//数组对象release,实际上是对数组中的每一个元素release一次
[dogs release];
}
return 0;
}
自动释放池:
//
// Dog.h
// IOS150618_ObjectiveC自动释放池
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Dog : NSObject
@property (assign,nonatomic)NSInteger age;
@end
//
// Dog.m
// IOS150618_ObjectiveC自动释放池
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import "Dog.h"
@implementation Dog
- (void)dealloc
{
NSLog(@"Dog is release");
[super dealloc];
}
@end
//
// main.m
// IOS150618_ObjectiveC自动释放池
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Dog.h"
int main(int argc, const char * argv[]) {
//自动释放池就是一个数组,自动释放池会将池中的所有对象都释放一次
@autoreleasepool {
Dog *xiaoHei = [[Dog alloc] init];
xiaoHei.age = 12;
[xiaoHei autorelease]; //将xiaoHei的拥有权交给自动释放池,xiaoHei失去对该对象的拥有权.
NSLog(@"retainCount = %li",xiaoHei.retainCount);
//运行结果:
//retainCount = 1
//Dog is release
//==============================
//NSMutableArray *array = [NSMutableArray alloc] init];
//[xiaoHei autorelease];相当于--->[array addObject:xiaoHei];
// [xiaoHei release];
} //运行到这个位置的时候,自动释放池会将里面的内容全部释放,(自动释放池相当于一个数组)
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
Dog *dog1 = [[Dog alloc] init];
dog1.age = 33;
NSLog(@"dog1 retainCount = %li",dog1.retainCount);
[dog1 retain];
NSLog(@"dog1 retainCount = %li",dog1.retainCount);
[dog1 autorelease];
NSLog(@"dog1 retainCount = %li",dog1.retainCount);
[dog1 autorelease];
[pool release];
return 0;
}
数组模拟实现自动释放池:
//
// Dog.h
// IOS150618_ObjectiveC数组模拟实现自动释放池
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Dog : NSObject
@end
//
// Dog.m
// IOS150618_ObjectiveC数组模拟实现自动释放池
//
// Created by Peng Junlong on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import "Dog.h"
@implementation Dog
- (void)dealloc
{
NSLog(@"dog is release");
[super dealloc];
}
@end
//
// main.m
// IOS150618_ObjectiveC数组模拟实现自动释放池
//
// Created by qianfeng on 15/6/18.
// Copyright (c) 2015年 Peng Junlong. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Dog.h"
int main(int argc, const char * argv[]) {
NSMutableArray *releasePool = [[NSMutableArray alloc] init]; //相当于@autoreleasepool{
Dog *dog1 = [[Dog alloc] init];
[releasePool addObject:dog1];
[dog1 release];
NSLog(@"dog1 retainCount = %li",dog1.retainCount);
Dog *dog2 = [[Dog alloc] init];
[releasePool addObject:dog2];
[dog2 release];
NSLog(@"dog2 retainCount = %li",dog2.retainCount);
Dog *dog3 = [[Dog alloc] init];
[releasePool addObject:dog3];
[dog3 release];
NSLog(@"dog3 retainCount = %li",dog3.retainCount);
[releasePool release]; //相当于}
return 0;
}