文档章节

OC语言的特性(一)-消息传递与调用函数的表现形式

浩浩老师
 浩浩老师
发布于 2015/09/08 14:47
字数 1071
阅读 1127
收藏 0

我们在初学Objective-C时,都会觉得ObjC中的消息传递和其他语言的调用函数差不多,只是在OC中,方法调用用消息传递这一概念来代替。

那么到底怎样区别OC中的消息传递与其他语言的调用函数呢。

可以使用C语言与OC语言进行一下对比。

C语言示例

 

//声明一个函数,用来获取两个整型值的中较大的值int max(int a,int b); 
int main(int argc, const char * argv[])
{    //调用函数,获取4,6两个整型值的最大值    int result = max(4,6);    
    //打印结果
    printf("4与6两个数的较大的值是:%d",result);    return 0;
}

 

编译运行程序之后,编译器会提示如下错误

Undefined symbols for architecture x86_64:
  "_max", referenced from:
      _main in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

在如上的例子中,我们能够体会到调用函数的语言在声明完函数后,如果没有实现函数,程序是无法编译通过的。

那么我们接下来看

OC的例子

 

#import <Foundation/Foundation.h>@interface Function : NSObject//声明一个类方法,用来获取两个整型值的最大值+ (int)max:(int)v1 :(int)v2;@end#import "Function.h"@implementation Function@end

 

只使用Xcode工具的build功能(Command+B),我们能够看到程序是可以编译通过的,但是会有一个黄色的警告

Method definition for 'max::' not found!

只有当程序运行之后才会出现如下的崩溃信息

+[Function max::]: unrecognized selector sent to class 0x1000010f8*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[Function max::]: unrecognized selector sent to class 0x1000010f8'*** First throw call stack:
(    0   CoreFoundation                      0x00007fff8ea9925c __exceptionPreprocess + 172    1   libobjc.A.dylib                     0x00007fff88555e75 objc_exception_throw + 43    2   CoreFoundation                      0x00007fff8ea9c02d +[NSObject(NSObject) doesNotRecognizeSelector:] + 205    3   CoreFoundation                      0x00007fff8e9f7272 ___forwarding___ + 1010    4   CoreFoundation                      0x00007fff8e9f6df8 _CF_forwarding_prep_0 + 120    5   SendMethod                          0x0000000100000f24 main + 68    6   libdyld.dylib                       0x00007fff8a8f95fd start + 1)
libc++abi.dylib: terminating with uncaught exception of type NSException

通过这种形式的对比,相信大家应该对消息传递和调用函数的形式上的区别应该能够看出来了。

对,消息传递调用函数对于程序员来说最大的区别就在于源代码编译的过程中是否能够编译通过.

解释消息传递机制的原理就要用到OC语言中的运行时系统(Runtime)了.

     运行时系统是一个提供一系列公开函数接口以及数据结构的动态链接库,这些头文件位于/usr/include/objc。许多这些函数允许你使用纯C语言重写当你写OC代码后编译器做的事情。其他形式的接口则是通过NSObject类中定义的一些方法。这些方法是可以用来实现其他的运行时接口来提高运行效率。但是重写运行时的代码对于使用OC语言进行编程并非是必须的,但是,少数的运行时函数在一些特殊情况下,对于OC程序还是很有用途的。

     接下来,我们一起看一下这些函数。

  Objc_msgSend()函数举例

  

#import <Foundation/Foundation.h>@interface Function : NSObject//声明一个类方法,用来获取两个整型值的最大值+ (int)max:(int)v1 :(int)v2;@end#import "Function.h"@implementation Function+ (int)max:(int)v1 :(int)v2
{    return v1 > v2 ? v1:v2;
}@end

 

根据以上的Function类,使用objc_msgSend()这种c语言的函数完成oc方法的调用。

 

    //获取4,6两个整型值的最大值    int result = (int)objc_msgSend([Function class], @selector(max::),4,6);    
    //打印结果
    NSLog(@"4,6的最大值是:%d",result);

 

