从C++到Objective-C
-
#import=#include+#pragma once -
继承的时候没有限定符,继承都是 public 的。
-
成员变量/函数没有限定符,成员变量缺省是
protected的,而函数是public的。 -
没有
const,virtual,Objective-C 中函数缺省的就是 virtual 的。 -
Objective-C 中 方法前面的“-”是实例方法(类似于C++中的类成员函数)。
-
Objective-C 中 前缀为“+”的是类方法(类似于C++中的静态成员函数,或者是全局函数)。
-
@后的关键字
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50@interface: 用于声明一个类的接口。它指定了类可以执行的方法(消息)和可以访问的实例变量。 @protocol: 用于声明一个或多个方法组成的协议。类可以选择遵循这些协议,并提供协议中定义的方法的实现。 @implementation: 用于提供在 @interface 中声明的类的方法的具体实现。 @class: 用于在头文件中声明一个类的存在,但不包含其完整定义。这允许在类定义之前引用该类,以避免循环依赖。 @end: 用于标记 @interface、@implementation 或 @protocol 的结束。 @selector: 用于创建一个 SEL 类型的值,该值表示 Objective-C 中的一个方法选择器。SEL 类型是一个指向 IMP(方法实现)的指针的指针。 @property: 用于在类的接口中声明属性。属性可以是实例变量和访问器方法的简洁声明。 @synthesize: 在 Objective-C 2.0 及以后的版本中,编译器会自动为声明的属性生成访问器方法。但在某些情况下,你可能需要手动使用 @synthesize 来控制访问器方法的实现。 @dynamic: 告诉编译器属性的访问器方法将在运行时动态地解析。这通常用于 Core Data 等框架中,其中属性的访问器方法是由框架动态提供的。 @private, @protected, @public: 用于在类的接口中指定实例变量的访问级别。默认情况下,实例变量是私有的(@private),但可以使用这些关键字来修改其可见性。 @encode: 用于获取类型编码,这是一个表示 C 语言类型的字符串。这通常用于 Objective-C 运行时函数,如 objc_msgSend。 @try, @catch, @finally, @throw: 用于实现异常处理。这些关键字提供了在 Objective-C 中捕获和处理异常的能力。 @autoreleasepool: 在非主线程或手动内存管理环境中使用,以定义自动释放池的范围。在这个范围内的对象会在池被释放时发送 autorelease 消息。 @synchronized: 用于同步代码块,防止多个线程同时访问同一块代码。它确保在给定时间只有一个线程可以执行同步块中的代码。 @compatibility_alias: 用于为已存在的类定义一个别名。这允许在不修改现有代码的情况下,通过新名称访问旧类。 @restrict: 在属性声明中使用,以指定属性应仅通过指定的访问器方法访问。这可以确保属性的值只能通过特定的方式来修改或读取。 @objc: 在 Swift 中与 Objective-C 交互时使用,用于标记 Swift 类、协议、方法或属性应暴露给 Objective-C 运行时。 -
一段代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50# @interface TestTimer ():这是一个类扩展(class extension)的定义。它允许你为类添加额外的属性、方法或协议,而不必在公共接口中暴露它们。这里,你添加了一个名为timer的属性。 @interface TestTimer () # 定义了一个名为timer的属性,类型为NSTimer * # nonatomic:这是一个性能优化选项,表示该属性的访问不是线程安全的。在单线程环境中,它通常比atomic更快。 # strong:表示这个属性是一个引用计数类型的属性,并且它拥有其引用的对象。当timer属性被设置为新的NSTimer对象时,该对象的引用计数会增加;当timer被设置为nil时,其引用计数会减少,如果减少到0,则该对象会被释放。 @property (nonatomic, strong) NSTimer *timer; # assign 用于简单的数据类型,如 NSInteger、CGFloat、char、int、float、double、CGPoint、CGRect、CGSize 等,以及 C 语言的指针类型(如 id、NSObject *、NSString * 等)。 # 使用 assign 时,只是简单地设置变量值,不会调用任何额外的内存管理方法(如 retain、release 或 autorelease)。 # 对于对象类型(如 NSString *、NSArray * 等),使用 assign 是不安全的,因为它不会增加对象的引用计数,从而可能导致野指针(dangling pointer)或内存泄漏。对于对象类型,通常应该使用 strong 或 weak。 @property (nonatomic, assign) NSInteger count; @end # 这是类的实现部分,包含了所有方法的具体实现。 @implementation TestTimer # 这个方法用于启动一个定时器。 - (void)startTimer { if (!_timer) { # selector:@selector(printCurrentTime):当定时器触发时,会调用printCurrentTime方法。 # userInfo:nil:传递给定时器触发方法的数据,这里为nil。 # repeats:YES:定时器是否应该重复触发。这里设置为YES,表示每秒都会触发一次。 # 调用[[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];实际上是不必要的,因为[NSTimer scheduledTimerWithTimeInterval:...]方法已经自动将定时器添加到当前运行循环的默认模式中。但如果你在其他情况下需要手动添加定时器,这段代码会很有用。 # userInfo:@{@"count": @(self.count)} # 这里创建了一个字典(使用 Objective-C 的字面量语法),其中包含一个键为 @"count",其对应的值是通过 @(self.count) 将 NSInteger 类型的 self.count 转换为 NSNumber 类型的对象。这是因为字典的值必须是对象类型,而 NSInteger 是一个基本数据类型,所以需要将其“装箱”(boxing)为 NSNumber 对象。 _timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(printCurrentTime) userInfo:@{@"count": @(self.count)} repeats:YES]; [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes]; } } - (void)stopTimer { if (_timer) { [_timer invalidate]; _timer = nil; } } - (void)printCurrentTime { NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; [dateFormatter setDateFormat:@"yyyy-MM-dd HH:mm:ss"]; NSString *currentTime = [dateFormatter stringFromDate:[NSDate date]]; NSLog(@"Current Time: %@, Count: %ld", currentTime, (long)self.count); } @end -
[car fly];- C++ : 调用car类别的fly方法,若car类别里头没有定义fly方法,那编译肯定不会通过。
- Objective-C: “发提交一个fly的消息给car对象”,fly是消息,而car是消息的接收者。car收到消息后会决定如何回应这个消息,若car类别内定义有fly方法就运行方法内之代码,若car内不存在fly方法,则程序依旧可以通过编译,运行期则抛出异常。
-
NSString :Objective-C提供了一个助记符可以方便地从常量值创建NSString对象。要使用这个助记符,你需要做的全部事情,是在普通的双引号字符串前放置一个@符号
-
类
Objective-C 的类规格说明包含了两个部分:定义(interface)与实现(implementation)。定义(interface)部分包含了类声明和实例变量的定义,以及类相关的方法。实现(implementation)部分包含了类方法的实际代码。
方法前面的 +/- 号代表函数的类型:加号(+)代表类方法(class method),不需要实例就可以调用,与C++ 的静态函数(static member function)相似。减号(-)即是一般的实例方法(instance method)。
-
方法声明语法
如果子类定义了跟父类的具有相同标识符的方法,那么子类首先收到消息,然后可以有选择的把消息转发(也可以不转发)给他的父类。
-
消息被中括号( [ 和 ] )包括。中括号中间,接收消息的对象在左边,消息(包括消息需要的任何参数)在右边。例如,给myArray变量传递消息insertObject:atIndex:消息,你需要使用如下的语法:
1[myArray insertObject:anObj atIndex:0];为了避免声明过多的本地变量保存临时结果,Objective-C允许你使用嵌套消息。每个嵌套消息的返回值可以作为其他消息的参数或者目标。例如,你可以用任何获取这种值的消息来代替前面例子里面的任何变量。所以,如果你有另外一个对象叫做myAppObject拥有方法,可以访问数组对象,以及插入对象到一个数组,你可以把前面的例子写成如下的样子:
1[[myAppObject getArray] insertObject:[myAppObject getObjectToInsert] atIndex:0];
-
-
协议
-
id : C++里的(void*)类似