OC-语法快速入门

1次阅读

共计 4609 个字符,预计需要花费 12 分钟才能阅读完成。

来源: https://www.runoob.com/w3cnot…

Interface

定义部分,清楚定义了类的名称、数据成员和方法。以关键字 @interface 作为开始,@end 作为结束。

@interface MyObject : NSObject {
    int memberVar1; // 实体变量
    id  memberVar2;
}

+(return_type) class_method; // 类方法

-(return_type) instance_method1; // 实例方法
-(return_type) instance_method2: (int) p1;
-(return_type) instance_method3: (int) p1 andPar: (int) p2;
@end

方法前面的 +/- 号代表函数的类型:加号(+)代表类方法(class method),不需要实例就可以调用,与 C ++ 的静态函数(static member function)相似。减号(-)即是一般的实例方法(instance method)。

这里提供了一份意义相近的 C ++ 语法对照,如下:

class MyObject : public NSObject {
protected:
    int memberVar1;  // 实体变量
    void * memberVar2;

  public:
    static return_type class_method(); // 類方法

    return_type instance_method1();    // 实例方法
    return_type instance_method2(int p1);
    return_type instance_method3(int p1, int p2);
}

Objective- C 定义一个新的方法时,名称内的冒号(:)代表参数传递,不同于 C 语言以数学函数的括号来传递参数。Objective- C 方法使得参数可以夹杂于名称中间,不必全部附缀于方法名称的尾端,可以提高程序可读性。设定颜色 RGB 值的方法为例:

- (void) setColorToRed: (float)red Green: (float)green Blue:(float)blue; /* 宣告方法 */

[myColor setColorToRed: 1.0 Green: 0.8 Blue: 0.2]; /* 呼叫方法 */

这个方法的签名是 setColorToRed:Green:Blue:。每个冒号后面都带着一个 float 类别的参数,分别代表红,绿,蓝三色。

在 Object-C 中,有两种类型的方法,类方法和实例方法。

类方法以+开头,其基本形式如下:

(id)someMethod;

类方法一般都是工厂方法,返回一个实例。

实例方法以 - 开头,其基本形式如下:

- (void)someMethod;

方法可以不带参数,也可以带一个或多个参数,也可以有返回值:

(int)someMethod;

(void)someMethodWithValue:(SomeType)value;

(void)someMethodWithFirstValue:(SomeType)value1 secondValue:(AnotherType)value2;

1、程序的头文件和源文件的扩展名分别为.h 和.m;

