从 c 进入oc

体现下差异性:

Objective-C 是 C 语言的超集

Objective-C 程序设计语言采用特定的语法,来定义类和方法、调用对象的方法、动态地扩展类,以及创建编程接口,来解决具体问题。Objective-C 作为 C 程序设计语言的超集,支持与 C 相同的基本语法。您会看到所有熟悉的元素,例如基本类型(intfloat等)、结构、函数、指针,以及流程控制结构,如 if...else 语句和 for 语句。您还可以访问标准 C 库例程,例如在 stdlib.h 和stdio.h 中声明的那些例程。

Objective-C 为 ANSI C 添加了下述语法和功能:

  • 定义新的类

  • 类和实例方法

  • 方法调用(称为发消息

  • 属性声明(以及通过它们自动合成存取方法)

  • 静态和动态类型化

  • 块 (block),已封装的、可在任何时候执行的多段代码

  • 基本语言的扩展,例如协议和类别

如果您现在还不太熟悉 Objective-C 的这些方面,也不必担心。随着您读完这篇文章的剩余部分,将会逐渐了解它们。如果您是过程化程序开发人员,不懂面向对象的概念,那么先将对象从本质上视为具有关联函数的结构,可能会有助于理解。这个概念与事实差不多,特别是在运行时实现方面。

除了提供在其他面向对象语言中已有的多数抽象和机制之外,Objective-C 还是一种非常动态的程序设计语言,而且这种动态是其最大优势。这种动态体现在它允许在运行应用程序时(即运行时)才去确定其行为,而不是在生成期间就已固定下来。因此,Objective-C 的动态机制让程序免受约束(编译和链接程序时施加的约束);进而在用户控制下,将大多数符号解析责任转移到运行时。

如果其他声明是编程接口的一部分,并且打算专有,您可以将它们放在实现文件中。

当您想要在源代码中包括头文件时,请在头文件或源文件的前几行之中,指定一个导入 (#import) 指令,#import 指令类似于 C 的#include 指令,不过前者确保同一文件只被包括一次。如果您要导入框架的大部分或所有头文件,请导入框架的包罗头文件 (umbrella header file),它具有与框架相同的名称。导入(假设的)Gizmo 框架的头文件的语法是:

#import <Gizmo/Gizmo.h>
在 Objective-C 中,一个类只能有一个父类。

如果类具有与其公共接口相关的自定函数、常量或数据类型,请将它们的声明放在 @interface ...@end 块之外。

类实现的语法是相似的。它以 @implementation 编译器指令开始(接着是该类的名称),以 @end 指令结束。中间是方法实现。(函数实现应在 @implementation ...@end 块之外。)一个实现应该总是将导入它的接口文件作为代码的第一行。

对于包含对象的变量,Objective-C 既支持动态类型化,也支持静态类型化。静态类型化的变量,要在变量类型声明中包括类名称。动态类型化的变量,则要给对象使用类型 id。您会发现在某些情况下,会需要使用动态类型化的变量。例如,集 (collection) 对象,如数组,在它包含对象的类型未知的情况下,可能会使用动态类型化的变量。此类变量提供了极大的灵活性,也让 Objective-C 程序拥有了更强大的活力。

下面的例子,展示了静态类型化和动态类型化的变量声明:

MyClass *myObject1;  // Static typing
id       myObject2;  // Dynamic typing
NSString *userName;  // From Your First iOS App (static typing)

请注意第一个声明中的星号 (*)。在 Objective-C 中,执行对象引用的只能是指针。如果您还不能完全理解这个要求,不用担心。并非一定要成为指针专家才能开始 Objective-C 编程。只需要记住,在静态类型化的对象的声明中,变量的名称前面应放置一个星号。id 类型意味着一个指针。

Objective-C 中有两种类型的方法:实例方法和类方法。

  • 实例方法,由类的实例来执行。换言之,在调用实例方法之前,必须先创建该类的实例。实例方法是最常见的方法类型。

  • 类方法,可由它所在的类直接执行。它不需要对象的实例作为消息的接收者。

方法声明包含方法类型标识符、返回类型、一个或多个签名关键词,以及参数类型和名称信息。以下是 insertObject:atIndex: 实例方法的声明。

方法声明语法

对于实例方法,声明前面是减号 (-);对于类方法,对应指示器是加号 (+)。

Objective-C 还提供用于调用存取方法的点记法语法。存取方法获取并设定对象的状态,因此对于封装很重要,是所有对象的重要功能。对象隐藏或封装其状态,并显示接口,该接口是访问该状态的所有实例都通用的。

编译器自动合成所声明的属性。在合成属性时,它创建自己的存取方法,以及“支持”该属性的专有实例变量。实例变量的名称与属性的名称相同,但具有下划线前缀 (_)。只有在对象初始化和取消分配的方法中,您的应用程序应该直接访问实例变量(而不是其属性)。

如果您想要让实例变量采用不同名称,可以绕过自动合成,并明确地合成属性。在类实现中使用 @synthesize 编译器指令,让编译器产生存取方法,以及进行特殊命名的实例变量。例如:

@synthesize enabled = _isEnabled;

同时,在声明属性时,您可以指定存取方法的自定名称,通常是使 Boolean 属性的 getter 方法遵循约定形式,如下所示:

@property (assign, getter=isEnabled) BOOL enabled; // Assign new value, change name of getter method

是封装工作单元的对象,即可在任何时间执行的代码段。它们在本质上是可移植的匿名函数,可作为方法和函数的参数传入,或可从方法和函数中返回。块本身具有一个已类型化的参数列表,且可能具有推断或声明的返回类型。您还可以将块赋值给变量,然后像调用函数一样调用它。

插入符号 (^) 是用作块的语法标记。块的参数、返回值和正文(即执行的代码)存在其他类似的语法约定。下图解释了该语法,尤其是在将块赋值给变量时。

图像: ../Art/blocks_2x.png

您接着可以调用块变量,就像它是一个函数一样:

int result = myBlock(4); // result is 28

块共享局部词法作用范围内的数据。块的这项特征非常有用,因为如果您实现一个方法,并且该方法定义一个块,则该块可以访问该方法的局部变量和参数(包括堆栈变量),以及函数和全局变量(包括实例变量)。这种访问是只读的,但如果使用 __block 修饰符声明变量,则可在块内更改其值。即使包含有块的方法或函数已返回,并且其局部作用范围已销毁,但是只要存在对该块的引用,局部变量仍作为块对象的一部分继续存在。

作为方法或函数参数时,块可用作回调。被调用时,方法或函数执行部分工作,并在适当时刻,通过块回调正在调用的代码,以从中请求附加信息,或获取程序特定行为。块使调用方在调用时能够提供回调代码。块从相同的词法作用范围内采集数据(就像宿主方法或函数所做的那样),而非将所需数据打包在“关联”结构中。由于块代码无需在单独的方法或函数中实现,您的实施代码会更简单且更容易理解。

Objective-C 框架具有许多含块参数的方法。例如,Foundation 框架的 NSNotificationCenter 类声明以下方法,该方法具有一个块参数:

- (id)addObserverForName:(NSString *)name object:(id)obj queue:(NSOperationQueue *)queue usingBlock:(void (^)(NSNotification *note))block

此方法将一个观察者添加到通知中心(通知在采用设计模式使您的应用程序合理化中有介绍)。指定名称的一则通知发布时,块被调用以处理该通知。

    opQ = [[NSOperationQueue alloc] init];
    [[NSNotificationCenter defaultCenter] addObserverForName:@"CustomOperationCompleted"
             object:nil queue:opQ
        usingBlock:^(NSNotification *notif) {
        // handle the notification
    }];
对于许多委托协议来说,采用一个协议仅仅是实现该协议定义的方法。有些协议要求您明确地声明支持该协议,而协议可以指定必需方法和可选方法。


其他是编程接口的一部分,并且打算专有,您可以将它们放在实现文件中。)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值