1> 使用alloc、new、copy族(如mutableCopy)创建的对象,要使用release/autorelease。使用retain的对象,同样处理。没有使用这四者的,不能用release/autorelease。
// 必须release
TestClass *ptr = [[TestClass alloc] init];
...
[ptr release];
// 不用release
NSString *str;
str = [NSString stringWithFormat:@"Some string here..."];
NSLog(str);
// 使用getter得到的,不增加引用计数,所以不用release
NSString *str;
str = [TestClass firstName];
2> alloc之后立刻init
TestClass *ptr = [TestClass alloc]; // 这样写是有问题的,因为alloc有可能失败
[ptr init]
if (ptr) {
...
正确的写法:TestClass *ptr = [[TestClass alloc] init];
3> 给野指针赋空值:nil
#import "TestClass.h"
@implementation TestClass
-(NSString *) str
{
return str;
}
-(void) setStr:(NSString *)input
{
[input retain];
[str release];
str = input;
}
-(void) dealloc
{
[str release];
[super dealloc];
}
@end
#import "TestClass.h"
int main(int argc, const char * argv[])
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
TestClass *ptr = [[TestClass alloc] init];
[ptr setStr:@"Fubar"];
[ptr release];
[pool drain];
return 0;
}
上面的程序看似毫无问题,但还是有问题的。
-(void) dealloc
{
[str setStr:nil];
[super dealloc];
}
用 [str setStr:nil]
来代替 [str release]
更好,可消灭野指针,和C++是一样的道理。
注:当input为nil时,[input retain]
还是合法的调用,不会引起异常。所以调用前无需检查空指针。
另外,[str setStr:nil]
还可以写成 self.str = nil
,一样是调用setter。但不能直接写成 str = nil
,这是内存泄漏。
4> iPhone 3G 有128M的内存。但给你的App的只有大约40M。即使你只用了3M内存,也有可能收到内存警报。
5> 即使用Objective-C 2.0编程,在iPhone上也没有垃圾收集机制。
6> Objective-C runtime 不允许在栈上创建对象,只能在堆上。所以不能使用智能指针帮助管理对象资源。
7> 用autorelease要小心。内存池释放时,它们才释放。如果不小心就和内存泄漏没大区别。释放内存池会花很多时间,如果里面有几万个小对象的话。
// 这样创建的都是autorelease对象,必须由内存池释放。少用!
NSString *string = [NSString stringWithFormat:@"value = %d", intVariable];
// 使用这样的方法,可以更好地利用iPhone的内存
NSString *string = [[NSString alloc] initWithFormat:@"value = %d", intVariable];
...
[string release];
// 或者在循环的时候用autorelease对象
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
for (id item in array)
{
id anotherItem = [item createSomeAutoreleasedObject];
[anotherItem doSomethingWithIt];
}
[pool release];
另外,千万不要对autorelease对象使用release方法:程序极可能会立刻崩溃!
8> iPhone没有内存交换文件,没有虚拟内存。物理内存没有的时候,App就挂掉了。
9> 在内存报警时,即使无法释放无用内存,至少也要像下面这样:
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
}
或者在application delegate里写上一点儿:
- (void)applicationDidReceiveMemoryWarning:(UIApplication *)application
{
[[ImageCache sharedImageCache] removeAllImagesInMemory];
}
NSNotificationCenter *center = [NSNotificationCenter defaultCenter];
[center addObserver:self
selector:@selector(whatever:)
name:UIApplicationDidReceiveMemoryWarningNotification
object:nil];
- (void) whatever: (NSNotification *)note {...}
10> 申请资源时,用“懒汉策略”
@interface UITableViewControllerSubclass
{
@private
NSMutableArray *items;
DetailController *detailController;
UINavigationController *navigationController;
}
@end
@implementation UITableViewControllerSubclass
- (id)init
{
if (self = [self initWithStyle:UITableViewStylePlain])
{
// only basic stuff
items = [[NSMutableArray] alloc] initWithCapacity:20];
navigationController = [[UINavigationController alloc]
initWithRootViewController:self];
}
return self;
}
- (void)dealloc
{
[items release];
[detailController release];
[navigationController release];
[super dealloc];
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Item *item = [items objectAtIndex:indexPath.row];
if (detailController == nil) // 在需要的时候才分配内存
{
detailController = [[DetailController alloc] init];
}
detailController.item = item;
[self.navigationController
pushViewController:detailController
animated:YES];
}
...
可以使用 UIViewController 的 viewWillAppear 和 viewDidDisappear 来申请/释放资源。
可以使用 UITabBarControllerDelegate 的 tabBarController:didSelectViewController: 来进一步控制资源的加载和释放。
11> 使用正确的setter:
@interface SomeClass
{
@private
NSArray *items;
NSString *name;
id<someProtocol> delegate;
}
@property (nonatomic, retain) NSArray *items;
@property (nonatomic, copy) NSString *name;
@property (nonatomic, assign) id<someProtocol> delegate;
@end
@implementation SomeClass
@synthesize items;
@synthesize name;
@synthesize delegate;
- (void)dealloc
{
[items release];
[name release];
delegate = nil;
}
- (void)setItems:(NSArray *)obj
{
if (obj == items) {
return;
}
[items release];
items = nil; // 很重要!参数obj有可能为空
items = [obj retain];
if (items != nil) {
...
}
}
- (void)setName:(NSString *)obj
{
[name release];
name = nil;
name = [obj copy]; // NSStrings总要用copy
if (name != nil) {
...
}
}
- (void)setDelegate:(id<someProtocol>)obj
{
// 身为delegate,只需assign,不要增加引用计数
delegate = obj;
if (delegate != nil) {
...
}
}
@end
12> 正确地处理delegate的dealloc:
@interface SomeClass <WidgetDelegate>
{
@private
Widget *widget;
}
@end
@implementation SomeClass
- (id)init
{
if (id = [super init]) {
widget = [[Widget alloc] init];
widget.delegate = self;
}
return self;
}
- (void)dealloc
{
widget.delegate = nil; // delegate已经消亡,而widget未必,所以要置空,免得
[widget release]; // widget以后调用已经不存在的delegate的方法,会crash的!
[super dealloc];
}
- (void)widget:(Widget *)obj callsItsDelegate:(BOOL)value
{
// and here something happens...
}
@end
分享到:
相关推荐
因此,在执行gcore前,建议通过`top`命令查看目标进程的内存使用情况,以估算生成的核心文件大小。 - **性能影响**:gcore操作会暂时冻结进程,可能导致程序响应延迟或暂时不可用。对于实时系统或关键服务,需要...
在32位的win7系统上intel凌动CPU总共能使用的内存就是3G,再减去集成显卡占用的内存,就是2.8G可用,如果你用64位WIN7的话说不定就是3.8G可用了,但64位win7与多款软件...所以sunnyvv版主老早就建议1215n上3G内存最完美
### 指针与内存详解 #### 一、引言 在计算机编程中,指针是一种非常强大的工具,尤其在C语言这样的低级...以上内容仅是关于指针与内存的基础介绍,对于更深入的应用和技术细节,建议参考相关的进阶教程和实践指南。
这些系统不仅可以监控CPU和内存使用情况,还能监控网络流量、磁盘使用率等多个方面,并支持警报通知等功能。 #### 2.4 高级日志管理 对于日志文件,建议使用更高级的日志管理系统,如Logstash、Elasticsearch、...
在解决N皇后问题时,我们可以使用面向对象的设计思想设计一个名为Queen的类,该类具有以下几个重要的成员变量和成员函数: * 成员变量:num(表示N皇后问题的N值)、chess(表示棋盘的状态)和count(表示成功解的...
### FX2N-2AD简易使用说明 #### 一、功能说明 FX2N-2AD是一款模拟输入模块,能够接收模拟信号(电压或电流),并通过光电耦合绝缘接口将其转换为12位精度的数字数值,供FX2N系列PLC主机读取。与FX2N主机之间的数据...
在 AMD 平台上,内存的实际运行频率可以通过分频系数 N 来计算,分频系数 N 的计算方法是:N=CPU 默认主频 / 内存标称频率,得到的数值再用"进一法"取整数。然后,内存实际运行频率 F=CPU 主频 / 分频系数 N。 本文...
它可以比较两个内存区间前n个字节的内容。函数原型为: int bcmp ( const void *s1, const void *s2, int n ); 其中,s1和s2是要比较的两个内存区间,n是要比较的字节数。如果n为0,则返回0。函数返回值为0表示两...
6. 接着创建Linux-Swap分区,通常建议不超过96M,用于虚拟内存。 7. 指定分区类型为主分区,并选择相应的文件系统类型(EXT3和Linux交换分区)。 8. 不分配盘符,避免在系统中显示额外的驱动器。 9. 提交并执行分区...
具体来说,在这个问题中,有n个人按编号1至n围坐成一圈。从指定的某个人开始报数,数到指定数字m时,这个人就被淘汰出局。接下来,从被淘汰者的下一个人重新开始报数,数到m的人继续出局,如此循环直至所有人被淘汰...
描述中提到项目尚未完成,缺少Visio结构说明文档和使用说明,这表明这是一个正在开发中的项目,代码可能不完整,不建议未经了解直接使用。 标签“内存字典”进一步明确了我们关注的核心技术点,即如何在内存中高效...
叶金荣在其分享《高效MySQL的N个习惯》中提出了几个关键点来帮助MySQL保持高效运行,这些习惯包括使用优质的硬件、优化操作系统配置、编写优秀的DDL与SQL语句等。本文将详细探讨这些内容。 #### 二、使用更好的硬件...
在Java中,为了更好地管理和优化内存,我们可以使用一系列的JVM参数来调整各个内存区域的大小和其他行为。以下是一些常用的JVM参数及其含义: 1. **堆设置**: - `-Xms`: 设置初始堆大小。通常建议初始堆大小和...
该程序将从键盘读取用户输入的N值,然后使用一个循环来计算N!的结果,最后将结果显示在显示器上。 在设计项目的实现过程中,我们将遇到一些挑战和难点,例如如何将结果保存在内存缓冲区中,如何实现高级语言中的...
总结,戴尔N4020和N4030系列笔记本的拆机流程主要包括电池、光驱、硬盘、内存、键盘、无线网卡小板、C壳、屏幕、风扇以及CPU的拆卸和安装。这些步骤对熟悉电脑硬件的用户来说是可操作的,但务必小心谨慎,避免对设备...
在实际开发中,建议采用一些自动化工具辅助检测内存泄漏,并结合良好的编程习惯,如在多分支语句中始终释放内存、正确使用`new`和`delete`操作符、为多态基类声明虚拟析构函数等,以降低内存泄漏的风险。
在音频功能方面,ITX-N29集成了ALC662六声道高保真音频控制器,支持MIC、Line_out和功放功能,功放使用建议采用3Ω2W的喇叭。在存储方面,ITX-N29提供了一个SATA硬盘接口,支持SATA和SSD硬盘,还有一个Mini-PCIE插槽...
同时,非官方的固件可能会导致保修失效,甚至带来未知风险,所以建议使用官方发布的固件版本。 总的来说,"TL-WR886N 宝蓝V6.0原厂编程器固件2M"是一个重要的软件组件,对于维持和提升TL-WR886N路由器的性能和安全...