消息传递函数为动态绑定提供所有必要的内容:

  • 首先,它找到选择器调用的过程(方法实现)。由于同一个方法在不同的类中可能有不同的实现,这个精确的调用过程依赖于接收者所属于的类。

  • 然后,它会调用这个过程,传递接收者对象(一个指向其数据的指针),以及消息中定义的那些参数。

  • 最后,它传递过程调用的返回值作为它自身的返回值。

  • 注意:编译器会自动调用消息传递函数。你不应该在自己的代码中直接调用该方法。

本文转载自:http://www.cnblogs.com/daxiaxiaohao/p/3907198.html

浩浩老师
粉丝 1
博文 80
码字总数 0
作品 0
海淀
程序员
私信 提问
iOS 编写高质量Objective-C代码(二)

《编写高质量OC代码》已经顺利完成一二三四篇! 附上链接: iOS 编写高质量Objective-C代码(一) iOS 编写高质量Objective-C代码(二) iOS 编写高质量Objective-C代码(三) iOS 编写高质量...

MrLiuQ
2018/08/13
0
0
iOS OC动态运行时(runtime)~动态特性表现

//联系人:石虎QQ:1224614774昵称:嗡嘛呢叭咪哄 一、概念: 因为运行时 runtime 是 必须到运行时(run time)才会做一些事情; 所以OC的动态特性表现为了三个方面:动态类型、动态绑定、动态加载;...

石虎132
2017/12/17
0
0
IOS OC objc_msgSend的作用

一 消息传递 OC中调用方法也叫消息传递(pass a message),消息有名称(name) 或 选择子(selector),可以接受参数,而且可以设定返回值。 OC中向某对象传递消息,会使用动态绑定机制来决定需...

卧龙小
2015/07/06
250
0
Effective objective-C 读书笔记 (第一部分)

第1章 熟悉Objective-C 第1条 了解Objective-C语言的起源 Objective-C是一种“消息结构”的语言,而非“函数调用”语言。 关键区别在于:使用消息结构的语言,其运行时所执行的代码由运行环境...

shenglanya
2017/12/05
0
0
【Objective-C】Objective-C语言的动态性

  Objective-C语言的动态性主要体现在以下3个方面   (1)动态类型:运行时确定对象的类型。   (2)动态绑定:运行时确定对象的方法。   (3)动态加载:运行时加载需要的资源或者或...

零零圈圈
06/19
0
0

没有更多内容

加载失败,请刷新页面

加载更多

Mybatis Plus删除

/** @author beth @data 2019-10-17 00:30 */ @RunWith(SpringRunner.class) @SpringBootTest public class DeleteTest { @Autowired private UserInfoMapper userInfoMapper; /** 根据id删除......

一个yuanbeth
19分钟前
2
0
总结

一、设计模式 简单工厂:一个简单而且比较杂的工厂,可以创建任何对象给你 复杂工厂:先创建一种基础类型的工厂接口,然后各自集成实现这个接口,但是每个工厂都是这个基础类的扩展分类,spr...

BobwithB
58分钟前
4
0
java内存模型

前言 Java作为一种面向对象的,跨平台语言,其对象、内存等一直是比较难的知识点。而且很多概念的名称看起来又那么相似,很多人会傻傻分不清楚。比如本文我们要讨论的JVM内存结构、Java内存模...

ls_cherish
今天
4
0
友元函数强制转换

友元函数强制转换 p522

天王盖地虎626
昨天
5
0
js中实现页面跳转(返回前一页、后一页)

本文转载于:专业的前端网站➸js中实现页面跳转(返回前一页、后一页) 一:JS 重载页面,本地刷新,返回上一页 复制代码代码如下: <a href="javascript:history.go(-1)">返回上一页</a> <a h...

前端老手
昨天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部