2、注释:单行(//)和多行(/* … */);

3、Object_C 中的 nil 相当于 NULL。

4、Object_C 中的 YES 和 NO 相当于 true 和 false。

5、#import 相当于 #include , 导入头文件也有两种查找方式 < … > 和 ” … “,但是 #import 可自动防止同一个文件被导入多次。

6、Object_C 中的所有类都必须继承自 NSObject。

7、Object_C 仅支持单一父类继承,不支持多重继承。

8、Object_C 中所有对象都是指针的形式。

9、Object_C 用 self 代替 this。

10、Object_C 使用 id 代替 void*。

11、Object_C 中用消息表示类的方法,并采用 [aInstance method:argv] 调用形式。

12、Object_C 支持反射机制。

13、Object_C 支持 Dynamic Typing,Dynamic Binding 和 Dynamic Loading。

Implementation

实现区块则包含了公开方法的实现,以及定义私有(private)变量及方法。以关键字 @implementation 作为区块起头,@end 结尾。

@implementation MyObject {int memberVar3; // 私有實體變數}

+(return_type) class_method {.... //method implementation}
-(return_type) instance_method1 {....}
-(return_type) instance_method2: (int) p1 {....}
-(return_type) instance_method3: (int) p1 andPar: (int) p2 {....}
@end

属性

属性是用来代替声明存取方法的便捷方式。属性不会在你的类声明中创建一个新的实例变量。他们仅仅是定义方法访问已有的实例变量的速记方式而已。暴露实例变量的类,可以使用属性记号代替 getter 和 setter 语法。类还可以使用属性暴露一些“虚拟”的实例变量,他们是部分数据动态计算的结果,而不是确实保存在实例变量内的。

实际上可以说,属性节约了你必须要写的大量多余的代码。因为大多数存取方法都是用类似的方式实现的,属性避免了为类暴露的每个实例变量提供不同的 getter 和 setter 的需求。取而代之的是,你用属性声明指定你希望的行为,然后在编译期间合成基于声明的实际的 getter 和 setter 方法。

属性声明应该放在类接口的方法声明那里。基本的定义使用 @property 编译选项,紧跟着类型信息和属性的名字。你还可以用定制选项对属性进行配置,这决定了存取方法的行为。下面的例子展示了一些简单的属性声明:

@interface Person : NSObject {
    @public
        NSString *name;
    @private
        int age;
}

@property(copy) NSString *name;
@property(readonly) int age;

-(id)initWithAge:(int)age;
@end

性的访问方法由 @synthesize 关键字来实现,它由属性的声明自动的产生一对访问方法。另外,也可以选择使用 @dynamic 关键字表明访问方法会由程序员手工提供。

@implementation Person
@synthesize name;
@dynamic age;

-(id)initWithAge:(int)initAge
{
    age = initAge; // 注意:直接赋给成员变量,而非属性
    return self;
}

-(int)age
{return 29; // 注意:并非返回真正的年龄}
@end

属性可以利用传统的消息表达式、点表达式或 ”valueForKey:”/”setValue:forKey:” 方法对来访问。

Person *aPerson = [[Person alloc] initWithAge: 53];
aPerson.name = @"Steve"; // 注意:点表达式,等于[aPerson setName: @"Steve"];
NSLog(@"Access by message (%@), dot notation(%@), property name(%@) and direct instance variable access (%@)",
      [aPerson name], aPerson.name, [aPerson valueForKey:@"name"], aPerson->name);

为了利用点表达式来访问实例的属性,需要使用 ”self” 关键字:

-(void) introduceMyselfWithProperties:(BOOL)useGetter
{NSLog(@"Hi, my name is %@.", (useGetter ? self.name : name)); // NOTE: getter vs. ivar access
}

类或协议的属性可以被动态的读取。

多个属性之间,可以使用逗号分隔:

@property (strong, nonatomic) UIWindow *window; 属性通常还会加一些修饰,来控制数据的访问和存储等:

@property (readonly) NSString *firstName;
@property (readonly) NSString *lastName;

属性修饰:

readonly 与 readwrite:

readonly 表明该属性是只读的,外部不能修改其值。与 readonly 相对的修饰是 readwrite,但你不必把它写出来,因为它是默认的。atomic 与 nonatomic:

(atomic、nonatomic)属性用于多线程编程,属性默认是 atomic 的。在多线程环境下设置为 atomic 可以保证数据读取的一致性(因为,它将保证数据仅仅被一个线程独占。也就是说一个线程进行写操作时,将锁定该属性,不允许其他的线程进行写操作。)由于该操作会对数据进行锁操作,故会消耗较多的资源。所以在不需要进行多线程操作时建议将该属性设置为 nonatomic,设置为该参数时程序在任何情况都不会锁定该属性。

strong 与 weak:

其中 strong 是默认的。strong 表示该属性对其相应的对象是强引用。一个变量保持对一个对象的强引用,只要该变量在其作用域范围内或者直到它被赋给另一个对象或者 nil 为止。weak 表示对属性对应的对象的弱引用。

copy、assign、retain:

copy 修饰表示该属性将使用强引用,因为它必须保持它创建的新对象。

assign 指定 setter 方法用简单的赋值,不更改索引计数(Reference Counting), 一般对简单数据类型 使用 assign。

retain,对象引用计数加一。

快速枚举

比起利用 NSEnumerator 对象或在集合中依次枚举,Objective-C 2.0 提供了快速枚举的语法。在 Objective-C 2.0 中,以下循环的功能是相等的,但性能特性不同。

// 使用 NSEnumerator
NSEnumerator *enumerator = [thePeople objectEnumerator];
Person *p;

while ((p = [enumerator nextObject]) != nil ) {NSLog(@"%@ is %i years old.", [p name], [p age]);
}
// 使用依次枚举
for (int i = 0; i < [thePeople count]; i++ ) {Person *p = [thePeople objectAtIndex:i];
    NSLog(@"%@ is %i years old.", [p name], [p age]);
}
// 使用快速枚举
for (Person *p in thePeople) {NSLog(@"%@ is %i years old.", [p name], [p age]);
}

快速枚举可以比标准枚举产生更有效的代码,由于枚举所调用的方法被使用 NSFastEnumeration 协议提供的指针算术运算所代替了。

还有一些其他的比如类别, 转发 这些都是后面再学也没关系的

正文完
 0