OC:属性的内部实现原理、dealloc内释放实例变量、便利构造器方法的实现原理、collection的内存管理
代码:
//
// main.m
#import <Foundation/Foundation.h>
#import "Person.h"
#import "SingleDog.h" int main(int argc, const char * argv[]) {
@autoreleasepool {
//改为工程为 非ARC 就是 MRC机制
Person * per = [[Person alloc]initWithName:@"lee" age:];
NSString * name = [[NSString alloc]initWithFormat:@"Li"];//为对象改名字
[per setName:name];
[per setName:name];//问题(多赋值了一次) B
[name release];//对应创建时候的 alloc 进行一次释放 E
NSLog(@"%@",[per name]);//这里出现野指针 A
NSString * na = @"Zhang";
[per setName:na];//C
} /**/
//自动释放池 用来存声明为 autorelease 的对象
//当自动释放池销毁时,会往池中的每一个对象(调用 autorelease 方法 的对象)(先进后出)发送一个 release 消息
@autoreleasepool {
Person * pp = [[Person alloc]init];
Person * pp2 = [[Person alloc]init];
Person * pp3 = [[Person alloc]init];
// [p autorelease];
@autoreleasepool {
//栈 ( LIFO 后进先出 )
//队列 先进先出( FIFO )
//自动释放池以 栈( LIFO ) 的方式来管理池中的对象
[pp retain];
[pp2 retain];
[pp3 retain];
[pp autorelease];//对象调用 autorelease 方法,当自动释放池销毁的时候,引用计数器减1
[pp2 autorelease];
[pp3 autorelease];
}
NSLog(@"内部释放池销毁");
}
NSLog(@"外部释放池销毁"); /*
@autoreleasepool {
//面试题
// for (long i = 0; i < 1000000000; i++) {
// Person * pp = [[Person alloc]init];
// [pp autorelease];
// }
//解决内存不足问题办法
for (long i = 0; i <10000000000000; i++) {
@autoreleasepool {
Person * pp = [[Person alloc]init];
[pp retain];
[pp autorelease];
}
}
}
*/ //copy
// copy 有深拷贝 和 浅拷贝 之分
//浅拷贝 只拷贝地址
//深拷贝 拷贝内容 新创建出一个对象
@autoreleasepool {
//
Person * one = [[Person alloc]initWithName:@"first" age:];
Person * two = [one copy];//直接 copy 一份
//如果是同一个地址就是 浅拷贝 如果不是同一个地址就是 深拷贝
NSLog(@"one %p",one);
NSLog(@"two %p",two);
NSLog(@"%lu %lu",one.retainCount,two.retainCount);
} //容器 (collection)的内存管理
//1.当集合中添加对象元素时,集合会对每一个元素做一次 retain 的操作,使其引用计数加 1
//2.当集合中移除某个元素的时候,集合会对其做一次 release 操作,使其引用计数器减 1
//3.当容器对象销毁的时候,会向容器内部的每一个元素的发送一个release 消息,使其引用计数器减 1
NSMutableArray * arr = [[NSMutableArray alloc]initWithCapacity:];
Person * p1 = [[Person alloc]init];
Person * p2 = [[Person alloc]init];
Person * p3 = [[Person alloc]init];
[arr addObject:p1];
[arr addObject:p2];
[arr addObject:p3];
for (Person * per in arr) {
NSLog(@"----%lu",per.retainCount);
}
[arr removeObject:p1];//这里我们移除一个对象 p1
NSLog(@"--%lu",p1.retainCount);
[arr removeAllObjects];//这里把所有的都释放掉
for (Person * per in arr) {
NSLog(@"--000--%lu",per.retainCount);
}
[arr release];//
p3 = nil;
NSLog(@"%lu",p3.retainCount); //便利构造器的内部内存管理
Person * person = [Person personWithName:@"wang" age:];
person.name = @"Hei"; return ;
}
main.m
//
// Person.h #import <Foundation/Foundation.h>
#import "SingleDog.h" @interface Person : NSObject<NSCopying>
//{
//// NSString * name; //只有在alloc 后才是一个对象,现在还是一个指针,是在栈区 D
//}
//属性的作用 自动生成setter getter
//copy只用于那些遵循 NSCopying协议的 ,retain 让计数器加1, 引用计数一定是对象,一定是在堆区
// assign 因为他不是对象,所以不用内存管理
@property (nonatomic,retain)NSString * name;
@property (nonatomic,assign)NSInteger age;
@property (nonatomic,retain) SingleDog * dog;
- (id)initWithName:(NSString *)name
age:(NSInteger)age;
- (void)test;
//便利构造器(的内存处理)
+ (Person *)personWithName:(NSString *)name
age:(NSInteger)age;
@end
person.h
//
// Person.m #import "Person.h" @implementation Person -(id)copyWithZone:(NSZone *)zone{
Person * per = [[Person allocWithZone:zone]init];//深拷贝copy
per.name = self.name;
per.age = self.age;
per.dog = self.dog;
return per;
}
@synthesize dog = _dog;//要自己写setter getter
-(void)setDog:(SingleDog *)dog{
if (_dog != dog) {
[_dog release];
_dog = [dog retain];//以上是内存处理
}
//这里可以设置自己设置的属性
} @synthesize name = _name;//这是我们要重新写setter getter的方法的时候,要用到,如果不需要重新写的话,就不用写这个方法
-(void)setNAme:(NSString *)name{
// _name = name ;
// [_name release];
if (_name != name) {//(这里是新对象) 判断是不是新的对象 B
[_name release];//。D (如果第一次初始化的时候,_name)如果还没有 E(原有的对象还没有释放) 保持对新的对象的所有权 C
//对一个字符串 多次release 不会 crash 因为他不在堆区 初次初始化的时候 name = nil,在栈区
_name = [name retain];//(让新对象引用计数器加1)(retain 保留所有权)解决野指针问题 A 该处的 retain 需要下面dealloc // retain 只是引用了对象的地址 copy 是拷贝对象(这里需要在学习) 如果对象的语义是 copy 这里就要写成_name = [name copy];
}
// _name = [name retain];//(retain 保留所有权)解决野指针问题 A
}
-(NSString *)name{
return [_name retain];
// return [_name copy];如果数据类型 为copy
// _age = age; 基本的数据类型 直接的赋值操作 语义为 assign
} - (void)setAge:(NSInteger)age{
_age = age;
} - (id)initWithName:(NSString *)name
age:(NSInteger)age{
self = [super init];//这里为什么这样写
if (self) {
// _name = name; 没有走 setter 方法
// _age = age;
self.name = name;
self.age = age;
}
return self;
}
//对象在销毁的时候会自动调用该方法(注意我们不能用对象直接去调用该方法)
-(void)dealloc{//一般对应于 语义属性为 retain copy 的, 注意:——》assign 的不会调用该方法(是直接的赋值 取值)
//在 MRC 下才要写这些方法 如果在 ARC 下就打不出来这些方法。 在dealloc 中需要对该类中语义属性为 retain copy 的属性生成的实例变量进行 release 操作
// [_name release];//与下面的作用是一样的(解决对象没有及时释放掉的)(这个方法建议不用)
self.name = nil;//在release 的时候 又把 指针置为 nil 防止出现野指针 好处是 内部调用了setter 方法 在 setter 方法内部进行了实例变量的 release 一次操作,同时将对象指向 nil
self.dog = nil;//处理狗的对象 所有的对象(有alloc retain的对象)在这里都要被销毁
[super dealloc ];//调用父类的方法将对象的空间真正回收
} //便利构造器(的内存处理)
+(Person * )personWithName:(NSString *)name
age:(NSInteger)age{
Person * per = [[Person alloc]initWithName:name age:age];
// [per release]; return per; //就相当于反回了一个野指针
// return per; [per release];//return 后面的代码不会执行
return [per autorelease];//既可以避免野指针,同时还可以避免内存泄露。。系统的内部的便利构造器的内存处理也是一样的
}
@end
person.m
//
// Student.h #import "Person.h" @interface Student : Person
@property (nonatomic,readwrite,assign)NSInteger stuNum;
@property(nonatomic,readwrite,copy)NSString * school;
@property(nonatomic,readwrite,copy)NSString *address; //初始化
-(id)initWithName:(NSString *)name
age:(NSInteger)age
// dog:(SingleDog*)dog
stunum:(NSInteger)stunum
school:(NSString *)school
address:(NSString *)address;
- (void)dealloc;
+(Student *)studentWithName:(NSString *)name
age:(NSInteger)age
stunum:(NSInteger)stunum
school:(NSString *)school
address:(NSString *)address;
@end
student.h
//
// Student.m #import "Student.h" @implementation Student -(id)initWithName:(NSString *)name
age:(NSInteger)age
// dog:(SingleDog*)dog
stunum:(NSInteger)stunum
school:(NSString *)school
address:(NSString *)address{
self = [super init];//一般进行初始化设置
if (self) {
self.name = name;
self.age =age;
self.stuNum = stunum;
self.school = school;
self.address = address;
}
return self;
}
- (void)dealloc{
self.name = nil;
self.school = nil;
self.address = nil;
[super dealloc];
} +(Student *)studentWithName:(NSString *)name
age:(NSInteger)age
stunum:(NSInteger)stunum
school:(NSString *)school
address:(NSString *)address{
Student * stu = [[Student alloc]initWithName:name age:age stunum:stunum school:school address:address];
return stu;
}
@end
student.m
//
// SingleDog.h #import <Foundation/Foundation.h> @interface SingleDog : NSObject @end
singleDog.h
//
// SingleDog.m #import "SingleDog.h" @implementation SingleDog @end
singleDog.h
//
// main.m
// Practice #import <Foundation/Foundation.h>
#import "Man.h"
#import "Woman.h"
#import "Family.h"
#import "Child.h" int main(int argc, const char * argv[]) {
@autoreleasepool {
// OC比较综合的一个练习 (本工程手动为 MRC)
Man * husband = [[Man alloc]initWithName:@"Lee" gender:@"man" age:];
Woman * wife = [[Woman alloc]init];
wife.age = ;
wife.gender = @"woman";
husband.wife = wife;//为丈夫设置一个媳妇
Family * family = [[Family alloc]init];
[family sayHi:husband];
[family sayHi:wife];
//多态,对一个方法传进去不同的值,反馈的结果不一样 对同一个方法的响应 回复的方法不一样
Child * ch = [[Child alloc]init];
/*
ch.delegate = husband;
ch.delegate = wife;
[husband release];// 孩子代理的语义属性问题 assign (避免代理的循环引用问题)
*/
//设置代理人
ch.delegate = husband;
[ch toGo];
ch.delegate = wife;//这里把上面的代理 husband 覆盖了
[ch toGo];
//一般一个类里设置一个代理
}
return ;
}
mian.m
//
// Person.h
// Practice #import <Foundation/Foundation.h> @interface Person : NSObject
@property(nonatomic,retain)NSString *name;
@property(nonatomic,retain)NSString *gender;
@property(nonatomic,assign)NSInteger age; - (id)initWithName:(NSString *)name
gender:(NSString *)gender
age:(NSInteger)age; - (void)dealloc;
@end
------------------------------------------------
person.h
//
// Person.m
// Practice #import "Person.h" @implementation Person - (id)initWithName:(NSString *)name
gender:(NSString *)gender
age:(NSInteger)age{
self = [super init];
if (self) {
self.name = name;
self.age = age;
self.gender = gender;
}
return self;
} - (void)dealloc{
self.name = nil;
self.gender = nil;
[super dealloc];
}
@end
person.m
//
// Family.h
// Practice #import <Foundation/Foundation.h>
#import "Person.h"
@class Man;
@class Woman;
@class Child; @interface Family : NSObject - (void)sayHi:(Person * )per;//自我介绍方法
@end
family.h
//
// Family.m
// Practice #import "Family.h"
#import "Man.h"
#import "Woman.h"
#import "Child.h" @implementation Family - (void)sayHi:(Person * )per{
NSLog(@"my name is %@ age is %ld gender is %@",per.name,per.age,per.gender);
}//自我介绍方法
@end
family.m
//
// Man.h
// Practice
//
//
#import "Person.h"
@class Woman;
//@class Child;
#import "Child.h" @interface Man : Person<TakecareDelegate>//3代理人遵循协议
//son wife
@property(nonatomic,retain)Child *son;
@property(nonatomic,retain)Woman *wife;
#pragma --------delegate----- - (void)playWithScore;
#pragma --内存释放--
- (void)dealloc;
@end
man.h
//
// Man.m
// Practice #import "Man.h"
#import "Woman.h"
#import "Child.h" @implementation Man @synthesize wife = _wife, son = _son; //setter getter
- (void)setWife:(Woman *)wife{
if (_wife != wife) {
[_wife release];
_wife = [wife retain];
// _wife = [_wife retain];//这是出错的方法,相当于_wife自己没有任何操作
}
_wife.name = @"Anni";//在这里做一些额外的操作
NSLog(@"my wife is %@",_wife.name);
}
- (Woman *)wife{
return [[_wife retain]autorelease];
} - (void)setSon:(Child *)son{
if (_son != son) {
[_son release];
_son = [son retain];
}
}
- (Child *)son{
return [[_son retain]autorelease];
} #pragma -----delegate---- - (void)playWithScore{
NSLog(@"踢足球");
}
#pragma ----内存释放-----
- (void)dealloc{
self.wife = nil;
self.son = nil;
[super dealloc];
}
@end
man.m
//
// Woman.h
// Practice #import "Person.h"
@class Man;
//@class Child;
#import "Child.h" @interface Woman : Person<TakecareDelegate>//3代理人遵循协议
//husband child
@property(nonatomic,retain)Man *husband;
@property(nonatomic,retain)Child *son;
#pragma -------delegate-----
- (void)getMeToSchool;
#pragma ---内存释放-----
-(void)dealloc;
@end
woman.h
//
// Woman.m
// Practice #import "Woman.h"
#import "Man.h"
#import "Child.h" @implementation Woman
#pragma ----delegate----
- (void)getMeToSchool{
NSLog(@"上学去");
}
#pragma ---内存释放----
-(void)dealloc{
self.son = nil;
self.husband = nil;
[super self];
}
@end
woman.m
//
// Child.h #import "Person.h"
@class Man;
@class Woman; //协议 (1)制定协议
@protocol TakecareDelegate <NSObject> - (void)getMeToSchool;
- (void)playWithScore; @end @interface Child : Person
//father mother
@property(nonatomic,retain)Man *father;
@property(nonatomic,retain)Woman *mother;
//协议 (2) 设置代理人 设置代理的语义属性 assign 主要是避免循环引用问题 (*****如果设置为 retain 在对应的 dealloc 方法里面)
@property(nonatomic,assign)id<TakecareDelegate>delegate; - (void)toGo; #pragma ---内存管理----
- (void)dealloc;
@end
child.h
//
// Child.m
// Practice #import "Child.h"
#import "Man.h"
#import "Woman.h" @implementation Child //通知代理去执行协议方法
- (void)toGo{
//下面是代理是父亲或者母亲单方(两个协议都执行了)
// if (_delegate) {
// [_delegate getMeToSchool];
// [_delegate playWithScore];
// } //下面是一个代理响应了某个方法,该代理就会去执行相对应的方法 (父母都为代理,分别执行一个协议)
//了解 respondsToSelector 方法(返回的是一个bool 数值) (看API 文档)
if (_delegate && [_delegate respondsToSelector:@selector(getMeToSchool)]) {//判断如果实现了 @selector(某方法) 下面就执行 某方法
[_delegate getMeToSchool];
}
if (_delegate && [_delegate respondsToSelector:@selector(playWithScore)]) {
[_delegate playWithScore];
}
}
#pragma -----内存管理------
- (void)dealloc{
self.mother = nil;
self.father = nil;
[super dealloc];
}
@end
child.m
Objective-C概述
面向过程 |
面向对象 |
|
特点 |
分析解决问题的步骤,实现函数,依次调用函数 |
分析某问题需要参与的对象,各对象的作用,多个对象协作完成任务 |
侧重点 |
实现功能 |
对象的设计 |
语言举例 |
C语言 |
OC、C++、Java等 |
OC:属性的内部实现原理、dealloc内释放实例变量、便利构造器方法的实现原理、collection的内存管理的更多相关文章
- Atitit paip.对象方法的实现原理与本质.txt
Atitit paip.对象方法的实现原理与本质.txt 对象方法是如何实现的1 数组,对象,字典1 对象方法是如何实现的 这显然是一个对象方法调用.但对象方法是如何实现的呢?在静态语言中,因为有编译 ...
- Python描述符以及Property方法的实现原理
Python描述符以及Property方法的实现原理 描述符的定义: 描述符是什么:描述符本质就是一个新式类,在这个新式类中,至少实了__get__(),__set__(),__delete__()中 ...
- new方法的实现原理
// // main.m // 04-new方法的实现原理 #import <Foundation/Foundation.h> #import "Person.h" # ...
- JVM源码分析之深入分析Object类finalize()方法的实现原理
原创申明:本文由公众号[猿灯塔]原创,转载请说明出处标注 “365篇原创计划”第十篇. 今天呢!灯塔君跟大家讲: 深入分析Object类finalize()方法的实现原理 finalize 如果 ...
- JavaScript内置一些方法的实现原理--new关键字,call/apply/bind方法--前戏
new关键字,call/apply/bind方法都和this的绑定有关,在学习之前,首先要理解this. 一起来学习一下this吧 首先.this是一个对象. 对象很好理解,引用类型值,可以实现如th ...
- JavaScript内置一些方法的实现原理--new关键字,call/apply/bind方法--实现
先学习下new操作符吧 new关键字调用函数的心路历程: 1.创建一个新对象 2.将函数的作用域赋给新对象(this就指向这个对象) 3.执行函数中的代码 4.返回这个对象 根据这个的思路,来实现一个 ...
- 【总结整理】js获取css的属性(内部,外部,内嵌(写在tag中))
在JS中需要获取某个元素的宽高或者是绝对定位的位置信息,通常我们会这么写: var elemWidth = elem.style.width; console.log(elemWidth); //(空 ...
- JavaScript内置一些方法的实现原理--Object.freeze()、instanceof
const定义的常量,一般是不能修改的. 比如: const TIME_OUT = 10000; 但是当值为引用类型值时,还是可以操作对象,扩展或修改对象属性.方法等等. 以下演示代码的操作是不会报错 ...
- jQuery 中 data 方法的实现原理
前言:jQuery 作为前端使用最多最广泛的 JS 库,其源码每个 JSer 都应该研究一下.早就打算看却一直被各种事拖着,上次某公司面试时被问到 jQuery 中 data 方法是如何实现的,结果答 ...
随机推荐
- 计算机网络——TCP/IP协议族详解
一.OSI七层协议体系结构域TCP/IP四层体系结构对比 ISO/OSI模型,即开放式通信系统互联参考模型(Open System Interconnection Reference Model),是 ...
- redo和undo的区别
转摘:http://blog.163.com/jing_playboy/blog/static/757362222012520104521864/ redo--> undo-->dat ...
- SSO单点登录在web上的关键点 cookie跨域
概述 其实WEB单点登录的原理挺简单的,抛开那些复杂的概念,简单来讲讲如何实现一个最基本的单点登录 首先需要有两个程序 例如:http://www.site-a.com 我们简称A http://ww ...
- Flex通信-与Java实现Socket通信实例
Flex通信-与Java实现Socket通信实例 转自:http://blessht.iteye.com/blog/1136888 博客分类: Flex 环境准备 [服务器端] JDK1.6,“ja ...
- linux下设置SSH无密码登陆
SSH配置 主机cloudgis22.edu.cn:192.168.3.21 主机cloudgis33.edu.cn:192.168.2.174 假设需要配置主机A无密码登录主机A,主机B,先确保所有 ...
- CSStickyHeaderFlowLayout collectionView headerView 悬浮
github:https://github.com/levyleo/CSStickyHeaderFlowLayout iOS 10 使用时会出现崩溃:https://github.com/CSStic ...
- 了解shell
1. shell 脚本文件第一行: #!/bin/sh 或 #!/bin/bash "#!" 又称为纪数,在执行bash脚本的时候,内核会根据它来确定该用哪个程序来解释脚本 ...
- What are some good resources for learning about Artificial Neural Networks
http://stackoverflow.com/questions/478947/what-are-some-good-resources-for-learning-about-artificial ...
- jquery让一个点击事件刷新页面就自己执行一次的方法
$('name')这个元素之前已经绑定过事件啦,(on绑定)然后直接调用下即可: $('name').click();
- ubuntu下设置开机自动挂载硬盘
我们在linux中常常用mount命令把硬盘分区或者光盘挂载到文件系统中./etc/fstab就是在开机引导的时候自动挂载到linux的文件系统. 如果给计算机配了一块新磁盘,已经分区,格式化,挂载, ...