Objective-C----MRC内存管理 、 自动释放池 、 面向对象三大特性及封装 、 继承 、 组合与聚合
1 MRC练习
1.1 问题
引用计数是Objective-C语言采用的一种内存管理技术,当一个对象被创建在堆上后,该对象的引用计数就自动设置为1,如果在其它对象中的对象成员需要持有这个对象时,则该对象的引用计数被加上1,此时如果该对象被释放,内存管理程序将首先把该对象的引用计数减1,然后判断该对象的引用计数是否为0,由于其它对象在持有该对象时将引用计数加了1,所以此时该对象的引用计数减1后不为0,则内存管理程序将不会释放该对象。直到持有该对象的其它对象也被释放时,该对象的引用计数再次减1,变为0时,该对象在堆上所占的存储空间才被释放。
引用计数技术的使用能够实现对资源的自动管理。
iOS5.0开始引入自动引用计数技术,iOS7.0以后则默认使用自动引用计数技术。自动引用计数技术,简称为ARC,由于ARC的出现,相对以前的方式被称为手动引用计数技术,简称为MRC。
1.2 方案
本案例是强制使用MRC(手动引用计数技术)来管理对象的引用计数的一个练习。由于iOS7.0以后使用Xcode创建的工程默认使用ARC(自动引用计数技术),所以需要强制转换回MRC。转换的方法如下步骤:
首先,创建一个工程,然后选择“工程导航”中的“工程项”,如图-1所示:

图-1
然后在右边窗口中选择Build Settings,如图-2所示:

图-2
下一步选择All选项,如图-3所示:

图-3
最后,向下滚动屏幕,找到Apple LLVM 5.1 – Language – Objective C中的Objective-C Automatic Reference Counting,将右边的选项选择为NO。如图-4所示:

