IOS之Objective-C学习笔记(六)
2015-08-31 22:01
597 查看
在之前的一片文章我们说了OC中谓词操作:/article/1537175.html,从今天开始我们就来看一下OC中最难的一部分内容:内存管理
为什么说他难呢?因为内存如果需要我们程序员去管理的话,那个难度肯定是很大的,如果是Java,垃圾回收器会把这份工作给做了,我们不需要关心,但是就是因为如此,Android运行速度上会慢一下,原因很简单,Java的垃圾回收器有很多收集算法的,这个在回收的过程中是很浪费时间的,效率自然就低了,但是如果这份工作给程序员自己去做的话,效率上肯定会增加,但是对于程序员来说任务就比较繁重了,而且还要特别的小心,千万不能造成内存溢出和泄露。
这里我们主要从四个方面来介绍一下内存管理
1、简单的例子来了解引用计数的使用
2、set方法来控制引用计数问题
3、销毁方法来控制引用计数问题
4、初始化方法来控制引用计数问题
下面就来简单看一下OC中的内存管理
这个例子有点复杂,我们慢慢分析
Dog.h
[objc] view
plaincopy
//
// Dog.h
// 24_MemeryManager
//
// Created by jiangwei on 14-10-12.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Dog : NSObject{
NSString *_name;
}
- (void) setName:(NSString *)name;
@end
Dog.m
[objc] view
plaincopy
//
// Dog.m
// 24_MemeryManager
//
// Created by jiangwei on 14-10-12.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import "Dog.h"
@implementation Dog
- (void) setName:(NSString *)name{
_name = name;
}
@end
Dog类中定义了name属性,并且给他提供了一个set方法
Person.h
[objc] view
plaincopy
//
// Person.h
// 24_MemeryManager
//
// Created by jiangwei on 14-10-12.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import <Foundation/Foundation.h>
@class Dog;
@interface Person : NSObject{
Dog *_dog;
NSString * _name;
}
- (id)initWithDog:(Dog*)dog;
- (void)setName:(NSString *)name;
- (void)setDog:(Dog *)dog;
- (void)playDog;
- (Dog *)dog;
- (void)dealloc;
@end
Person.m
[objc] view
plaincopy
//
// Person.m
// 24_MemeryManager
//
// Created by jiangwei on 14-10-12.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import "Person.h"
@implementation Person
- (id)initWithDog:(Dog*)dog{
//使用初始化的时候传入dog
self = [super init];
if(self != nil){
//因为初始化方法只会调用一次,所以这里就没有做判断了
[_dog release];
_dog = [dog retain];
}
return self;
}
- (void)setName:(NSString *)name{
//这里name也是对象,所以也是需要进行改写
_name = name;
/*
//这里的判断是因为setName方法可能会被多次调用
if(_name != name){
[_name release];
[name copy];//这里使用了copy,而没有使用retain,这个是字符串独有的,其他对象类型都是使用retain的
}
*/
}
//第一种方式
/*
- (void)setDog:(Dog *)dog{
//引用计数需要+1
_dog = [dog retain];
//有时候可能需要替换Dog对象,所以这里还要注意释放Dog的引用
}
*/
//第二种方式
/*
- (void)setDog:(Dog *)dog{
//使用nil去调用方法是没有错误的
//但是当一个对象被销毁的时候,指针就变成野指针了,这时候调用方法会出错的
[_dog release];
_dog = [dog retain];
}
*/
//第三种方式
- (void)setDog:(Dog *)dog{
//这里的判断是因为setName方法可能会被多次调用
if(_dog != dog){
[_dog release];
_dog = [dog retain];
}
}
- (void)playDog{
NSLog(@"playDog");
}
- (Dog *)dog{
return _dog;
}
- (void)dealloc{
//对象类型的属性都需要在这里进行释放引用
//对狗进行释放
[_dog release];
NSLog(@"dealloc is Executing");
[super dealloc];
}
@end
Person类中有一个Dog的属性,然后提供了set方法。代码有点复杂,我们后面会详细说明
下面来看一下测试代码
main.m
[objc] view
plaincopy
//
// main.m
// 24_MemeryManager
//
// Created by jiangwei on 14-10-12.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Dog.h"
//内存管理
//alloc用来创建对象,创建完成之后,引用计数为1,只调用一次
//retain使引用计数+1,可以多调用几次
//release使引用计数-1,可以多调用几次
//当引用计数为0的时候会调用dealloc
//最新的Xcode版本默认情况下会开启ARC机制的,当开启这个机制之后,我们就不能手动的显示调用这些方法,编译器会报错
//所以我们可以将这个默认状态的ARC关闭,但是这个只是为了测试使用
int main(int argc, const charchar * argv[]) {
/*
Person *person = [[Person alloc] init];//引用计数为1
NSLog(@"引用计数:%ld",[person retainCount]);
//引用计数加1
[person retain];
[person release];
NSLog(@"引用计数:%ld",[person retainCount]);
[person release];
*/
Dog *dog = [[Dog alloc] init];
[dog setName:@"小黑"];
Dog *dog1 = [[Dog alloc] init];//引用计数为1
[dog setName:@"大黄"];
Person *p1 = [[Person alloc] init];
[p1 setName:@"张三"];
[p1 setDog:dog];
[p1 setDog:dog1];//狗的引用替换成了大黄
Person *p2 = [[Person alloc] init];
[p2 setName:@"李四"];
[p2 setDog:dog];
//这里引用计数为1,这个和我们之前说的引用计数管理有矛盾,所以我们在使用的时候需要手动的retain
NSLog(@"引用计数为:%ld",[dog retainCount]);
[dog1 release];//因为alloc的时候引用计数就为1了
//这里就有一个问题了,dog1对象已经被销毁了,但是setDog对象还是用了dog1对象调用方法了,这就会报错了
//所以又对set方法进行改进了
[p1 setDog:dog1];
//当人销毁的时候,还需要对狗的引用-1
//在人的dealloc方法中实现
Person *p3 = [[Person alloc] initWithDog:dog1];
[dog1 release];//dog1的引用计数:0
[p3 playDog];
[p3 release];
return 0;
}
下面我们来详细说明一下:
首先如果想演示这个例子的话,需要修改一下设置:
最新的XCode默认是会自动选上ARC(Automatic Reference Counting),如果我们不把这个手动关闭的话,代码中会报错的。
alloc用来创建对象,创建完成之后,引用计数为1,只调用一次
retain使引用计数+1,可以多调用几次
release使引用计数-1,可以多调用几次
当引用计数为0的时候会调用dealloc
黄金法则:每次调用alloc一次,都需要调用release一次,他们两是成对出现的
最新的Xcode版本默认情况下会开启ARC机制的,当开启这个机制之后,我们就不能手动的显示调用这些方法,编译器会报错
所以我们可以将这个默认状态的ARC关闭,但是这个只是为了测试使用
同时我们会发现main.m文件中没有自动释放池了@autoreleasepool了。
1、简单的例子
[objc] view
plaincopy
Person *person = [[Person alloc] init];//引用计数为1
NSLog(@"引用计数:%ld",[person retainCount]);
//引用计数加1
[person retain];
[person release];
NSLog(@"引用计数:%ld",[person retainCount]);
[person release];
我们创建了一个Person类,然后可以打印一下的引用计数值:1
当我们调用retain方法的时候,引用计数就会+1,当我们调用release方法的时候引用计数会-1
一旦系统发现引用计数为0的时候,就会销毁这个对象,调用dealloc方法
2、set方法来控制引用计数
这个例子简单吧,没什么问题的,现在我们把问题复杂化
[java] view
plaincopy
Dog *dog = [[Dog alloc] init];
[dog setName:@"小黑"];
Dog *dog1 = [[Dog alloc] init];//引用计数为1
[dog setName:@"大黄"];
Person *p1 = [[Person alloc] init];
[p1 setName:@"张三"];
[p1 setDog:dog];
[p1 setDog:dog1];//狗的引用替换成了大黄
Person *p2 = [[Person alloc] init];
[p2 setName:@"李四"];
[p2 setDog:dog];
//这里引用计数为1,这个和我们之前说的引用计数管理有矛盾,所以我们在使用的时候需要手动的retain
NSLog(@"引用计数为:%ld",[dog retainCount]);
[dog1 release];//因为alloc的时候引用计数就为1了
//这里就有一个问题了,dog1对象已经被销毁了,但是setDog对象还是用了dog1对象调用方法了,这就会报错了
//所以又对set方法进行改进了
[p1 setDog:dog1];
//当人销毁的时候,还需要对狗的引用-1
//在人的dealloc方法中实现
我们定义了两条狗,然后将这两条狗通过setDog方法设置到p1对象上,同时将第一条狗设置到p2对象上,这时候我们打印一下第一条狗的引用计数,发现他的引用计数是1,原因很简单,这个1是在alloc时候有的,但是现在是有问题的,因为第一条狗被p1和p2引用者,按照正常情况,第一条狗的引用计数为3的。所以这时候我们就需要修改一下Person类中setDog方法了
[objc] view
plaincopy
- (void)setDog:(Dog *)dog{
//引用计数需要+1
_dog = [dog retain];
//有时候可能需要替换Dog对象,所以这里还要注意释放Dog的引用
}
我们需要手动的增加dog的引用计数,这样就正常了。
现在又有一个问题了,上面p1对象设置了第二条狗
[objc] view
plaincopy
[p1 setDog:dog1];//狗的引用替换成了大黄
按照上面的setDog方法,我们又发现一个问题,现在p1引用的狗是第二条狗了,不是第一条,那么这时候按照正常情况第一条狗的引用计数-1,因为他已经不再被p1引用了。所以setDog方法还得修改:
[objc] view
plaincopy
- (void)setDog:(Dog *)dog{
//使用nil去调用方法是没有错误的
//但是当一个对象被销毁的时候,指针就变成野指针了,这时候调用方法会出错的
[_dog release];
_dog = [dog retain];
}
这时候我们就在赋值之前,对_dog调用一次release方法,这样就解决了上面的那个问题。
但是现在还有一个问题:
[java] view
plaincopy
[dog1 release];//因为alloc的时候引用计数就为1了
NSLog(@"dog1:%ld",[dog1 retainCount]);
//这里就有一个问题了,dog1对象已经被销毁了,但是setDog对象还是用了dog1对象调用方法了,这就会报错了
//所以又对set方法进行改进了
[p1 setDog:dog1];
在执行release代码之后,dog1的引用计数为1,这是继续调用setDog方法:
[objc] view
plaincopy
- (void)setDog:(Dog *)dog{
//使用nil去调用方法是没有错误的
//但是当一个对象被销毁的时候,指针就变成野指针了,这时候调用方法会出错的
[_dog release];
_dog = [dog retain];
}
这时候_dog是dog1,继续调用release方法,执行完之后,引用继续为0了,对象被释放了,但是这时候dog参数的值还是dog1,那么在执行retain方法就会报错了,这个原因很简单,就是我们两次调用了setDog方法,将dog1设置了两次。中间调用一次release方法。所以解决这样的问题,我们在修改一下setDog方法:
[objc] view
plaincopy
//第三种方式
- (void)setDog:(Dog *)dog{
//这里的判断是因为setName方法可能会被多次调用
if(_dog != dog){
[_dog release];
_dog = [dog retain];
}
}
我只需要判断一下,之前的属性值和当前需要设置的值是否相同。这种方式就是没有问题了,所以我们以后在写set方法的时候,这就是模板了。
3、销毁方法dealloc控制引用计数
现在假如p1被销毁了,那么对于dog1来说引用计数应该-1的,所以需要在Person类中的dealloc方法中修改一下:
[objc] view
plaincopy
- (void)dealloc{
//对象类型的属性都需要在这里进行释放引用
//对狗进行释放
[_dog release];
NSLog(@"dealloc is Executing");
[super dealloc];
}
4、初始化方法控制引用计数
现在还有一种情况,如果我们使用初始化方法来设置Dog属性值:
[objc] view
plaincopy
- (id)initWithDog:(Dog*)dog{
//使用初始化的时候传入dog
self = [super init];
if(self != nil){
//因为初始化方法只会调用一次,所以这里就没有做判断了
[_dog release];
_dog = [dog retain];
}
return self;
}
我们这里的处理和setDog方法的处理方式一样,但是这里不需要做一次判断了,因为初始化方法只会调用一次。所以不会出现setDog的第三种情况。
为什么说他难呢?因为内存如果需要我们程序员去管理的话,那个难度肯定是很大的,如果是Java,垃圾回收器会把这份工作给做了,我们不需要关心,但是就是因为如此,Android运行速度上会慢一下,原因很简单,Java的垃圾回收器有很多收集算法的,这个在回收的过程中是很浪费时间的,效率自然就低了,但是如果这份工作给程序员自己去做的话,效率上肯定会增加,但是对于程序员来说任务就比较繁重了,而且还要特别的小心,千万不能造成内存溢出和泄露。
这里我们主要从四个方面来介绍一下内存管理
1、简单的例子来了解引用计数的使用
2、set方法来控制引用计数问题
3、销毁方法来控制引用计数问题
4、初始化方法来控制引用计数问题
下面就来简单看一下OC中的内存管理
这个例子有点复杂,我们慢慢分析
Dog.h
[objc] view
plaincopy
//
// Dog.h
// 24_MemeryManager
//
// Created by jiangwei on 14-10-12.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface Dog : NSObject{
NSString *_name;
}
- (void) setName:(NSString *)name;
@end
Dog.m
[objc] view
plaincopy
//
// Dog.m
// 24_MemeryManager
//
// Created by jiangwei on 14-10-12.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import "Dog.h"
@implementation Dog
- (void) setName:(NSString *)name{
_name = name;
}
@end
Dog类中定义了name属性,并且给他提供了一个set方法
Person.h
[objc] view
plaincopy
//
// Person.h
// 24_MemeryManager
//
// Created by jiangwei on 14-10-12.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import <Foundation/Foundation.h>
@class Dog;
@interface Person : NSObject{
Dog *_dog;
NSString * _name;
}
- (id)initWithDog:(Dog*)dog;
- (void)setName:(NSString *)name;
- (void)setDog:(Dog *)dog;
- (void)playDog;
- (Dog *)dog;
- (void)dealloc;
@end
Person.m
[objc] view
plaincopy
//
// Person.m
// 24_MemeryManager
//
// Created by jiangwei on 14-10-12.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import "Person.h"
@implementation Person
- (id)initWithDog:(Dog*)dog{
//使用初始化的时候传入dog
self = [super init];
if(self != nil){
//因为初始化方法只会调用一次,所以这里就没有做判断了
[_dog release];
_dog = [dog retain];
}
return self;
}
- (void)setName:(NSString *)name{
//这里name也是对象,所以也是需要进行改写
_name = name;
/*
//这里的判断是因为setName方法可能会被多次调用
if(_name != name){
[_name release];
[name copy];//这里使用了copy,而没有使用retain,这个是字符串独有的,其他对象类型都是使用retain的
}
*/
}
//第一种方式
/*
- (void)setDog:(Dog *)dog{
//引用计数需要+1
_dog = [dog retain];
//有时候可能需要替换Dog对象,所以这里还要注意释放Dog的引用
}
*/
//第二种方式
/*
- (void)setDog:(Dog *)dog{
//使用nil去调用方法是没有错误的
//但是当一个对象被销毁的时候,指针就变成野指针了,这时候调用方法会出错的
[_dog release];
_dog = [dog retain];
}
*/
//第三种方式
- (void)setDog:(Dog *)dog{
//这里的判断是因为setName方法可能会被多次调用
if(_dog != dog){
[_dog release];
_dog = [dog retain];
}
}
- (void)playDog{
NSLog(@"playDog");
}
- (Dog *)dog{
return _dog;
}
- (void)dealloc{
//对象类型的属性都需要在这里进行释放引用
//对狗进行释放
[_dog release];
NSLog(@"dealloc is Executing");
[super dealloc];
}
@end
Person类中有一个Dog的属性,然后提供了set方法。代码有点复杂,我们后面会详细说明
下面来看一下测试代码
main.m
[objc] view
plaincopy
//
// main.m
// 24_MemeryManager
//
// Created by jiangwei on 14-10-12.
// Copyright (c) 2014年 jiangwei. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Person.h"
#import "Dog.h"
//内存管理
//alloc用来创建对象,创建完成之后,引用计数为1,只调用一次
//retain使引用计数+1,可以多调用几次
//release使引用计数-1,可以多调用几次
//当引用计数为0的时候会调用dealloc
//最新的Xcode版本默认情况下会开启ARC机制的,当开启这个机制之后,我们就不能手动的显示调用这些方法,编译器会报错
//所以我们可以将这个默认状态的ARC关闭,但是这个只是为了测试使用
int main(int argc, const charchar * argv[]) {
/*
Person *person = [[Person alloc] init];//引用计数为1
NSLog(@"引用计数:%ld",[person retainCount]);
//引用计数加1
[person retain];
[person release];
NSLog(@"引用计数:%ld",[person retainCount]);
[person release];
*/
Dog *dog = [[Dog alloc] init];
[dog setName:@"小黑"];
Dog *dog1 = [[Dog alloc] init];//引用计数为1
[dog setName:@"大黄"];
Person *p1 = [[Person alloc] init];
[p1 setName:@"张三"];
[p1 setDog:dog];
[p1 setDog:dog1];//狗的引用替换成了大黄
Person *p2 = [[Person alloc] init];
[p2 setName:@"李四"];
[p2 setDog:dog];
//这里引用计数为1,这个和我们之前说的引用计数管理有矛盾,所以我们在使用的时候需要手动的retain
NSLog(@"引用计数为:%ld",[dog retainCount]);
[dog1 release];//因为alloc的时候引用计数就为1了
//这里就有一个问题了,dog1对象已经被销毁了,但是setDog对象还是用了dog1对象调用方法了,这就会报错了
//所以又对set方法进行改进了
[p1 setDog:dog1];
//当人销毁的时候,还需要对狗的引用-1
//在人的dealloc方法中实现
Person *p3 = [[Person alloc] initWithDog:dog1];
[dog1 release];//dog1的引用计数:0
[p3 playDog];
[p3 release];
return 0;
}
下面我们来详细说明一下:
首先如果想演示这个例子的话,需要修改一下设置:
最新的XCode默认是会自动选上ARC(Automatic Reference Counting),如果我们不把这个手动关闭的话,代码中会报错的。
alloc用来创建对象,创建完成之后,引用计数为1,只调用一次
retain使引用计数+1,可以多调用几次
release使引用计数-1,可以多调用几次
当引用计数为0的时候会调用dealloc
黄金法则:每次调用alloc一次,都需要调用release一次,他们两是成对出现的
最新的Xcode版本默认情况下会开启ARC机制的,当开启这个机制之后,我们就不能手动的显示调用这些方法,编译器会报错
所以我们可以将这个默认状态的ARC关闭,但是这个只是为了测试使用
同时我们会发现main.m文件中没有自动释放池了@autoreleasepool了。
1、简单的例子
[objc] view
plaincopy
Person *person = [[Person alloc] init];//引用计数为1
NSLog(@"引用计数:%ld",[person retainCount]);
//引用计数加1
[person retain];
[person release];
NSLog(@"引用计数:%ld",[person retainCount]);
[person release];
我们创建了一个Person类,然后可以打印一下的引用计数值:1
当我们调用retain方法的时候,引用计数就会+1,当我们调用release方法的时候引用计数会-1
一旦系统发现引用计数为0的时候,就会销毁这个对象,调用dealloc方法
2、set方法来控制引用计数
这个例子简单吧,没什么问题的,现在我们把问题复杂化
[java] view
plaincopy
Dog *dog = [[Dog alloc] init];
[dog setName:@"小黑"];
Dog *dog1 = [[Dog alloc] init];//引用计数为1
[dog setName:@"大黄"];
Person *p1 = [[Person alloc] init];
[p1 setName:@"张三"];
[p1 setDog:dog];
[p1 setDog:dog1];//狗的引用替换成了大黄
Person *p2 = [[Person alloc] init];
[p2 setName:@"李四"];
[p2 setDog:dog];
//这里引用计数为1,这个和我们之前说的引用计数管理有矛盾,所以我们在使用的时候需要手动的retain
NSLog(@"引用计数为:%ld",[dog retainCount]);
[dog1 release];//因为alloc的时候引用计数就为1了
//这里就有一个问题了,dog1对象已经被销毁了,但是setDog对象还是用了dog1对象调用方法了,这就会报错了
//所以又对set方法进行改进了
[p1 setDog:dog1];
//当人销毁的时候,还需要对狗的引用-1
//在人的dealloc方法中实现
我们定义了两条狗,然后将这两条狗通过setDog方法设置到p1对象上,同时将第一条狗设置到p2对象上,这时候我们打印一下第一条狗的引用计数,发现他的引用计数是1,原因很简单,这个1是在alloc时候有的,但是现在是有问题的,因为第一条狗被p1和p2引用者,按照正常情况,第一条狗的引用计数为3的。所以这时候我们就需要修改一下Person类中setDog方法了
[objc] view
plaincopy
- (void)setDog:(Dog *)dog{
//引用计数需要+1
_dog = [dog retain];
//有时候可能需要替换Dog对象,所以这里还要注意释放Dog的引用
}
我们需要手动的增加dog的引用计数,这样就正常了。
现在又有一个问题了,上面p1对象设置了第二条狗
[objc] view
plaincopy
[p1 setDog:dog1];//狗的引用替换成了大黄
按照上面的setDog方法,我们又发现一个问题,现在p1引用的狗是第二条狗了,不是第一条,那么这时候按照正常情况第一条狗的引用计数-1,因为他已经不再被p1引用了。所以setDog方法还得修改:
[objc] view
plaincopy
- (void)setDog:(Dog *)dog{
//使用nil去调用方法是没有错误的
//但是当一个对象被销毁的时候,指针就变成野指针了,这时候调用方法会出错的
[_dog release];
_dog = [dog retain];
}
这时候我们就在赋值之前,对_dog调用一次release方法,这样就解决了上面的那个问题。
但是现在还有一个问题:
[java] view
plaincopy
[dog1 release];//因为alloc的时候引用计数就为1了
NSLog(@"dog1:%ld",[dog1 retainCount]);
//这里就有一个问题了,dog1对象已经被销毁了,但是setDog对象还是用了dog1对象调用方法了,这就会报错了
//所以又对set方法进行改进了
[p1 setDog:dog1];
在执行release代码之后,dog1的引用计数为1,这是继续调用setDog方法:
[objc] view
plaincopy
- (void)setDog:(Dog *)dog{
//使用nil去调用方法是没有错误的
//但是当一个对象被销毁的时候,指针就变成野指针了,这时候调用方法会出错的
[_dog release];
_dog = [dog retain];
}
这时候_dog是dog1,继续调用release方法,执行完之后,引用继续为0了,对象被释放了,但是这时候dog参数的值还是dog1,那么在执行retain方法就会报错了,这个原因很简单,就是我们两次调用了setDog方法,将dog1设置了两次。中间调用一次release方法。所以解决这样的问题,我们在修改一下setDog方法:
[objc] view
plaincopy
//第三种方式
- (void)setDog:(Dog *)dog{
//这里的判断是因为setName方法可能会被多次调用
if(_dog != dog){
[_dog release];
_dog = [dog retain];
}
}
我只需要判断一下,之前的属性值和当前需要设置的值是否相同。这种方式就是没有问题了,所以我们以后在写set方法的时候,这就是模板了。
3、销毁方法dealloc控制引用计数
现在假如p1被销毁了,那么对于dog1来说引用计数应该-1的,所以需要在Person类中的dealloc方法中修改一下:
[objc] view
plaincopy
- (void)dealloc{
//对象类型的属性都需要在这里进行释放引用
//对狗进行释放
[_dog release];
NSLog(@"dealloc is Executing");
[super dealloc];
}
4、初始化方法控制引用计数
现在还有一种情况,如果我们使用初始化方法来设置Dog属性值:
[objc] view
plaincopy
- (id)initWithDog:(Dog*)dog{
//使用初始化的时候传入dog
self = [super init];
if(self != nil){
//因为初始化方法只会调用一次,所以这里就没有做判断了
[_dog release];
_dog = [dog retain];
}
return self;
}
我们这里的处理和setDog方法的处理方式一样,但是这里不需要做一次判断了,因为初始化方法只会调用一次。所以不会出现setDog的第三种情况。
相关文章推荐
- 斯坦福大学iOS应用开发教程学习笔记(第三课) Objective-C
- NSMutableString可变字符串的定义及常用方法
- 关于JSONArray明明添加add JSONObject却为空
- OC基础-零基础学习Objective-C:第四部分.NSArray
- OC基础-零基础学习Objective-C:第五部分.@property
- OC基础-零基础学习Objective-C:第六部分.ARC内存管理
- objective-c 实现常用算法(冒泡、选择、快速、插入)
- Swift Tutorial(swift 教程) 3:Arrays, Objects, and Classes数组,对象和类
- gobject base class
- iOS开发系列—Objective-C之内存管理(前辈写的,借鉴了一下,超赞)
- swift中导入Objective-c的第三方库(swift与oc混编)
- gobject type system
- 将List<Map<String, Object>>排序,升序、降序
- java.lang.NoSuchMethodError: org.objectweb.asm.ClassWriter. <init>(Z)V
- iOS利用block实现链式编程方法(Objective-C链式编程)
- OC之ARC环境中的循环strong问题
- iPhone Development 101: Objective-C: Objective-C: Custom URL Schemes
- OC之@class
- OC之set方法内存管理
- [Swift] Any VS AnyObject