我知道HIG(这非常方便!),但是在编写Objective-C时,更具体地说,在使用Cocoa(或CocoaTouch)时,您使用了什么编程实践?
当前回答
使用NSAssert和朋友。 我一直使用nil作为有效对象…特别是发送消息给nil在Obj-C中是完全有效的。 然而,如果我真的想确定一个变量的状态,我使用NSAssert和NSParameterAssert,这有助于轻松跟踪问题。
其他回答
使用LLVM/Clang静态分析仪
注意:在Xcode 4中,这是内置在IDE中。
你可以使用Clang Static Analyzer在Mac OS X 10.5上分析你的C和Objective-C代码(还没有c++)。安装和使用起来很简单:
从本页下载最新版本。 从命令行,cd到您的项目目录。 执行scan-build -k -V xcodebuild。
(还有一些额外的限制等等,特别是你应该在“调试”配置中分析一个项目——详情请参阅http://clang.llvm.org/StaticAnalysisUsage.html——但这或多或少就是它的总结。)
分析器然后为您生成一组网页,显示可能的内存管理和编译器无法检测的其他基本问题。
不要把Objective-C写成Java/ c# / c++等。
我曾经看到一个编写Java EE web应用程序的团队尝试编写Cocoa桌面应用程序。就好像它是一个Java EE web应用程序。有很多AbstractFooFactory、FooFactory、IFoo和Foo,而他们真正需要的只是一个Foo类,可能还有一个Fooable协议。
确保你不这样做的部分原因是真正理解语言的差异。例如,您不需要上面的抽象工厂和工厂类,因为Objective-C类方法和实例方法一样是动态分派的,并且可以在子类中重写。
不要使用未知字符串作为格式字符串
当方法或函数接受格式字符串参数时,应确保能够控制格式字符串的内容。
例如,当记录字符串时,很容易将字符串变量作为唯一参数传递给NSLog:
NSString *aString = // get a string from somewhere;
NSLog(aString);
这样做的问题是,字符串可能包含被解释为格式字符串的字符。这可能导致错误的输出、崩溃和安全问题。相反,你应该将字符串变量替换为一个格式字符串:
NSLog(@"%@", aString);
我已经开始做的一些事情,我认为不是标准的:
1)随着属性的出现,我不再使用“_”作为“私有”类变量的前缀。毕竟,如果一个变量可以被其他类访问,不应该有一个属性吗?我一直不喜欢“_”前缀,因为它会让代码变得更丑,现在我可以把它去掉了。
2)说到私有的东西,我更喜欢把私有方法定义放在.m文件的类扩展名中,就像这样:
#import "MyClass.h"
@interface MyClass ()
- (void) someMethod;
- (void) someOtherMethod;
@end
@implementation MyClass
为什么要用外人不应该关心的东西把.h文件弄得乱七八糟呢?empty()适用于.m文件中的私有类别,如果您没有实现声明的方法,则会发出编译警告。
3)我已经开始把dealloc放在。m文件的顶部,就在@synthesize指令的下面。你在课堂上想要思考的事情不应该排在最前面吗?在iPhone这样的环境下尤其如此。
3.5)在表格单元格中,为了性能,使每个元素(包括单元格本身)都不透明。这意味着在所有内容中设置适当的背景颜色。
3.6)当使用NSURLConnection时,作为一个规则,你可能很想实现委托方法:
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse *)cachedResponse
{
return nil;
}
我发现大多数web调用是非常单一的,这是一个例外,而不是规则,你会希望响应缓存,特别是web服务调用。实现如下所示的方法将禁用响应缓存。
同样有趣的是,Joseph Mattiello的一些关于iPhone的好建议(从iPhone邮件列表中收到的)。还有更多,但这些是我认为最有用的(注意,现在有几个比特已经从原始的轻微编辑,以包括在回复中提供的细节):
4)只有在必要时才使用双精度,比如在使用CoreLocation时。确保常量以“f”结尾,以使gcc将它们存储为浮点数。
float val = someFloat * 2.2f;
当someFloat实际上可能是double类型时,这是非常重要的,你不需要混合模式数学,因为你在存储上失去了'val'的精度。虽然iphone的硬件支持浮点数,但与单精度相比,执行双精度算术可能仍需要更多时间。引用:
iPhone上的Double vs float iPhone/iPad双精度数学
在老式手机上,计算的速度应该是相同的,但你可以在寄存器中使用更多的单精度组件,所以对于许多计算来说,单精度最终会更快。
5)设置你的属性为非原子的。默认情况下,它们是原子的,在合成时,将创建信号量代码以防止多线程问题。99%的人可能不需要担心这个,当设置为nonatomic时,代码就不会那么臃肿,内存效率更高。
6) SQLite can be a very, very fast way to cache large data sets. A map application for instance can cache its tiles into SQLite files. The most expensive part is disk I/O. Avoid many small writes by sending BEGIN; and COMMIT; between large blocks. We use a 2 second timer for instance that resets on each new submit. When it expires, we send COMMIT; , which causes all your writes to go in one large chunk. SQLite stores transaction data to disk and doing this Begin/End wrapping avoids creation of many transaction files, grouping all of the transactions into one file.
此外,如果GUI在主线程上,SQL将阻塞它。如果你有一个很长的查询,最好将查询存储为静态对象,并在单独的线程上运行SQL。确保将修改数据库查询字符串的任何内容包装在@synchronize(){}块中。对于简短的查询,为了更方便,只需将内容留在主线程中。
更多的SQLite优化技巧在这里,虽然文档看起来过时了,但许多要点可能仍然是好的;
http://web.utk.edu/~jplyon/sqlite/SQLite_optimization_FAQ.html
声明属性
对于所有属性,您通常应该使用Objective-C 2.0声明属性特性。如果它们不是公共的,将它们添加到类扩展中。使用声明的属性使内存管理语义立即清晰,并使您更容易检查dealloc方法——如果您将属性声明分组在一起,您可以快速扫描它们并与dealloc方法的实现进行比较。
在不将属性标记为“nonatomic”之前,您应该仔细考虑一下。正如《Objective C编程语言指南》所指出的,属性在默认情况下是原子的,并且会产生相当大的开销。此外,简单地将所有属性都设置为原子化并不能使应用程序具有线程安全性。当然,还要注意,如果你没有指定“nonatomic”,并且实现你自己的访问方法(而不是合成它们),你必须以原子的方式实现它们。
推荐文章
- 如何删除默认的导航栏空间在SwiftUI导航视图
- 如何在iOS中使用Swift编程segue
- Swift -整数转换为小时/分钟/秒
- Swift:声明一个空字典
- 为什么ARC仍然需要@autoreleasepool ?
- 在成功提交我的应用程序后,“太多符号文件”
- 首先添加一个UIView,甚至是导航栏
- 我如何改变UIButton标题颜色?
- 如何从UIImage (Cocoa Touch)或CGImage (Core Graphics)获取像素数据?
- 在Swift中如何调用GCD主线程上的参数方法?
- NSLayoutConstraints是可动画的吗?
- iOS -构建失败,CocoaPods无法找到头文件
- Xcode 4挂在“附加到(应用程序名称)”
- 为什么单元测试中的代码不能找到包资源?
- CFNetwork SSLHandshake iOS 9失败