关于iPhone:在编写Objective-C和Cocoa时,您使用的最佳实践是什么?

What are best practices that you use when writing Objective-C and Cocoa?

我知道希格粒子(这非常方便!)但是,在编写Objective-C时使用什么编程实践,更具体地说,在使用Cocoa(或CocoAtouch)时使用什么编程实践。


我开始做一些我认为不标准的事情:

1)随着属性的出现,我不再使用"u"作为"private"类变量的前缀。毕竟,如果一个变量可以被其他类访问,那么它是否应该有一个属性?我一直不喜欢"uuu"前缀使代码更丑,现在我可以把它删掉了。

2)说到私有事物,我更喜欢将私有方法定义放在.m文件中的类扩展名中,如下所示:

1
2
3
4
5
6
7
8
#import"MyClass.h"

@interface MyClass ()
- (void) someMethod;
- (void) someOtherMethod;
@end

@implementation MyClass

为什么把外人不关心的东西乱放在.h文件中?空()适用于.m文件中的私有类别,如果不实现声明的方法,则会发出编译警告。

3)我把dealloc放在.m文件的顶部,刚好在@synthesis指令的下面。你所处理的事情不应该是你想在课堂上思考的事情中最重要的吗?在iPhone这样的环境中尤其如此。

3.5)在表格单元格中,使每个元素(包括单元格本身)不透明以提高性能。这意味着在每件事情中设置适当的背景色。

3.6)当使用nsurlconnection时,通常您可能希望实现委托方法:

1
2
3
4
5
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
                  willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
      return nil;
}

我发现大多数Web调用都是非常单一的,这比您希望缓存响应的规则更为例外,尤其是对于Web服务调用。如图所示实现方法将禁用响应的缓存。

另外,还有来自Joseph Mattiello(在iPhone邮件列表中收到)的一些针对iPhone的好提示。还有很多,但这些都是我认为最有用的(注意,现在已经从原始文件中稍微编辑了一些内容,以包含响应中提供的详细信息):

4)如果必须使用双精度,例如使用CoreLocation时。确保在"f"中结束常量,以使gcc将其存储为float。

1
float val = someFloat * 2.2f;

someFloat实际上是一个双精度数时,这一点非常重要,因为您在"val"中的存储精度正在下降,所以不需要混合模式数学。虽然在iPhone的硬件中支持浮点数字,但与单精度相比,执行双精度运算可能需要更多的时间。参考文献:

  • iPhone上的双浮
  • iPhone/iPad双精度数学

在老式手机上,假设计算的速度是一样的,但寄存器中的单精度元件可以比双精度元件多,因此对于许多计算,单精度最终会更快。

5)将属性设置为nonatomic。默认情况下,它们是atomic,合成后,将创建信号量代码以防止多线程问题。99%的人可能不需要担心这一点,而且当设置为非原子代码时,代码的膨胀要小得多,内存效率也要高得多。

6)sqlite可以非常、非常快速地缓存大型数据集。例如,地图应用程序可以将其图块缓存到sqlite文件中。最昂贵的部分是磁盘I/O。通过在大数据块之间发送BEGIN;COMMIT;,避免许多小的写入。例如,我们使用一个2秒的计时器,在每次新提交时重置。当它过期时,我们将发送commit;,这将导致您的所有写操作都集中在一个大块中。sqlite将事务数据存储到磁盘,这样做可以避免创建许多事务文件,将所有事务分组到一个文件中。

另外,如果GUI在主线程上,SQL也会阻塞它。如果查询非常长,最好将查询存储为静态对象,并在单独的线程上运行SQL。确保在@synchronize() {}块中包装修改数据库查询字符串的任何内容。对于短查询,只需在主线程上留下一些东西,以方便使用。

这里有更多的sqlite优化提示,尽管文档看起来已经过时了,但其中许多要点可能仍然很好;

http://web.utk.edu/~jplyon/sqlite/sqlite_optimization_faq.html


不要将未知字符串用作格式字符串

当方法或函数采用格式字符串参数时,您应该确保您可以控制格式字符串的内容。

例如,在记录字符串时,将字符串变量作为唯一参数传递给NSLog

1
2
    NSString *aString = // get a string from somewhere;
    NSLog(aString);

问题在于字符串可能包含被解释为格式字符串的字符。这可能导致错误的输出、崩溃和安全问题。相反,您应该将字符串变量替换为格式字符串:

