OC 语法快速入门

来源: https://www.runoob.com/w3cnote/objective-c-tutorial.html

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协议提供的指针算术运算所代替了。

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

posted @ 2020-06-17 14:46  Grewer  阅读(518)  评论(0编辑  收藏  举报