第三章 Objective-C 基础知识

3.1 命名约定

  良好的命名,Cocoa 命名约定比较注重清晰性。这一点与C++大相径庭。

  1)方法名要能够清晰地反应出参数类型和返回类型。 

//令人困惑
- (void) add;

//从上面的名称看来,add方法需要接受一个参数,但实际上它不接受任何参数。难道这个方法是在某个默认对象上做add吗?
//下面这种做法就清晰多了
- (void)addEmptyRecord;
- (void) addRecord:(Record *)record;

//不正确,从名称上看setURL应该接受一个URL最为参数对象而不是NSString
- (void) setURL:(NSString *) URL;
//正确
- (void) setURLString:(NSString *) string;
- (void) setURL:(NSURL *) URL;

  2) 静态变量以 s 开头

static MYThing *sSharedInstance;

  3)全局变量以 g 开头,通常情况下应该避免使用常量之外的全局变量

MYThing * gGlobal;

  4)常量在 Cocoa 和 Core Fondation 中使用不同的命名方式。在Core Fondation 中,常量以 k 开头,在 Cocoa 中则不是。建议文件作用域内的(静态)常量都以 k 开头。

static const NSUInteger kMaximunNumberOfRows = 3

  5)方法参数名称通常要加一个冠词(a,an,the)作为前缀。“the” 用的比较少,只在特制某些非常重要的或者唯一的对象使用。用这种方式对参数进行命名,可以避免它们与方法中的局部变量和实例变量混淆。特别有帮助的一点是,避免无意地修改它们。

  6)实例变量以下划线开头。

  7)类名应该总是以大写字母开头,方法名和变量名则应该以小写字母开头。所有的类名和方法名都必须使用驼峰式大小写来分割单词。

 

3.2 自动引用计数ARC(Automatic Reference Counting)

  ARC 极大的减少了 Cocoa 开发中的常见编程错误:retain 跟 release 不匹配。ARC 并不会消除对 retain 和 release 的调用,而是把这项原本属于程序员的工作交给了编译器。记住,ARC 并不等同于 垃圾回收。它只是在编译的时候自动在合适的位置插入一些代码。垃圾回收机制是在运行时起作用,会影响运行时效率,而ARC 是在编译的时候插入内存管理代码,不影响运行时效率,所以内存回收比垃圾回收的效率要高,能提升系统性能。

  ARC 不是垃圾回收,尤其他不能像 Snow Leopard 中的垃圾回收机制那样处理循环引用(保留)。下图中的对象 A 与对象 B 之间存在循环保留。

第三章 Objective-C 基础知识_第1张图片

  在Snow leapard 的垃圾回收机制下,如果从“外部对象”到“对象A” 的引用链接中断了,对象A 和 对象B 都会被销毁,因为它们从程序中孤立出去了。而在ARC 中,对象A 和 对象B 都不会被销毁,因为它们的引用计数都大于0。因此,在IOS开发中,必须要做好对强引用的跟踪管理以避免出现循环引用。

  属性关系有两种主要类型:strong 和 weak,相当于非 ARC 中的 retain 和 assign。只要存在一个强引用,对象会一直存在,不会被销毁。(这里可以先简单地理解为 强引用 是存在retainCount加一,而弱引用则不存在)。

  Objective-C 中一直存在循环引用的问题,但在实际应用中很少出现循环引用。大部分的循环引用都是由于 delegate 引起的,所以应该总是把 delegate 属性声明为 weak。当引用的对象被销毁后,weak 引用会被自动设置为nil,与 assign 相比这是一个巨大的进步,因为 assign 可以指向被释放的内存,导致程序崩溃。

  在 ARC 之前,合成属性(synthesized property)的默认属性是 assign,而在ARC 中,默认属性则是 strong。这一点要注意下。

 

