雨雪霏霏 – iPhone博客

Posts Tagged ‘iPhone

08 Sep, 2010

iOS内存管理系列之二:自动释放与便捷方法

Posted by: 雨雪霏霏 In: iPhone

本系列文章版权归李晨所有,出版权归华章公司所有,谢绝转载。 —–自动释放(Auto release)与便捷方法(convenience method)—– 有时候一个所有者创建一个对象后,会立刻将该对象的指针传递给其它所有者。这时,这个创建者不希望再拥有这个对象,但如果立刻给它发送一个release消息会导致这个对象被立刻释放掉——这样其它所有者还没有来得及保留该对象。解决这个两难问题的方法是,给对象发送一个autorelease消息:这样创建者不再拥有该对象的所有权;该对象成为自动释放的对象,但是不会立刻被释放掉;其它所有者可以有时间保留或复制该对象,并成为其唯一所有者。 我们来看一个自动释放的例子(代码清单3-1)。一个所有者先用alloc方法创建一个对象;此时该所有者拥有这个对象,对象的引用计数为1。紧接着,所有者自动释放该对象;所有者此时已经放弃了所有权,但对象的引用计数在一段时间内依然为1。我们可以看出自动释放的另一个好处:你不会因为在后面忘记给对象发送release消息而造成内存泄露。 代码清单3-1 -(Object*)returnAutoreleaseObject { Object* obj = [[Object alloc] init]; return [obj autorelease]; } 与自动释放相关的,有一大类构造方法(constructor method),由它们构造的对象直接就是自动释放的对象;这一类构造方法叫做便捷方法。比如下面这句的字符串就是一个自动释放的对象,stringWithFormat:就是一个便捷方法。 NSString* string = [NSString stringWithFormat:@”autoreleaseString”]; 再举几个便捷方法的例子,方便读者以后的开发。 1.NSArray的arrayWithObjects:和arrayWithArray:。 2.UIImage的imageNamed:。 3.NSNumber的numberWithBool等。 现在我们已经解释了,autorelease方法会在一段时间以后释放掉一个对象,在这段时间内我们可以安全地使用该对象。那么这段时间究竟是多久呢?我们需要先更多地了解自动释放的机制,再来回答这个问题。 让我们先来看看自动释放池。自动释放池是NSAutoreleasePool的实例,其中包含了收到autorelease消息的对象。当一个自动释放池自身被销毁(dealloc)时,它会给池中每一个对象发送一个release消息(如果你给一个对象多次发送autorelease消息,那么当自动释放池销毁时,这个对象也会收到同样数目的release消息)。可以看出,一个自动释放的对象,它至少能够存活到自动释放池销毁的时候。 那么自动释放池何时被创建,又何时被销毁呢?在每一个事件周期(event cycle)的开始,系统会自动创建一个自动释放池;在每一个事件周期的结尾,系统会自动销毁这个自动释放池。一般情况下,你可以理解为:当你的代码在持续运行时,自动释放池是不会被销毁的,这段时间内你也可以安全地使用自动释放的对象;当你的代码运行告一段落,开始等待用户输入(或者其它事件)时,自动释放池就会被释放掉,池中的对象都会收到一个release消息,有的可能会因此被销毁。 到此为止,相信你已经对自动释放的机制有了一个大体的了解。自动释放而非直接释放,可以帮助你节省一些代码量,提高开发速度。但是它有一个直接的缺点:它延缓了对象的释放,在有大量自动释放的对象时,会占用大量内存资源。因此,你需要避免将大量对象自动释放。并且,在以下两种情况下,你需要手动建立并手动销毁掉自动释放池: 1.当你在主线程外开启其它线程时:系统只会在主线程中自动生成并销毁掉自动释放池。 2.当你在短时间内制造了大量自动释放对象时:及时地销毁有助于有效利用iPad上有限地内存资源。

18 Aug, 2010

iOS内存管理系列之一:对象所有权与引用计数

Posted by: 雨雪霏霏 In: iPhone

