//
// main.m
// OC08,09_内存管理
//
// Created by dllo on 15/7/27.
// Copyright (c) 2015年 Clare. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Boy.h"
#import "Girl.h"
#import "Person.h"
int main(int argc, const char * argv[]) {
// Boy *boy = [[Boy alloc] init];
// Girl *girl = [[Girl alloc] init];
// girl.delegate = boy;
// [girl getMarry];
// 管理内存有三种方式
// 一:是垃圾回收,java中常见的管理内存的方法,系统来检测对象是否被使用,是否被释放
// 二:MRC手动管理引用计数,iOS管理内存的方式,程序员通过手动的方式来管理对象是否被释放
// 三:ARC自动管理引用计数,基于MRC,系统自动的管理内存,今后先使用MRC,培养管理内存的习惯
// 对象被创建出来之后他的引用计数retainCount就变成1
// Boy *boy = [[Boy alloc] init];
// NSLog(@"%ld",boy.retainCount);
//
// // retain:对对象的引用计数+1
// [boy retain];
// NSLog(@"%ld", boy.retainCount);
//
// [boy retain];
// [boy retain];
// NSLog(@"%ld", boy.retainCount);
// [boy release];
// NSLog(@"%ld", boy.retainCount);
// // 对对象的引用计数-1
// [boy release];
// NSLog(@"%ld", boy.retainCount);
// [boy release];
// NSLog(@"%ld", boy.retainCount);
// [boy release];
// NSLog(@"%ld", boy.retainCount);
// [boy release];
//
// NSLog(@"%ld", boy.retainCount);
// // 当对象的引用计数1 -> 0 的时候,会自动的调用dealloc方法,dealloc才是对应对象释放的方法
// // 当对象调用release的时候,它的引用计数是1,这个对象就不在对它的引用计数进行-1操作,而是直接调用dealloc方法,所以我们在访问对象的引用计数还是1
//
// // 如果多长对对象进行释放,会造成过度释放,过度释放也是最常见的内存问题,报错一般是lldb
// [boy release];
// NSArray *arr = @[@"1", @"2", @"3", @"4"];
// NSLog(@"%ld", arr.retainCount);
//
// NSString *str = @"11111";
// NSLog(@"%ld", str.retainCount);
// NSLog(@"%u", 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);
// NNString 的对象在全局静态区,它的引用计数是-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);
// // 自动释放池
// // 只要对象用autoreleasepool释放会把对象放入到系统自动释放池中,等出了池子的范围,对象引用计数自动-1,这个相当于java的垃圾回收,对象释放由系统来管理
// @autoreleasepool {
// [boy autorelease];
// NSLog(@"%ld", boy.retainCount);
// }
// NSLog(@"%ld", boy.retainCount);
// 内存管理的原则:加多少,对应减多少,加减做到平衡
// 对象的所有权:拥有所有权的对象都可以对他进行release
//
// Boy *b = [Boy boy];
// [b retain];
// NSLog(@"%ld", b.retainCount);
// [b release];
// 对象如果是我们进行alloc或者retain之后我们就获取了对象的所有权,就可以对对象进行release操作
// 便利构造器在返回对象的时候会加上一个autorelease,所以用便利构造器创建对象不需要对内存进行管理
// NSArray *arr1 = [[NSArray alloc] initWithObjects:@"1", @"2", nil];
// NSArray *arr2 = [NSArray arrayWithObjects:@"1", @"2", nil];
// id是泛指型指针,可以用在任何的方法中,但是instancetype代表实例类型,用在自定义初始化方法,便利构造器作为返回值类型使用,标识方法会返回一个对象回去
// NSArray *arr = @[@"1", @"2", @"3", @"4"];
// NSLog(@"%ld", arr.retainCount);
// // NSArray *newArr = [arr copy];
// NSArray *newArr = [NSArray arrayWithArray:arr];
// NSLog(@"%@", newArr);
// NSLog(@"%ld", newArr.retainCount);
//
// // 不可变 ->可变
// NSMutableArray *arr1 = [NSMutableArray arrayWithArray:arr];
// NSMutableArray *arr2 = [arr mutableCopy];
// [arr2 addObject:@"5"];
// NSLog(@"%@", arr2);
// NSDictionary *dic = @{@"1":@"2", @"3":@"4"};
// NSMutableDictionary *muDic = [dic mutableCopy];
// NSLog(@"%@", muDic);
// 系统的类要是实现拷贝的功能,必须先签订拷贝NSCopying的协议,然后实现对应的方法
// 不可变的数组字典可以通过mutableCopy转换成可变的数组字典
// mutableCopy出来的对象是可变的,copy是不可变的
// Boy *boy = [Boy boyWithname:@"叶寒" hobby:@"巫妖战"];
// Boy *newBoy = [boy copy];
// NSLog(@"%@", newBoy.name);
//
// // 如果自己的类想要实现copy的功能,就必须先签订NSCopying,然后实现对应的协议方法,initWithZone,之后就可以使用copy的功能
//
// // boy newBoy
// NSLog(@"%ld", boy.retainCount);
// NSLog(@"%ld", newBoy.retainCount);
// copy也可以改变引用计数,但是它改变的是新对象的引用计数,而原先的对象计数不变
// Boy *boy1 = [[Boy alloc] init];
// [boy1 retain];
// [boy1 retain];
// NSLog(@"%ld", boy1.retainCount);
// NSMutableArray *arr = [NSMutableArray arrayWithObjects:boy1, nil];
// NSLog(@"%ld", [boy1 retainCount]);
//
// [arr removeObjectAtIndex:0];
// NSLog(@"%ld", boy1.retainCount);
// // 当对象放入到容器Array或者字典中,对象会被容器进行一次持有,就是retain一次,他的引用计数会加一,主要是为了防止空指针的问题
// // 等对象从容器中移除掉之后,相应的会-1
//
// Boy *b = [[Boy alloc] init];
// // 当对象加入到数组中的时候,对象使用完了消失,一旦加入到数组中,立即释放
// NSArray *arr1 = [NSArray arrayWithObjects:b, nil]; // 最后对象随着数组释放
// [b release]; // 对应的是alloc减1
// 自己alloc几次自己一定要release几次还有retain也是只要是自己写的就要对应release
// 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);
Person *per = [[Person alloc] initWithName:@"星辰" age:40];
[per.arr addObject:@"1"];
NSLog(@"%@", per.arr);
return 0;
}
//
// Boy.h
// OC08,09_内存管理
//
// Created by dllo on 15/7/27.
// Copyright (c) 2015年 Clare. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Girl.h"
@interface Boy : NSObject<GirlDelegate, NSCopying>
@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;
+ (Boy *)boy;
@end
//
// Boy.m
// OC08,09_内存管理
//
// Created by dllo on 15/7/27.
// Copyright (c) 2015年 Clare. 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*可以在任何方法中使用
// instancetype只能在实例中使用只能在alloc和init使用,即只能在便利构造器使用或者是自定义初始化中使用
//- (instancetype);
- (id)copyWithZone:(NSZone *)zone
{
Boy *b = [Boy allocWithZone:zone];
b.hobby = _hobby;
b.name = _name;
return b;
}
- (instancetype)initWithName:(NSString *)name
hobby:(NSString *)hobby
{
self = [super init];
if (self) {
self.name = name;
self.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 = [name retain]; // 然后再对_那么进行retain
// }
[name retain];
[_name release];
_name = name;
}
@end
//
// Girl.h
// OC08,09_内存管理
//
// Created by dllo on 15/7/27.
// Copyright (c) 2015年 Clare. All rights reserved.
//
#import <Foundation/Foundation.h>
// 1.声明协议
@protocol GirlDelegate <NSObject>
@required // 必须执行的
- (void)married;
@optional // 可执行可不执行
- (void)cook;
@end
@interface Girl : NSObject
// 声明代理人属性
@property(nonatomic, assign)id<GirlDelegate>delegate;
- (void)getMarry;
@end
//
// Girl.m
// OC08,09_内存管理
//
// Created by dllo on 15/7/27.
// Copyright (c) 2015年 Clare. All rights reserved.
//
#import "Girl.h"
@implementation Girl
- (void)getMarry
{
[self.delegate cook];
}
@end
//
// Person.h
// OC08,09_内存管理
//
// Created by dllo on 15/7/27.
// Copyright (c) 2015年 Clare. 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;
//
// Person.m
// OC08,09_内存管理
//
// Created by dllo on 15/7/27.
// Copyright (c) 2015年 Clare. 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;
// _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];
[super dealloc];
}
@end
@end