3.3 属性

  从最近几个版本的IOS 开始,编译器会根据属性自动合成实例变量和相对应的存取方法。通常情况下,已经不需要再使用 @synthesized 关键字了。建议以后在编程中都是用属性和自动合成的实例变量,在头文件中声明共有属性,在 .m 文件中的类扩展部分声明私有变量。如下实例:

// MyClass.h

@interface MyClass : NSObject

@property (nonatomic, readwrite, weak) id delegate;
@property (nonatomic, readonly, strong) NSString *readonlyString;

@end

// MyClass.m

@interface MyClass () //私有方法

@property (nonatomic, readwrite, strong) NSString *readonlyString;
@property (nonatomic, readwrite, strong) NSString *privateString;
 
@end

  上面的代码会制动创建几个实例变量:_delegate, _readonlyString,_privateString。注意上面的 readonlyString 在类扩展部分被重新定义使用了 readwrite 关键字进行修饰,这样便为该类创造了一个私有的设置方法(setter)。

  另外一种私有实例的方法可以在 @implementation 这一块实现。如下代码:

@implementation Something 
{    
   __weak  NSString *_name; //声明一个weak实例变量,默认是strong
}

3.4 存取器

  应该使用存取器访问实例变量,避免直接使用实例变量。

3.5 分类和扩展

  使用分类(category)可以在运行时向某个现有的类添加新的方法。包括苹果官方的 Cocoa 类在内的任何类,都可以使用分类进行扩展(extension),新加入的方法类在类的所有实例中都可以用。分类用于以模块化的方式将一个大型类分化成多个更易维护的部分。

  分类的声明方法如下: 

@interface NSMutableString (Capitalize) 
- (void) capitalize;
@end

capitalize 就是分类的名称。

  注意:

    1)这里没有声明任何实例变量,分类中不能声明实例变量,也不能合成属性(不过可以声明属性)。

    2)分类不要求方法一定要实现,但是如果没有实现分类的方法,在调用过程中会因为找不到而抛出异常。

  分类的实现:

@implementation NSMutableString (Capitalize)

- (void) capitalize 
{
    [self setString:[self capitalizedString]];
}

@end

3.5.3 类扩展

  Objective-C对分类添加了一个有用的功能,叫做类扩展(class extension)。类扩展的声明方法跟分类很像,只有不括号内的名字是空的:

@interface MYObject() 
- (void) doSomething;
@end

  类扩展是在 .m 中实现私有方法的一个很棒的方式。不同于分类,在类扩展中声明的方法与在类中声明的方法完全一致,这些方法必须实现,且在编译时被添加到类中,而分类是在运行时添加的。在类扩展中也可以声明合成属性。

3.6 正式协议和非正式协议

   协议是 Objective-C 中的一个重要部分,在 Objective-C 2.0 中,正式协议已经非常普遍了。但是,在 Objective-C 1.0 的协议方法中没有 @optional 这个标签,所有的协议方法都是必须实现的,这种协议的用处不大。通常我们希望一部分协议是可选的,一部分是必须实现的,而Objective-C 1.0 中是不可能实现的。所以开发者通常会使用“非正式协议”来实现(非正式协议其实就是 NSObject 的一个分类)。

  Objective-C 2.0 添加了 @optional 这个标签,是它能够在正式协议中声明可选方法。

  使用一个协议很简单,只要在父类后面的尖括号中包含协议的名称就可以了,如下代码:

@interface AppController : NSObject 

  声明一个协议如下: 

@protocol CCDirectorDelegate 

//可选的方法
@optional
-(void) updateProjection;

//@required 实现必须要实现的方法
@required
...

@end

通常声明协议后,通常需要一个熟悉以便操作它,通常使用 id 的方式来声明

@property (nonatomic,readwrite,weak) id delegate;

呼呼~~~累了,休息先

 

转载于:https://www.cnblogs.com/style513/p/3156085.html

你可能感兴趣的:(第三章 Objective-C 基础知识)