内存管理是iPhone或iPad开发中最为重要的一部分。掌握好了内存管理,开发出的应用就能运行流畅;掌握不好,开发出的东西就会效率低下,且容易崩溃。从本文开始,我将分几次详细介绍iOS内存管理的方方面面,包括对象的所有权与引用计数、自动释放与便捷方法、访问器方法与属性、一些会改变引用计数的特殊情况、以及一个总结。希望这些介绍会对开发者有所帮助。 本系列文章版权归李晨所有,出版权归华章公司所有,谢绝转载。 -----对象所有权(ownership)与引用计数(retain count、reference count)----- 当一个所有者(owner,其本身可以是任何一个Objective-C对象)做了以下某个动作时,它拥有对一个对象的所有权(ownership): 1. 创建一个对象。包括使用任何名称中包含“alloc”、“new”、或者“copy”的方法。 2. 保留(retain)一个对象。 一个对象可以有多个所有者,一个所有者也可以拥有多个对象。 相应的,引用计数增减的基本规则是: 1.当所有者创建一个对象时,该对象的引用计数为1。 2.当所有者保留它时,该对象的引用计数加1。 3.当所有者释放(release)它时,该对象的引用计数减1。 与此相关的,当一个所有者对于一个对象的引用计数的增减总计为0时,它放弃了对这个对象的所有权。 现在我们可以从两个不同的角度来看Objective-C的内存管理问题。从对象所有权的角度来看,当一个对象有着至少一个所有者(owner)的时候,它依然存在;当它没有任何所有者的时候,它会被释放掉。从引用计数的角度看,一个对象存在时,其引用计数大于零;当一个对象的引用计数为零时,它会调用dealloc方法并释放掉。这两个角度的关系是:在所有权的背后起作用的机制是引用计数机制;我们通过引用计数的增减来理解所有权的概念;但是你只应当使用所有权的概念来管理内存,因为如果你试图直接获取对象的引用计数,那么得到的数将让你感到匪夷所思——系统的一些框架会“偷偷”增减对象的引用计数。 回顾一下,内存管理的目标是:当一个对象的某个所有者依然需要使用它时,保证这个对象的存在;当一个对象的所有所有者都不再需要它时,保证这个对象被销毁。因此只要任何一个所有者在使用完一个对象之后释放掉它,那么以上内存管理的目标就可以实现。我们可以得出任何一个所有者(记住,所有者本身也只是一个对象)所应当遵守的基本步骤: 拥有一个对象 -> 使用一个对象 -> 放弃对象的所有权。 从引用计数的角度来看就是: 还需要这个对象时,保持对其增减为正;不再需要这个对象时,保持对其增减为0。 下图很好地诠释了这些基本规则:所有者1和所有者2单独地执行了拥有对象、使用对象、放弃对象所有权的步骤;当所有者1不再需要该对象时及时放弃了所有权,但此时所有者2依然拥有该对象,因此该对象依然存在,所有者2可以继续使用它;当所有者2也不再需要该对象时,也放弃掉所有权,这时对象以不再有任何所有者(相应的引用计数也变为0),因此立刻被销毁掉。 需要注意的是,所有者2只是复制了该对象的指针,并没有使用copy方法,因此复制指针这个操作本身并不增加对象的引用计数;而正因为所有者2希望能使用该对象,因此通过retain方法成为它的所有者,也保证了所有者1放弃该对象时,对象不被销毁。

13 Aug, 2010

为你的iPhone/iPad游戏设置Openfeint(支持Cocos2d)

Posted by: 雨雪霏霏 In: iPhone

今天为我的iPhone游戏添加了Openfeint功能。有不少相关设置,花了我不少时间;发上来希望能对大家有所帮助。完成以下步骤后,你应当能看到下面的Openfeint界面! 简介:Openfeint是一个在线游戏系统,用于iPhone或者iPad游戏计分、挑战、多人对战等。可以在官网免费下载它的SDK。 环境:Openfeint 2.5.1,XCode 3.2.3,iPhone SDK 4.0,Cocos 2d 0.94。 步骤: 1. 将下载好的Openfeint文件夹加入工程之中。 2. 移除其中不需要的文件夹 - 如果你的游戏只支持landscape或者只支持iPad,移除iPhone_Portrait文件夹 - 如果你的游戏只支持Portrait或者只支持iPad,移除iPhone_Landscape文件夹 - 如果你的游戏不支持iPad,移除iPad文件夹 3. 在Project Settings中, - 选择Build页,Configuration设置为All Configurations - 找到Other Linker Flags,设置为 -ObjC - 确保Call C++ Default Ctors/Dtors in Objective-C被打了钩   4. 添加以下framework * Foundation* UIKit* CoreGraphics* QuartzCore* Security* SystemConfiguration* libsqlite3.0.dylib (located in (iPhoneSDK Folder)/usr/lib/)* CFNetwork* CoreLocation* MapKit [...]

24 Jun, 2010

雨雪霏霏 – iPhone博客 正式推出移动版!

Posted by: 雨雪霏霏 In: iPhone

请大家在手机上看雨雪霏霏的iPhone博客,效果很不一样,很赞哦!标题、日期、评论数目、分类,均一目了然。点进每一篇文章后,文章内容格式均很棒。在此感谢WPTouch,是它使得这一切成为可能。

22 Jun, 2010

NSLog:既是天使也是魔鬼

Posted by: 雨雪霏霏 In: iPhone

相信所有的iPhone开发者都曾经或者将会用到NSLog这个函数。NSLog的强大之处在于,它能在代码运行过程中显示变量值以及程序实际走向,能帮助我们发现大量错误和潜在风险。我们希望尽可能多的用到NSLog,希望它能无处不在,使得错误无法存在——简单的说NSLog是一个天使。 比如下面这段代码就利用NSLog,在程序运行时判断设备种类并显示出来 NSString *deviceType = [UIDevice currentDevice].model;NSLog(@”device type: %@.”, deviceType); 使用NSLog的一个风险是:它的运行会占用时间和设备资源。当我们用Simulator时,NSLog的资源占用并不引人注意,风险也不会显示出来。但是如果你写的是一个即时战略游戏,而你在每一个action中都加入了NSLog——那么NSLog将成为一个魔鬼。灾难的具体表现常常是:你在Simulator中运行游戏畅通无阻,但到了真机上,会发现很“卡”,不论是拖动一个单位还是缩放一个场景,FPS也降到了各位数。 简单而粗暴的解决方案是:在一个游戏release前,将所有的NSLog注释掉。简单有效,但副作用是:下次你要调试时,又得将NSLog一个个取消注释。 我找到了一个最为有效的解决方案:你以release模式编译的程序不会用NSLog输出,而你以debug模式编译的程序将执行NSLog的全部功能。 #ifndef __OPTIMIZE__ # define NSLog(…) NSLog(__VA_ARGS__) #else # define NSLog(…) {} #endif 代码来源 这个代码的魔术在于:release模式通常会定义 __OPTIMIZE__,当然debug模式不会。将这段代码放在你的头文件当中,你就可以放心的使用NSLog了!


About

About Google, about Apple, about phones and browsers, about science and technologies.

Subscribe
Page 1 of 612345...Last »