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协议提供的指针算术运算所代替了。
还有一些其他的比如类别,转发 这些都是后面再学也没关系的
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 记一次.NET内存居高不下排查解决与启示
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