1
    NSLog(@"%@", aString);


使用标准的Cocoa命名和格式化约定和术语,而不是从其他环境中使用的任何内容。现在有很多Cocoa开发人员,当他们中的另一个开始使用您的代码时,如果它看起来和感觉与其他Cocoa代码相似,那么它将更加容易接近。

做什么和不做什么的例子:

  • 不要在对象的接口中声明id m_something;并将其称为成员变量或字段;使用something_something作为其名称并将其称为实例变量。
  • 不要给一个getter命名为-getSomething;正确的cocoa名称只是-something
  • 不要给setter命名为-something:;它应该是-setSomething:
  • 方法名中穿插了参数并包含冒号;它是-[NSObject performSelector:withObject:],而不是NSObject::performSelector
  • 在方法名、参数、变量、类名等中使用大写(camelcase),而不是在底线(下划线)中使用。
  • 类名以大写字母开头,变量名和方法名以小写字母开头。

无论您做什么,都不要使用win16/win32风格的匈牙利符号。甚至微软也放弃了这一点,转而使用.NET平台。


伊布斯特

历史上,插座的内存管理一直很差。当前的最佳实践是将出口声明为属性:

1
2
3
4
5
@interface MyClass :NSObject {
    NSTextField *textField;
}
@property (nonatomic, retain) IBOutlet NSTextField *textField;
@end

使用属性使内存管理语义清晰;如果使用实例变量合成,它还提供一致的模式。


使用llvm/clang静态分析器

注意:在Xcode4下,现在它内置在IDE中。

