Interface Builder参与的内存管理问题
I 要点:
- 如果一个变量在类中被定义为了 IBOutlet 那么你无需对其进行实例化,xib载入器会对其初始化。
- 如果一个变量在类中被定义为了 IBOutlet 那么你必须负责将其释放。xib载入器不会帮忙的… …
*切不要初始化两回,内存会溢出,而且对象锁定也会出错。
IPhone, Cocoa, PHP, Javascript, JQuery, Actionscript, etc…
Archive for 六月 2009
I 要点:
*切不要初始化两回,内存会溢出,而且对象锁定也会出错。
M 答案是”可以的”,MVC要点:

M *retain值 = 索引计数(Reference Counting)
T 多线程编程是防止主线程堵塞,增加运行效率等等的最佳方法。而原始的多线程方法存在很多的毛病,包括线程锁死等。在Cocoa中,Apple提供了NSOperation这个类,提供了一个优秀的多线程编程方法。
本次介绍NSOperation的子集,简易方法的NSInvocationOperation:
@implementation MyCustomClass - (void)launchTaskWithData:(id)data { //创建一个NSInvocationOperation对象,并初始化到方法 //在这里,selector参数后的值是你想在另外一个线程中运行的方法(函数,Method) //在这里,object后的值是想传递给前面方法的数据 NSInvocationOperation* theOp = [[NSInvocationOperation alloc] initWithTarget:self selector:@selector(myTaskMethod:) object:data]; // 下面将我们建立的操作“Operation”加入到本地程序的共享队列中(加入后方法就会立刻被执行) // 更多的时候是由我们自己建立“操作”队列 [[MyAppDelegate sharedOperationQueue] addOperation:theOp]; } // 这个是真正运行在另外一个线程的“方法” - (void)myTaskMethod:(id)data { // Perform the task. } @end
一个NSOperationQueue 操作队列,就相当于一个线程管理器,而非一个线程。因为你可以设置这个线程管理器内可以并行运行的的线程数量等等。下面是建立并初始化一个操作队列:
@interface MyViewController : UIViewController { NSOperationQueue *operationQueue; //在头文件中声明该队列 } @end @implementation MyViewController - (id)init { self = [super init]; if (self) { operationQueue = [[NSOperationQueue alloc] init]; //初始化操作队列 [operationQueue setMaxConcurrentOperationCount:1]; //在这里限定了该队列只同时运行一个线程 //这个队列已经可以使用了 } return self; } - (void)dealloc { [operationQueue release]; //正如Alan经常说的,我们是程序的好公民,需要释放内存! [super dealloc]; } @end
简单介绍之后,其实可以发现这种方法是非常简单的。很多的时候我们使用多线程仅仅是为了防止主线程堵塞,而NSInvocationOperation就是最简单的多线程编程,在iPhone编程中是经常被用到的。
@property (copy, nonatomic) NSString *title;
什么是assign,copy,retain之间的区别?
retain的实际语法为:
- (void)setName:(NSString *)newName { if (name != newName) { [name release]; name = [newName retain]; // name’s retain count has been bumped up by 1 } }
说了那么麻烦,其实接下来的话最重要:
?如果你不懂怎么使用他们,那么就这样 ->
nonatomic关键字:
atomic是Objc使用的一种线程保护技术,基本上来讲,是防止在写未完成的时候被另外一个线程读取,造成数据错误。而这种机制是耗费系统资源的,所以在iPhone这种小型设备上,如果没有使用多线程间的通讯编程,那么nonatomic是一个非常好的选择。
CS193P的笔记上有如下实例:
aString = @"I am a string that 2 years old, man!";
这种情况下,字符串储存和管理由系统做,我们不用操心。
aString = [NSString stringWithFormat:@"I am a string that %d years old, man!",2];
第二种情况下,我们需要去retain和release这个字符串,系统不管。
1,你初始化(alloc/init)的对象,你需要释放(release)它。例如:
NSMutableArray aArray = [[NSArray alloc] init];
后,需要
[aArray release];
2,你retain或copy的,你需要释放它。例如:
[aArray retain]
后,需要
[aArray release];
3,被传递(assign)的对象,你需要斟酌的retain和release。例如:
obj2 = [[obj1 someMethod] autorelease];
对象2接收对象1的一个自动释放的值,或传递一个基本数据类型(NSInteger,NSString)时: 你或希望将对象2进行retain,以防止它在被使用之前就被自动释放掉。但是在retain后,一定要在适当的时候进行释放。
M 在看过CS193P的笔记后,以下是真正有用的句子:
dealloc不等于C中的free,dealloc并不将内存释放,也不会将索引计数(Reference counting)降低。于是直接调用dealloc反而无法释放内存。
在Objective-C中,索引计数是起决定性作用的。
I 在CS193P中,Evan强调了以下问题:
为什么要在覆盖init的时候需要检查是否在父类中作初始化,例如:
- (id)init { if(self = [super init]) { } }
或
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil { if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) { // Custom initialization } return self; }
主要是将本地对象用父类的init进行初始化,其中的等号“=”另一方面检查了是不是成功进行了初始化。CS193P提供了更多关于这个的信息:
http://cocoadev.com/index.pl?FactoryMethod
-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-
不仅仅是init等初始化对象,还有其他一些方法(Method)是需要对自己的父类打声招呼得,例如:
- (void)viewDidLoad { [super viewDidLoad]; }
那这个没有super这句会怎么样呢?没事,一样用。这个是一个delegate,所以需要收听的类应该会收听到的。但是既然缺省的方法就是这么写的,我们也没有必要特意去删除掉这个super方法。