kenyo网友的原创说法是:做IOS开发的估计都对Objective-C的内存管理机制很头疼,一不小心程序就会出内存泄露,我也不例外,前几天被指针的置nil与release给搞惨了,今和大家详细解说一下有关Objective-C中nil与release的区别与用法。
首先说一下他们两的作用,nil就是把一个对象的指针置为空,只是切断了指针与内存中对象的联系,它对内存的释放没有什么作用;而release才是真正用于内存释放的,release后系统会将该块内存标记为可用(可重新分配)。所以nil并没有释放内存,只有release才是真正释放内存。
二者使用顺序,如果没有release就直接nil,那么虽然不会出错(release一个空指针是合法的),但却等于自己制造了内存泄漏,因为nil之后release就已经不起作用了,我之前的教训就是一不小心把nil搁在了release之前,所以leak一直报内存泄露。
相反,如果先release后设置nil,就不会出现这样的问题,但是有人就会问,release而没有设置nil,会怎样?其实程序可能也不会报错,但是要知道设置nil其实是为了防止指针错乱,因为一个对象在release之后,给它所分配的内存就已经被释放了,如果释放之后不把指针置空的话,系统再误用到到这个指针时,那么程序就会崩溃(此种情况特别容易出现在延时调用函数中),如果释放之后把它的指针置为空,则即便后面的程序用到该指针,也不会崩溃。所以Objective-C释放内存时必须先release然后nil。
还有一点,在子龙山人的原创文章中有这样的话:可能有读者经常看到,在我的教程的dealloc函数里面有这样的代码:self.xxx = nil;看到这里,现在你们明白这样写有什么用了吧?它等价于[xxx release]; xxx = [nil retain];(---如果你的property(nonatomic,retian)xxx,那么就会这样,如果不是,就对号入座吧)。这就是说,在使用了@property运算符后的类变量会产生set和get方法,而set方法的具体写法是这样的:
-(void) setNames:(NSArray*)names{
NSLog(@"setNames");
if (_name != name) {
[_name release];
_name = [name retain]; }
}
原来的变量和nil比较,不等于就自动释放了,然后再执行xxx=[nil retain];语句
nil
- nil 是 ObjC 对象的字面空值,对应 id 类型的对象,或者使用 @interface 声明的 ObjC 对象。
- 例如:
NSString *someString = nil;
NSURL *someURL = nil;
id someObject = nil;
if
(anotherObject == nil)
// do something
- 定义:
// objc.h
#ifndef nil
# if __has_feature(cxx_nullptr)
# define nil nullptr
# else
# define nil __DARWIN_NULL
# endif
#endif
// __DARWIN_NULL in _types.h
#define __DARWIN_NULL ((void *)0)
Nil
- Nil 是 ObjC 类类型的书面空值,对应 Class 类型对象。
- 例如:
Class someClass = Nil;
Class anotherClass = [NSString
class
];
- 定义声明和 nil 是差不多的,值相同:
// objc.h
#ifndef Nil
# if __has_feature(cxx_nullptr)
# define Nil nullptr
# else
# define Nil __DARWIN_NULL
# endif
#endif
NULL
- NULL 是任意的 C 指针空值。
- 例如:
int
*pointerToInt = NULL;
char
*pointerToChar = NULL;
struct
TreeNode *rootNode = NULL;
- 定义:
// in stddef.h
#define NULL ((void*)0)
NSNull
- NSNull 是一个代表空值的类,是一个 ObjC 对象。实际上它只有一个单例方法:+[NSNull null],一般用于表示集合中值为空的对象。
- 例子说明:
// 因为 nil 被用来用为集合结束的标志,所以 nil 不能存储在 Foundation 集合里。
NSArray *array = [NSArray arrayWithObjects:@
"one"
, @
"two"
, nil];
// 错误的使用
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:nil forKey:@
"someKey"
];
// 正确的使用
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:[NSNull null] forKey:@
"someKey"
];
- 定义:
/* NSNull.h
Copyright (c) 1994-2012, Apple Inc. All rights reserved.
*/
#import <Foundation/NSObject.h>
@interface NSNull : NSObject <NSCopying, NSSecureCoding>
+ (NSNull *)null;
@end
NIL 或 NSNil
ObjC 不存在这两个符号!
小结
虽然 nil, Nil, NULL 的值相同,理解它们之间的书面意义才重要,让代码更加明确,增加可读性。
参考资料
object c 中的BOOL值与bool值
typedef signed char BOOL;
#define YES (BOOL) 1
#define NO (BOOL) 0
从上面的定义我们发现布尔变量的值为 YES/NO,或 1/0 。YES 或 1 代表真,NO 或 0 代表假。比如你定义了一个布尔变量并赋了值:
BOOL enabled = NO;
enabled = 0;
判断BOOL值为YES:
if(enabled == YES){
}
或者YES可以省略
if(enabled){
}
判断BOOL值为NO:
if(!enabled){
}
或者
if(enabled != YES){
}