你可以使用CLAN静态分析器——毫不奇怪地——在Mac OS X 10.5上分析C和Objul-C代码(没有C++)。安装和使用很简单:

  • 从此页下载最新版本。
  • 从命令行cd到项目目录。
  • 执行scan-build -k -V xcodebuild
  • (还有一些附加的约束等,特别是您应该在"调试"配置中分析一个项目——有关详细信息,请参阅http://clang.llvm.org/staticanalysiususage.html——但这或多或少就是它的归宿。)

    然后分析器为您生成一组网页,显示可能的内存管理和编译器无法检测到的其他基本问题。


    这是一个方便的subtle but one。如果你通过自己授予to another as a,s代表对象,object'复位之前你dealloc。P></

    1
    2
    3
    4
    5
    6
    7
    - (void)dealloc
    {
    self.someObject.delegate = NULL;
    self.someObject = NULL;
    //
    [super dealloc];
    }

    做中学,这不代表你保障方法将得到我的黑莓。当你和一deallocabout to滚开你想让sure that醚can send你没有任何更多的信息模式的事故。记得self.someobject是retained by another对象(它是在单件或任何autorelease or on the池)和直到你告诉它"停止发送我的消息。"恩,你只是认为它-好- dealloced对象是公平的游戏。P></

    这个习惯会让你从保存在许多of that are a Weird崩溃痛苦去调试。P></

    委托applies key value to the same观察和nsnotifications,太。P></

    编辑:P></

    甚至更多的防守,变化:P></

    1
    self.someObject.delegate = NULL;

    为:P></

    1
    2
    if (self.someObject.delegate == self)
        self.someObject.delegate = NULL;


    "尼尔P></

    :instead ofP></

    1
    2
    3
    4
    @interface MyClass (private)
    - (void) someMethod
    - (void) someOtherMethod
    @end

    使用:P></

    1
    2
    3
    4
    @interface MyClass ()
    - (void) someMethod
    - (void) someOtherMethod
    @end

    纽约在Objective-C 2.0。P></

    苹果是在S级扩展描述的程序办理参考Objective-C 2.0。P></

    "让你额外的类来扩展API for a class宣布在其他位置比在初级班块"接口"P></

    我知道他们part of the actual and not a级(私人)在加成to the class category。差分subtle but important。P></


    避免自动释放

    由于您通常(1)无法直接控制它们的生存期,因此自动释放的对象可以持续相当长的时间,并且不必要地增加应用程序的内存占用。虽然在桌面上这可能影响不大,但在更受限的平台上,这可能是一个重要问题。因此,在所有平台上,尤其是在更受约束的平台上,最好不要使用会导致自动释放对象的方法,而是鼓励您使用alloc/init模式。

    因此,而不是:

    1
    aVariable = [AClass convenienceMethod];

    如果可以,您应该使用:

    1
    2
    3
    aVariable = [[AClass alloc] init];
    // do things with aVariable
    [aVariable release];

    在编写返回新创建的对象的方法时,可以利用cocoa的命名约定向接收者标记必须通过在方法名称前面加上"new"来释放该对象。

    因此,不是:

    1
    2
    3
    4
    5
    - (MyClass *)convenienceMethod {
        MyClass *instance = [[[self alloc] init] autorelease];
        // configure instance
        return instance;
    }

    你可以写:

    1
    2
    3
    4
    5
    - (MyClass *)newInstance {
        MyClass *instance = [[self alloc] init];
        // configure instance
        return instance;
    }

    由于方法名以"new"开头,所以API的使用者知道他们负责释放接收到的对象(例如,请参见nsObjectController的newObject方法)。

    (1)您可以使用自己的本地自动释放池来控制。有关更多信息,请参阅自动释放池。


    其中一些已经提到过,但下面是我能想到的:

    • 遵循kvo命名规则。即使你现在不使用kvo,根据我的经验,它在未来仍然是有益的。如果您使用的是kvo或绑定,那么您需要知道事情正在按照预期的方式进行。这不仅包括访问器方法和实例变量,还包括许多关系、验证、自动通知依赖键等。
    • 将私有方法放入类别中。不仅是接口,还包括实现。在概念上,在私有方法和非私有方法之间保持一定距离是很好的。我的.m文件中包含了所有内容。
    • 将后台线程方法放在类别中。同上。我发现,当你在思考什么是主线,什么不是主线时,保持一个清晰的概念障碍是很好的。
    • 使用#pragma mark [section]。通常我用自己的方法分组,每个子类的覆盖,以及任何信息或正式协议。这使得我更容易找到我想要的东西。在同一个主题上,将类似的方法(如表视图的委托方法)分组在一起,不要将它们粘在任何地方。
    • 在private methods&ivars前面加上。我喜欢它的外观,当我无意中指的是财产时,我不太可能使用IVAR。
    • 不要在init&dealloc中使用mutator方法/属性。我从来没有因为它而发生过任何不好的事情,但是如果你改变方法来做一些依赖于对象状态的事情,我可以看到逻辑。
    • 将iboutlets放入属性。我刚刚在这里读了这本书,但我要开始读了。不管记忆有什么好处,它看起来更时尚(至少对我来说)。
    • 避免编写完全不需要的代码。这真的涵盖了很多事情,比如在#define将要做的时候生成ivar,或者在每次需要数据时缓存数组而不是对其进行排序。关于这一点,我有很多话可以说,但底线是在您需要代码之前不要编写代码,否则探查器会告诉您。从长远来看,它使维护变得容易得多。
    • 完成你开始的。有很多半成品,有缺陷的代码是最快的方式杀死一个项目死亡。如果你需要一个很好的存根方法,只要把NSLog( @"stub" )放在里面就可以了,或者不管你想怎么做都可以。


    写单元测试。你可以测试很多事情会在学院努力在其他可可那间好。for example,与IU的尾巴,你可以generally verify that they should be as things are连通和信托,他们工作when used。你可以集上被授予easily &;试验方法invoke to them。P></

    你也不要有私人和公共和保护的方式进入法学院,能见度测试internals换你的写作。P></


    金科玉律:如果你是alloc,那么你就是release

    更新:除非使用ARC


    不要编写Objto-C,就好像它是Java/C/C/C++等。

    我曾经见过一个团队,用来编写JavaEE Web应用程序,试图编写一个可可桌面应用程序。就好像它是一个JavaEE Web应用程序一样。有很多抽象的foofactory和foofactory,以及ifoo和foo四处飞来飞去,而它们真正需要的只是一个foo类,可能还有一个foooable协议。

    确保你不这样做的一部分是真正理解语言的差异。例如,您不需要上面的抽象工厂类和工厂类,因为Objective-C类方法和实例方法一样动态地被调度,并且可以在子类中被重写。


    请确保将调试魔法页面加入书签。这应该是你在寻找可可虫源头时头撞到墙上的第一站。

    例如,它将告诉您如何找到您第一次分配内存的方法,而该方法随后会导致崩溃(如在应用程序终止期间)。


    现在我试着avoid have to newbiecategoryaholism决定的呼叫。newcomers to when they often categories发现Objective-C去猪野小,每级增useful to在存在(categories"什么?我add a method to convert to a number to罗马numerals在线")nsnumber摇滚!。P></

    不给你这个。P></

    你会更多的便携式easier队列超时和了解与dozens of category方法在线小sprinkled打基础顶部的两类。P></

    most of the time when你真想You need a category method to find some help流线端尾巴上你你不重用the method。P></

    there are other dangers太你,除非你namespacing(the category的方法和校正besides utterly ddribin是谁?)苹果的机会,there is something or,or else插件在运行,也将在你的地址空间定义category method with the same the same name与slightly端效应不同。P></

    好吧。现在,你已经warned ignore the",本部分不给。"但极端运动抑制。P></


    根据用户需要对字符串排序

    当排序要呈现给用户的字符串时,不应使用简单的compare:方法。相反,您应该始终使用本地化比较方法,如localizedCompare:localizedCaseInsensitiveCompare:

    有关详细信息,请参阅搜索、比较和排序字符串。


    抵制将世界划分为子类。在cocoa中,很多工作是通过委托和使用底层运行时完成的,而在其他框架中,则是通过子类化完成的。

    例如,在Java中,大量使用匿名EDCOX1和0个子类的实例,在.NET中,您大量使用EDCOX1和1个子类。在Cocoa中,你也不会这样做——而是使用目标动作。


    声明的属性

    您通常应该对所有属性使用Objective-c2.0声明的属性功能。如果它们不是公共的,请将它们添加到类扩展中。使用已声明的属性可以立即清除内存管理语义,并使检查DealLoc方法更加容易——如果将属性声明分组在一起,可以快速扫描它们并与DealLoc方法的实现进行比较。

    在不将属性标记为"非原子"之前,您应该仔细考虑。正如目标C编程语言指南所指出的,默认情况下属性是原子的,并且会产生相当大的开销。此外,简单地将所有属性设置为原子属性并不能使应用程序线程安全。当然,还要注意,如果不指定"非原子"并实现自己的访问器方法(而不是合成它们),则必须以原子方式实现它们。


    使用nsassert和朋友。我一直使用nil作为有效对象…尤其是向nil发送消息在obj-c中是完全有效的。但是,如果我真的想确定一个变量的状态,我使用nsassert和nsparametersert,这有助于轻松地跟踪问题。


    考虑零值

    正如这个问题所指出的那样,发送给nil的消息在objective-c中是有效的。虽然这通常是一个优势——导致更干净和更自然的代码——但是如果您在不期望的情况下得到nil值,这个特性有时会导致特殊和难以跟踪错误。


    简单但经常被遗忘。根据规范:

    In general, methods in different
    classes that have the same selector
    (the same name) must also share the
    same return and argument types. This
    constraint is imposed by the compiler
    to allow dynamic binding.

    在这种情况下,即使在不同的类中,所有相同的命名选择器也将被视为具有相同的返回/参数类型。下面是一个简单的例子。

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    @interface FooInt:NSObject{}
    -(int) print;
    @end

    @implementation FooInt
    -(int) print{
        return 5;
    }
    @end

    @interface FooFloat:NSObject{}
    -(float) print;
    @end

    @implementation FooFloat
    -(float) print{
        return 3.3;
    }
    @end

    int main (int argc, const char * argv[]) {

        NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];    
        id f1=[[FooFloat alloc]init];
        //prints 0, runtime considers [f1 print] to return int, as f1's type is"id" and FooInt precedes FooBar
        NSLog(@"%f",[f1 print]);

        FooFloat* f2=[[FooFloat alloc]init];
        //prints 3.3 expectedly as the static type is FooFloat
        NSLog(@"%f",[f2 print]);

        [f1 release];
        [f2 release]
        [pool drain];

        return 0;
    }


    如果您使用Leopard(Mac OS X 10.5)或更高版本,则可以使用Instruments应用程序查找和跟踪内存泄漏。在Xcode中构建程序之后,选择运行>从性能工具开始>泄漏。

    即使你的应用程序没有显示任何泄漏,你可能把物体放在周围太久了。在Instruments中,可以为此使用ObjectAlloc工具。在Instruments文档中选择ObjectAlloc Instrument,然后通过选择View>Detail(查看>详细信息)(它旁边应该有一个复选标记)来显示仪器的详细信息(如果尚未显示)。在"ObjectAlloc详细信息"中的"分配寿命"下,确保选择"已创建并仍在使用"旁边的单选按钮。

    现在,每当您停止记录应用程序时,选择ObjectAlloc工具将在"net"列中显示应用程序中每个静止对象的引用数。确保您不仅查看自己的类,还查看NIB文件的顶级对象的类。例如,如果屏幕上没有窗口,并且您看到对仍在运行的nswindow的引用,那么您可能没有在代码中释放它。


    在dealloc开始清理。P></

    This is one of the things to easiest忘记- AT 150mph ESP。当编码。总是,总是,总是检查你的清洁成员在dealloc变量/属性。P></

    我使用的是2 - objc with the New点位置让我知道this the无痛的清理。often as simple as:P></

    1
    2
    3
    4
    5
    - (void)dealloc
    {
        self.someAttribute = NULL;
        [super dealloc];
    }

    这会来照顾你和释放为零(which to set the属性防御的设计考虑在一家dealloc唐氏法在固体聚合物accesses继续发生罕见但可以变了)。P></

    在线色谱在10.5和批判,这不需要任何更多的,但你知道我会检查need to你创建其他资源的清洁,你可以给我在the instead finalize方法。P></


    所有这些评论都很好,但我真的很惊讶没人提到不久前发布的Google的Objective-C风格指南。我认为他们做得很彻底。


    相关的话题(半也,与反应室和更多!):P></

    什么是这些小技巧你的Xcode提示&;希望你知道的关于针2年?。P></


    不要忘记nswindowcontroller和nsviewcontroller将释放它们所管理的NIB文件的顶级对象。

    如果您手动加载一个NIB文件,那么当您完成NIB的顶级对象时,您将负责释放它们。


    对于初学者来说,有一个相当明显的用法:为代码使用Xcode的自动缩进特性。即使您是从另一个源复制/粘贴代码,粘贴代码后,也可以选择整个代码块,右键单击它,然后选择重新缩进该块中的所有内容的选项。

    Xcode实际上会通过该部分进行解析,并根据括号、循环等对其进行缩进。这比为每一行点击空格键或制表键要高效得多。


    我知道我在第一次进入可可编程时忽略了这一点。

    确保您了解有关NIB文件的内存管理职责。您负责释放加载的任何NIB文件中的顶级对象。阅读苹果关于这个主题的文档。


    打开所有GCC警告,然后关闭那些经常由苹果头引起的警告,以减少噪音。

    还可以经常运行clang静态分析;您可以通过"运行静态分析器"构建设置为所有构建启用它。

    编写单元测试并在每个构建中运行它们。


    变量和属性好的。

    1/保持头部干净,隐藏实现不要在头中包含实例变量。私有变量作为属性放入类继续中。公共变量在头中声明为公共属性。如果它应该是只读的,则将其声明为read only,并在类连续性中重写为readwrite。基本上,我根本不使用变量,只使用属性。好的。

    2/给属性一个非默认变量名,例如:好的。

    1
    @synthesize property = property_;

    原因1:在分配属性时,您将捕获由于忘记"self."而导致的错误。原因2:从我的实验来看,仪器中的泄漏分析仪在用默认名称检测泄漏特性时存在问题。好的。

    3/切勿直接在财产上使用RETAIN或RELEASE(或仅在非常特殊的情况下使用)。在你的交易中,给他们分配一个零。retain属性是指自己处理retain/release。例如,您永远不知道setter是否没有添加或删除观察器。您应该只在setter和getter中直接使用变量。好的。

    意见好的。

    1/如果可以,将每个视图定义放入XIB中(例外情况通常是动态内容和层设置)。它节省了时间(比编写代码更容易),也很容易更改,并且保持了代码的整洁。好的。

    2/不要试图通过减少视图数量来优化视图。不要仅仅因为想在代码中添加子视图而在代码中创建uiImageView而不是xib。使用uiImageView作为背景。视图框架可以毫无问题地处理数百个视图。好的。

    3/iBooklets不必总是保留(或强保留)。请注意,大多数iboutlet都是视图层次结构的一部分,因此被隐式保留。好的。

    4/释放viewdidUnload中的所有iboutlets好的。

    5/从DealLoc方法调用viewdidUnload。它不是隐式调用的。好的。

    记忆好的。

    1/创建对象时自动释放对象。许多错误是由将您的发布调用移入一个if-else分支或在返回语句之后引起的。只有在特殊情况下才应使用release而不是autorelease,例如,当您在等待runloop,并且不希望您的对象过早地自动释放时。好的。

    2/即使您使用的是授权引用计数,您也必须完全理解RETAIN发布方法的工作原理。手动使用RETAIN RELEASE并不比ARC复杂,在这两种情况下,您都必须考虑泄漏和保留周期。考虑在大型项目或复杂的对象层次结构上手动使用RETAIN RELEASE。好的。

    评论好的。

    1/使代码自动记录。每个变量名和方法名都应该知道它在做什么。如果代码编写正确(您需要大量实践),则不需要任何代码注释(与文档注释不同)。算法可能很复杂,但代码应该总是简单的。好的。

    2/有时候,你需要一个评论。通常用来描述不明显的代码行为或黑客行为。如果你觉得你必须写一个注释,首先试着重写代码使其更简单,而不需要注释。好的。

    压痕好的。

    1/不要增加过多的压痕。您的大多数方法代码应该在方法级别缩进。嵌套块(if、for等)会降低可读性。如果有三个嵌套块,则应尝试将内部块放入单独的方法中。不应使用四个或更多嵌套块。如果大多数方法代码都在if中,则取消if条件,例如:好的。

    1
    2
    3
    4
    5
    if (self) {
       //... long initialization code ...
    }

    return self;
    1
    2
    3
    4
    5
    6
    7
    if (!self) {
       return nil;
    }

    //... long initialization code ...

    return self;

    理解C代码,主要是C结构好的。

    请注意,obj-c只是C语言上的一个轻量级oop层。您应该了解C中的基本代码结构是如何工作的(枚举、结构、数组、指针等)。例子:好的。

    1
    view.frame = CGRectMake(view.frame.origin.x, view.frame.origin.y, view.frame.size.width, view.frame.size.height + 20);

    相同:好的。

    1
    2
    3
    CGRect frame = view.frame;
    frame.size.height += 20;
    view.frame = frame;

    还有更多好的。

    维护自己的编码标准文档并经常更新。试着从你的错误中学习。了解为什么会创建bug,并尝试使用编码标准来避免它。好的。

    我们的编码标准目前大约有20页,混合了Java编码标准、谷歌Obj-C/C++标准和我们自己的附录。记录您的代码,在正确的地方使用标准的缩进、空格和空行等。好的。好啊。


    更实用。

    Objective-C是面向对象的语言,但是Cocoa框架的功能风格是感知的,并且在很多情况下都是设计的功能风格。

  • 变异性的分离。使用不可变类作为主要类,使用可变对象作为次要类。例如,主要使用nsarray,并且仅在需要时使用nsmutablerray。

  • 有纯粹的功能。不多,购买许多框架API都是像纯函数那样设计的。查看诸如CGRectMake()CGAffineTransformMake()之类的函数。显然,指针形式看起来更有效。但是,带有指针的间接参数不能提供无副作用。尽可能多地设计结构。分离偶数状态对象。向其他对象传递值时,使用-copy而不是-retain。因为共享状态可以悄悄地影响到其他对象中的值的变化。所以不能没有副作用。如果有来自对象的外部值,请复制它。因此,尽可能少地设计共享状态也是很重要的。

  • 但是也不要害怕使用不纯函数。

  • 有懒惰的评价。参见类似于-[UIViewController view]属性的内容。创建对象时不会创建视图。它将在调用方首次读取view属性时创建。在实际绘制之前,不会加载UIImage。这种设计有很多实现。这种设计对资源管理非常有帮助,但是如果你不知道懒惰评估的概念,就不容易理解它们的行为。

  • 这里是封闭的。尽可能使用C块。这将大大简化你的生活。但在使用块内存管理之前,请再次阅读它。

  • 有半自动GC。自动释放池。使用-autoreleaseprimary。当您真正需要时,使用手动-retain/-release辅助。(例如:内存优化、显式资源删除)


  • 苹果提供了我看到的示例,将应用程序委托视为一个全局数据存储,一个数据管理器。那是错误的。创建一个单一实例,并在应用程序委托中实例化它,但不要将应用程序委托作为除应用程序级事件处理之外的任何事情来使用。我衷心地附和了这篇博文中的建议。这根线把我弄歪了。


    只释放dealoc方法中的属性。如果要释放属性所持有的内存,只需将其设置为nil:

    1
    self.<property> = nil;


    1
    2
    3
    4
    5
    6
    7
    8
    #import"MyClass.h"

    @interface MyClass ()
    - (void) someMethod;
    - (void) someOtherMethod;
    @end

    @implementation MyClass