1.3 步骤
实现此案例需要按照如下步骤进行。
步骤一:定义Integer类
首先,在Day03工程中新添加Integer.h文件,用于定义新的类Integer。
代码如下所示:
- #import <Foundation/Foundation.h>
- @interface Integer : NSObject
- @property int integer;
- -(void)print;
- @end
在上述代码中,为Integer类添加一个属性,整型变量integer;然后为Integer类添加一个方法print,用于将属性的值输出到控制台。
然后,在类Integer的实现部分,即在Integer.m文件中,添加print方法的实现。代码如下所示:
- #import "Integer.h"
- @implementation Integer
- -(void)print
- {
- NSLog(@"%d", self.integer);
- }
- @end
步骤二: 查看初始引用计数值
在Day03工程中新添加MRC.m文件,用于主程序,在主程序中定义Integer的对象并查看该对象的引用计数。此时对象的引用计数值为1。
代码如下所示:
- #import <Foundation/Foundation.h>
- #import "Integer.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- // insert code here...
- Integer *int1 = [[Integer alloc] init];
- NSLog(@"%ld", [int1 retainCount]);
- }
- return 0;
- }
上述代码中,以下代码:
- NSLog(@"%ld", [int1 retainCount]);
retainCount消息将得到对象int1当前的引用计数值。
步骤三:增加引用
在主程序中添加另一个引用,再查看该对象的引用计数。此时对象的引用计数值不会发生变化,仍然为1。
代码如下所示:
- #import <Foundation/Foundation.h>
- #import "Integer.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- // insert code here...
- Integer *int1 = [[Integer alloc] init];
- NSLog(@"%ld", [int1 retainCount]);
- Integer *int2 = int1;
- NSLog(@"%ld", [int1 retainCount]);
- }
- return 0;
- }
上述代码中,以下代码:
- Integer *int2 = int1;
仅仅是定义了一个指针,将其初始化为int1,这将不会改变对象int1的引用计数值。
步骤四:增加引用计数
由于此时有两个指针指向对象int1,int1的引用计数应该变为2。但在MRC下,要想将int1的引用计数值加1,必须手动添加retain消息才能实现。
代码如下所示:
- #import <Foundation/Foundation.h>
- #import "Integer.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- // insert code here...
- Integer *int1 = [[Integer alloc] init];
- NSLog(@"%ld", [int1 retainCount]);
- Integer *int2 = int1;
- NSLog(@"%ld", [int1 retainCount]);
- [int2 retain];
- NSLog(@"%ld", [int1 retainCount]);
- }
- return 0;
- }
上述代码中,以下代码:
- [int2 retain];
- NSLog(@"%ld", [int1 retainCount]);
是向对象int2发送消息retain,该消息会使int2指向的对象的引用计数加1,由于int2与int1共同指向一个对象,所以向对象int1发送retainCount消息,得到的值为2。
步骤五:减少引用计数
在MRC下,要想将int1的引用计数值减1,必须手动添加release消息才能实现。
代码如下所示:
- #import <Foundation/Foundation.h>
- #import "Integer.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- // insert code here...
- Integer *int1 = [[Integer alloc] init];
- NSLog(@"%ld", [int1 retainCount]);
- Integer *int2 = int1;
- NSLog(@"%ld", [int1 retainCount]);
- [int2 retain];
- NSLog(@"%ld", [int1 retainCount]);
- [int2 release];
- NSLog(@"%ld", [int1 retainCount]);
- }
- return 0;
- }
上述代码中,以下代码:
- [int2 release];
- NSLog(@"%ld", [int1 retainCount]);
是向对象int2发送消息release,该消息会使int2指向的对象的引用计数减1,由于int2与int1共同指向一个对象,所以向对象int1发送retainCount消息,得到的值为1。
步骤六:释放对象
在MRC下,如果int1的引用计数值减1后值为0,则内存管理程序将把int1所占的内存空间释放掉。
代码如下所示:
- #import <Foundation/Foundation.h>
- #import "Integer.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- // insert code here...
- Integer *int1 = [[Integer alloc] init];
- NSLog(@"%ld", [int1 retainCount]);
- Integer *int2 = int1;
- NSLog(@"%ld", [int1 retainCount]);
- [int2 retain];
- NSLog(@"%ld", [int1 retainCount]);
- [int2 release];
- NSLog(@"%ld", [int1 retainCount]);
- [int1 release];
- NSLog(@"%ld", [int1 retainCount]);
- int1 = nil;
- [int1 print];
- }
- return 0;
- }
上述代码中,以下代码:
- [int1 release];
- NSLog(@"%ld", [int1 retainCount]);
是向对象int1发送消息release,该消息会使int1指向的对象的引用计数减1,由于int1指向的对象的引用计数已经为1,再减1,将会变为0。此时int1所指向的对象被释放了。但是,如果此时向对象int1发送retainCount消息,得到的int1的引用计数值仍然为1,这是因为此时retainCount消息访问的int1的地址空间,是已经释放的空间,在释放前该空间的引用计数变量没有清0的缘故。
1.4 完整代码
本案例中,类Integer声明,即Integer.h文件,完整代码如下所示:
- #import <Foundation/Foundation.h>
- @interface Integer : NSObject
- @property int integer;
- -(void)print;
- @end
类Integer实现,即Integer.m文件,完整代码如下所示:
- #import "Integer.h"
- @implementation Integer
- -(void)print
- {
- NSLog(@"%d", self.integer);
- }
- @end
主程序,即MRC.m,完整代码如下所示:
- #import <Foundation/Foundation.h>
- #import "Integer.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- // insert code here...
- Integer *int1 = [[Integer alloc] init];
- NSLog(@"%ld", [int1 retainCount]);
- Integer *int2 = int1;
- NSLog(@"%ld", [int1 retainCount]);
- [int2 retain];
- NSLog(@"%ld", [int1 retainCount]);
- [int2 release];
- NSLog(@"%ld", [int1 retainCount]);
- [int1 release];
- NSLog(@"%ld", [int1 retainCount]);
- int1 = nil;
- [int1 print];
- }
- return 0;
- }
2 编写Student和Book类
2.1 问题
本案例需要创建一个Book类,类中有一个整型price属性,用于记录书的价格。还需要创建一个Student类,类中有两个带参属性,它们是整型的年龄age和类Book类型的book,分别用于存储学生的年龄和学生正在学习的书,并且有一个study方法,用于显示年龄为age的学生学习价格为book.price的书。
在主程序中创建Student类的一个对象和Book类的两个对象,首先让Student类的对象拥有一个Book类的对象,然后让Student类的对象更换了拥有对象,换成另一个Book类对象。
2.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:定义类Book
首先,在Day03工程中新添加Book.h文件,用于定义新的类Book。
代码如下所示:
- #import <Foundation/Foundation.h>
- @interface Book : NSObject
- @property int price;
- @end
在上述代码中,定义了类Book,在类中有一个属性,是整型变量price,用于存储书的价格。
然后,在类Book的实现部分,即在Book.m文件中,添加dealloc方法,该方法在本类中实际上没有任何实际意义,只是在类的对象销毁时,在控制台上输出一个提示。
代码如下所示:
- #import "Book.h"
- @implementation Book
- -(void)dealloc{
- NSLog(@"书对象销毁了 price:%d",self.price);
- [super dealloc];
- }
- @end
dealloc方法不能在类外直接被调用,它是在一个对象被release并且对象的引用计数为0时,由内存管理程序调用的方法。
步骤二:定义类Student
首先,在Day03工程中新添加Student.h文件,用于定义新的类Student。
代码如下所示:
- #import <Foundation/Foundation.h>
- #import "Book.h"
- @interface Student : NSObject
- {
- }
- @property(nonatomic,assign) int age;
- @property(nonatomic,retain) Book* book;
- -(void)study;
- @end
在上述代码中,定义了类Student,在类中有两个带参属性。
一个属性是整型变量age,如下代码所示:
- @property(nonatomic,assign) int age;
用于存储学生的年龄。它有两个参数,一个是nonatomic,它代表对属性赋值的时候不加锁,即在多线程环境下访问时可能会出现数据错误,如果需要在多线程环境下运行,为保证数据不会出现错误,可使用atomic参数,它会在对属性赋值的时候加锁。另一个参数是assign,对于C语言的基本数据类型,只能选取这个参数。
另一个属性是book,如下代码所示:
- @property(nonatomic,retain) Book* book;
用于存储学生正在学习的书。它有两个参数,一个是nonatomic,另一个参数是retain,该参数一般用于NSObject类及其子类的对象,这些对象在赋值时需要将引用计数加1,retain参数可以满足这样的需求。
然后,在类Student的实现部分,即在Student.m文件中,添加dealloc方法和study方法的实现。
代码如下所示:
- #import "Student.h"
- @implementation Student
- -(void)dealloc{
- //将所有引用类型的属性在此释放掉
- [self.book release];
- NSLog(@"学生对象销毁了,dealloc方法执行了");
- [super dealloc];
- }
- -(void)study{
- NSLog(@"学生 age:%d 学习书 price:%d 中的知识",self.age,self.book.price);
- }
- @end
dealloc方法在这个类中是必须有的,前面在讲到属性book的retain参数时,指出retain参数会将赋值给属性book的对象的引用计数加1,那么这个对象必须还要减1,其存储空间才能最终得到释放。但是只要Student类对象的存储空间没有释放,属性book的引用计数就不能减1,所以只有在Student类对象的存储空间释放时,通过dealloc将属性book的引用计数减1。
study方法要完成的工作是在控制台上输出学生的年龄和正在学习的书。
步骤三:在主程序中使用Student类和Book类
代码如下所示:
- #import <Foundation/Foundation.h>
- #import "Student.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- Student* stu1 = [[Student alloc]init];
- stu1.age = 18;
- Book* sanguo = [[Book alloc]init];
- sanguo.price = 10;
- stu1.book = sanguo;//将书对象给学生对象
- NSLog(@"%ld", [sanguo retainCount]);
- Book* hongloumeng = [[Book alloc]init];
- hongloumeng.price = 20;
- stu1.book = hongloumeng;
- NSLog(@"%ld", [hongloumeng retainCount]);
- NSLog(@"%ld", [sanguo retainCount]);
- [hongloumeng release];
- [sanguo release];
- [stu1 study];
- [stu1 release];
- }
- return 0;
- }
在上述代码中,以下代码:
- Student* stu1 = [[Student alloc]init];
- stu1.age = 18;
定义了一个Student类的对象stu1,并将stu1的age属性赋值为18。
在上述代码中,以下代码:
- Book* sanguo = [[Book alloc]init];
- sanguo.price = 10;
- stu1.book = sanguo;//将书对象给学生对象
- NSLog(@"%ld", [sanguo retainCount]);
首先,定义了一个Book类的对象sanguo,并将sanguo的price属性赋值为10。然后,将stu1的book属性赋值为sanguo。我们知道book属性有一个参数是retain,它会将赋值给它的对象的引用计数加1,那么现在将sanguo赋值给stu1的book属性,sanguo的引用计数会加1,所以当我们查看sanguo的引用计数值时会发现是2。
在上述代码中,以下代码:
- Book* hongloumeng = [[Book alloc]init];
- hongloumeng.price = 20;
- stu1.book = hongloumeng;
- NSLog(@"%ld", [hongloumeng retainCount]);
- NSLog(@"%ld", [sanguo retainCount]);
首先,定义了一个Book类的对象hongloumeng,并将hongloumeng的price属性赋值为20。然后,将stu1的book属性重新赋值为hongloumeng。我们知道book属性有一个参数是retain,它会将赋值给它的对象的引用计数加1,那么现在将hongloumeng赋值给stu1的book属性,hongloumeng的引用计数会加1,所以当我们查看hongloumeng的引用计数值时会发现是2。但如果此时再查看sanguo的引用计数值时会发现变成了1,这是为什么呢?原因是Student类的book属性参数retain,除了会将赋值给它的对象的引用计数加1外,在加1之前,还会将先前赋值给它的对象的引用计数减1。如本案例中,先将stu1的book属性赋值为sanguo,然后重新赋值为hongloumeng,那么在给hongloumeng引用计数加1之前,先将sanguo的引用计数减了一个1。
在上述代码中,以下代码:
- [hongloumeng release];
- [sanguo release];
对hongloumeng对象进行释放,它不会被从存储空间中删除,因为release只会将hongloumeng的引用计数由2减为1。但是,对sanguo对象进行释放,就会被从存储空间中删除,因为release只会将sanguo的引用计数由1减为0。
在上述代码中,以下代码:
- [stu1 study];
是向对象stu1发送study消息时,因为hongloumeng的引用计数为1,所以它能显示出hongloumeng的价格。
在上述代码中,以下代码:
- [stu1 release];
是释放对象stu1,在stu1的存储空间被释放之前,还会先调用Student类的dealloc方法,在dealloc方法中,hongloumeng的引用计数由1减为0,所以hongloumeng的对象存储空间被释放。而stu1的引用计数一直为1,此时对其进行release,将减为0,stu1的存储空间被释放。
2.3 完整代码
本案例中,类Book声明,即Book.h文件,完整代码如下所示:
- #import <Foundation/Foundation.h>
- @interface Book : NSObject
- @property int price;
- @end
类Book实现,即Book.m文件,完整代码如下所示:
- #import "Book.h"
- @implementation Book
- -(void)dealloc{
- NSLog(@"书对象销毁了 price:%d",self.price);
- [super dealloc];
- }
- @end
本案例中,类Student声明,即Student.h文件,完整代码如下所示:
- #import <Foundation/Foundation.h>
- #import "Book.h"
- @interface Student : NSObject
- {
- }
- @property(nonatomic,assign) int age;
- @property(nonatomic,retain) Book* book;
- -(void)study;
- @end
类Student实现,即Student.m文件,完整代码如下所示:
- #import "Student.h"
- @implementation Student
- -(void)dealloc{
- //将所有引用类型的属性在此释放掉
- [self.book release];
- NSLog(@"学生对象销毁了,dealloc方法执行了");
- [super dealloc];
- }
- -(void)study{
- NSLog(@"学生 age:%d 学习书 price:%d 中的知识",self.age,self.book.price);
- }
- @end
主程序,即StudentBook.m,完整代码如下所示:
- #import <Foundation/Foundation.h>
- #import "Student.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- Student* stu1 = [[Student alloc]init];
- stu1.age = 18;
- Book* sanguo = [[Book alloc]init];
- sanguo.price = 10;
- stu1.book = sanguo;//将书对象给学生对象
- NSLog(@"%ld", [sanguo retainCount]);
- Book* hongloumeng = [[Book alloc]init];
- hongloumeng.price = 20;
- stu1.book = hongloumeng;
- NSLog(@"%ld", [hongloumeng retainCount]);
- NSLog(@"%ld", [sanguo retainCount]);
- [hongloumeng release];
- [sanguo release];
- [stu1 study];
- [stu1 release];
- }
- return 0;
- }
3 编写父类Animal和子类Cat、Dog
3.1 问题
本案例需要创建一个Animal类,类中有一个方法叫shout的方法,该方法默认输出 "动物会叫",这个类作为父类,派生出两个子类Cat类和Dog类。
Cat类没有覆盖父类的shout方法,而Dog覆盖了父类的shout方法,改成自己的输出,"汪汪汪"。
分别调用cat、dog对象的shout方法。
3.2 步骤
实现此案例需要按照如下步骤进行。
步骤一:定义类Animal
首先,在Day03-2工程中新添加Animal.h文件,用于定义新的类Animal。
代码如下所示:
- #import <Foundation/Foundation.h>
- @interface Animal : NSObject
- @property int age;
- -(void)shout;
- @end
在上述代码中,定义了类Animal,在类中有一个属性,是整型变量age,用于存储动物的年龄。类中还有一个eat方法的声明。
然后,在类Animal的实现部分,即在Animal.m文件中,添加shout方法的实现,该方法在控制台上输出“动物会叫”。
代码如下所示:
- #import "Animal.h"
- @implementation Animal
- -(void)shout{
- NSLog(@"动物会叫");
- }
- @end
步骤二:定义类Cat
首先,在Day03-2工程中新添加Cat.h文件,用于定义新的类Cat。
代码如下所示:
- #import <Foundation/Foundation.h>
- #import "Animal.h"
- @interface Cat : Animal
- @end
在上述代码中,以下代码:
- @interface Cat : Animal
是定义一个类Cat,继承父类Animal。
然后,在类Cat的实现部分,即在Cat.m文件中,什么都不做。
代码如下所示:
- #import "Cat.h"
- @implementation Cat
- @end
步骤三:定义类Dog
首先,在Day03-2工程中新添加Dog.h文件,用于定义新的类Dog。
代码如下所示:
- #import "Animal.h"
- @interface Dog : Animal
- @end
上述代码中,类Dog继承与父类Animal。
然后,在类Dog的实现部分,即在Dog.m文件中,覆盖父类Animal中的shout方法。该方法在控制台上输出“汪汪汪”。
代码如下所示:
- #import "Dog.h"
- @implementation Dog
- -(void)shout
- {
- NSLog(@"汪汪汪");
- }
- @end
Dog类中覆盖了Animal类中的方法后, Dog类中有两个shout方法,一个继承自Animal类的shout方法,另一个是是自定义的shout方法。
步骤四:在主程序中使用Animal类、Cat类和Dog类
代码如下所示:
- #import <Foundation/Foundation.h>
- #import "Dog.h"
- #import "Cat.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- Animal* animal = [[Animal alloc]init];
- animal.age = 30;
- //Cat继承于Animal
- Cat* cat = [[Cat alloc]init];
- NSLog(@"cat age:%d",cat.age);
- [cat shout];
- //Dog继承于Animal
- Dog* dog = [[Dog alloc]init];
- dog.age = 18;//可以得到父类属性
- NSLog(@"dog age:%d",dog.age);
- [dog shout];
- }
- return 0;
- }
在上述代码中,以下代码:
- Animal* animal = [[Animal alloc]init];
- animal.age = 30;
定义了一个Animal类的对象animal,并将animal的age属性赋值为30。
在上述代码中,以下代码:
- //Cat继承于Animal
- Cat* cat = [[Cat alloc]init];
定义了一个Cat类的对象cat。
在上述代码中,以下代码:
- NSLog(@"cat age:%d",cat.age);
由于定义Cat类的对象cat后,没有为从Animal类继承过来的属性age赋值,所以输出的猫的年龄为0。
在上述代码中,以下代码:
- [cat shout];
对cat对象发送的shout消息,调用的是父类Animal中shout。因为定义Cat类时没有覆盖父类Animal类中的方法shout,所以在Cat类中只有从父类Cat中继承的shout方法。
在上述代码中,以下代码:
- //Dog继承于Animal
- Dog* dog = [[Dog alloc]init];
- dog.age = 18;//可以得到父类属性
定义了一个Dog类的对象dog,并对从Animal类继承过来的属性age赋值为18。
在上述代码中,以下代码:
- NSLog(@"dog age:%d",dog.age);
由于定义Dog类的对象dog后,已经为从Animal类继承过来的属性age赋值为18,所以输出的狗的年龄为18。
在上述代码中,以下代码:
- [dog shout];
对dog对象发送的shout消息,调用的是Dog类中shout。因为定义Dog类时已经覆盖父类Animal类中的方法shout,即在Dog类中有两个shout方法,一个是从父类Animal中继承的shout方法,另一个是自定义的shout。按照继承的语法规则,当向Dog类的对象dog发送shout消息时,优先调用自定义的shout方法。
3.3 完整代码
本案例中,类Animal声明,即Animal.h文件,完整代码如下所示:
- #import <Foundation/Foundation.h>
- @interface Animal : NSObject
- @property int age;
- -(void)shout;
- @end
类Animal实现,即Animal.m文件,完整代码如下所示:
- #import "Animal.h"
- @implementation Animal
- -(void)shout{
- NSLog(@"动物会叫");
- }
- @end
本案例中,类Cat声明,即Cat.h文件,完整代码如下所示:
- #import <Foundation/Foundation.h>
- #import "Animal.h"
- @interface Cat : Animal
- @end
类Cat实现,即Cat.m文件,完整代码如下所示:
- #import "Cat.h"
- @implementation Cat
- @end
本案例中,类Dog声明,即Dog.h文件,完整代码如下所示:
- #import "Animal.h"
- @interface Dog : Animal
- @end
类Dog实现,即Dog.m文件,完整代码如下所示:
- #import "Dog.h"
- @implementation Dog
- -(void)shout
- {
- NSLog(@"汪汪汪");
- }
- @end
主程序,即AnimalCatDog.m,完整代码如下所示:
- #import <Foundation/Foundation.h>
- #import "Dog.h"
- #import "Cat.h"
- int main(int argc, const char * argv[])
- {
- @autoreleasepool {
- Animal* animal = [[Animal alloc]init];
- animal.age = 30;
- //Cat继承于Animal
- Cat* cat = [[Cat alloc]init];
- NSLog(@"cat age:%d",cat.age);
- [cat shout];
- //Dog继承于Animal
- Dog* dog = [[Dog alloc]init];
- dog.age = 18;//可以得到父类属性
- NSLog(@"dog age:%d",dog.age);
- [dog shout];
- }
- return 0;
- }
Objective-C----MRC内存管理 、 自动释放池 、 面向对象三大特性及封装 、 继承 、 组合与聚合的更多相关文章
- OC 内存泄露 自动释放池
花絮:看到下面的代码就想起这么一个调侃: 一个老程序员,功成名就,金盆洗手不在写代码后,决定练练书法.提笔思索良久后在纸上写下:Hello world! /********************** ...
- objective-C 的内存管理之-自动释放池(autorelease pool)
如果一个对象的生命周期显而易见,很容易就知道什么时候该new一个对象,什么时候不再需要使用,这种情况下,直接用手动的retain和release来判定其生死足矣.但是有些时候,想知道某个对象在什么时候 ...
- OC_内存管理(二)对象复制、循环引用问题、自动释放池
循环调用: 1.循环引用的问题 两个对象A.B,有可能会出现特殊情况:A中包含B的实例变量:B中也包含A的实例变量,如果这两个实例变量都是强引用(A有着B的实例变量所有权,B也有A的实例变量所有权 ...
- Objective c 自动释放池
学IOS 的大家都知道,IOS 一共有三种内存管理方式:MRC .ARC.自动释放池.我按照我个人的理解简述一下自动释放池,希望能给大家一点帮助,如有错误请大家及时批评指正. 自动释放池有几个特点:1 ...
- iOS阶段学习第20天笔记(MRC内存管理)
iOS学习(OC语言)知识点整理 一.OC中的内存管理 1)概念:内存管理的对象为所有继承了NSObject的对象,对基本数据(如:int .float.double...)无效 OC中采用 ...
- 63 (OC)* NSAutoreleasePool 自动释放池
目录 0:ARC 1: 自动释放池 2:NSAutoreleasePool实现原理 3:autorelease 方法 4: Runloop和Autorelease的关系 5: Using Autore ...
- iOS进阶四-自动释放池原理
概述 AutoreleasePool(自动释放池)是OC中的一种内存自动回收机制,它可以延迟加入AutoreleasePool中的变量release的时机.在正常情况下,创建的变量会在超出其作用域的时 ...
- Autorelease自动释放池的使用
Autorelease自动释放池的使用 使用ARC开发,只是在编译时,编译器会根据代码结构自动添加了retain.release和autorelease. MRC内存管理原则:谁申请,谁释放 遇到al ...
- autoreleasepool自动释放池
示例: @autoreleasepool { ; i[largeNumber; i++) { (因识别问题,该行代码中尖括号改为方括号代替) Person *per = [[Person alloc ...
随机推荐
- mysql str_to_date字符串转换为日期
mysql内置函数,在mysql里面利用str_to_date()把字符串转换为日期. 示例:分隔符一致,年月日要一致 select str_to_date('2008-4-2 15:3:28','% ...
- weblogic被锁解决方案
weblogic被锁,无法启动. 解决方案:http://blog.csdn.net/zhengqiqiqinqin/article/details/17025741
- Oracle内置函数内容整理
--绝对值select abs(-100) from dual; --取余select mod(8,3) from dual; --取整,大于该数的最小整数(上限值)select ceil(12.0) ...
- 从QQ网站中提取的纯JS省市区三级联动
在 http://ip.qq.com/ 的网站中有QQ自己的JS省市区三级联动 QQ是使用引用外部JS来实现三级联动的.JS如下:http://ip.qq.com/js/geo.js <!DOC ...
- CSS 水平居中
一.水平居中:行内元素解决方案 居中元素:文字.链接以及其它行内元素(inline或inline-*类型的元素,如inline-block,inline-table,inline-flex)解决方案: ...
- iOS 下如果存在UIScrollerView 使用UIScreenEdgePanGestureRecognizer实现侧滑效果失效的问题
当你在使用UIScreenEdgePanGestureRecognizer手势实现侧滑的时候,如果后期你导航控制器push出的界面中包含UIScrollerView,这个时候你会发现,侧滑效果无法实现 ...
- java基础之 http
HTTP(HyperText Transfer Protocol)是一套计算机通过网络进行通信的规则.计算机专家设计出HTTP,使HTTP客户(如Web浏览器)能够从HTTP服务器(Web服务器)请求 ...
- php可变变量
例子: <?php $a = "b"; $$a = "c"; echo $$a; echo "<br>"; echo $b ...
- navtab方法参数以及事件
参数(options) DOM方式初始化navtab的,推荐使用集合属性data-options定义参数,如果使用data属性定义参数,注意转换成对应的名称. 名称 类型 默认值 描述 id stri ...
- Python开发入门与实战1-开发环境
1.搭建Python Django开发环境 1.1.Python运行环境安装 Python官网:http://www.python.org/ Python最新源码,二进制文档,新闻资讯等可以在Pyth ...