NSInvocation Basics
What is NSInvocation?
Apple Developer Reference describes NSInvocation this way:
When we call a method or access a member data of an object in our application, we are actually sending a message. Usually we don't send messages explicitly in our code since the compiler does the work for us. What NSInvocation brings to us is the ability to manually send a message to an object. So a NSInvocation object's job is to send messages; hence we create an object of NSInvocation class, we describe the aspects of the message and finally we send it to our target. The most useful advantage of NSInvocation is that it's an object so we can pass it as an argument to other methods.
Simple NSInvocation example
Suppose we have a dummy object named myDummyObject and it is an object of class myClass. in myClass we have a defined method named sayHelloWorld without any arguments. The simplest way to execute sayHelloWorld method is:
[myDummyObject sayHelloWorld];
1:
Now we want to create the same message manually and send it to myDummyObject using NSInvocation.
A selector describes which method we want to call:
SEL selector = @selector(sayHelloWorld);
1:
Our NSInvocation object needs to know whether the target object has declared the method or if not throws an exception, so it should utilize some search algorithm to achieve this: A method signature is fingerprint of a method which depends on its return value, number of arguments it takes and their types. Therefore our NSInvocation will be able to search through the target object's methods list to see whether it has defined the method or not. This signature is created using methodSignatureForSelector method which every NSObject descendent has this method. In this case sayHelloWorld is a method of myClass. myDummyObject is an object of myClass so we should call methodSignatureForSelector on myDummyObject to return the signature for the method named sayHelloWorld using the selector we declared above:
NSMethodSignature *signature = [myDummyObject methodSignatureForSelector:selector];
1:
We create our NSInvocation object based on the method signature we declared:
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
1:
NSInvocation objects also wants to have our selector:
[invocation setSelector:selector];
1:
Here we specified our target object which we want our message to be sent to:
[invocation setTarget:myDummyObject];
1:
The final step here. Commanding our NSInvocation object to send the message.
[invocation invoke];
1:
NSInvocation to call a method with arguments
Suppose myDummyObject contains a method as follows:
-(void)myFunctionWithArg1: (NSString*) arg1 Arg2: (NSString *) arg2 Arg3: (NSString *) arg3 Arg4: (NSString *) arg4
{
NSLog(@"I am a function with 4 arguments: <%@> <%@> <%@> <%@>" , arg1, arg2, arg3, arg4);
}
1:
2:
3:
4:
The normal way of calling this method is:
[myDummyObject myFunctionWithArg1:@"First" Arg2:@"Second" Arg3:@"Third" Arg4:@"Fourth"];
1:
Now we want to create the message manually using NSInvocation. As I explained above:
SEL selector = @selector(myFunctionWithArg1:Arg2:Arg3:Arg4:);
NSMethodSignature *signature = [myDummyObject methodSignatureForSelector:selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setTarget:myDummyObject];
[invocation setSelector:selector];
1:
2:
3:
4:
5:
We define four strings. We will pass them through our NSInvocation toward the target object:
NSString *arg1 = @"First";
NSString *arg2 = @"Second";
NSString *arg3 = @"Third";
NSString *arg4 = @"Fourth";
1:
2:
3:
4:
This is the way to set the arguments for the method. You can use SetArgument:atIndex for each argument at the specified index.
Some notes about SetArgument:atIndex method:
1- The first argument should be the address of the variable you want to set. (You may encounter bridging if you are on ARC mode)
2- Indexes start at 2 so e.g. index 2 is the first argument of the method.
[invocation setArgument:&arg1 atIndex:2];
[invocation setArgument:&arg2 atIndex:3];
[invocation setArgument:&arg3 atIndex:4];
[invocation setArgument:&arg4 atIndex:5];
1:
2:
3:
4:
And finally invoking our message:
[invocation invoke];
1:
Using NSInvocation for call-backs
The most interesting usage of NSInvocation is that we can setup a call-back method for another method using NSInvocation. Now you may ask "what is a call-back method?" There are many asynchronous operations such as NSURLConnection (which is bound to transfer some data through a network) or NSXMLParser (which has the duty to parse a XML document). Most times these operations do not return their results immediately. We can request and setup many of such operations to call our desired methods (call-back method) when they are done (may also pass the result to our call-back method through arguments).
NSInvocation with call-back example
Suppose myDummyObject has a method named processMyTasksWithCallBackFunction as follows: processMyTasksWithCallBackFunction dispatches its tasks asynchronously using GCD.
-(void)processMyTasksWithCallBackFunction: (NSInvocation *) invocation
{
dispatch_async(dispatch_get_main_queue(), ^{
@autoreleasepool {
NSLog(@"Performing tasks like accessing a web service or preparing data for app");
sleep(3);//waiting 3 seconds
NSLog(@"DONE! Now calling the callback function...");
///////// tasks are done; return the results through the NSInvocation object
///////// NSInvocation is supposed to point to a method which takes 4 NSString arguments
NSString *arg1 = @"Result1";
NSString *arg2 = @"Result2";
NSString *arg3 = @"Result3";
NSString *arg4 = @"Result4";
[invocation setArgument:&arg1 atIndex:2];
[invocation setArgument:&arg2 atIndex:3];
[invocation setArgument:&arg3 atIndex:4];
[invocation setArgument:&arg4 atIndex:5];
[invocation invoke];
}
});
}
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
Now we want to call processMyTasksWithCallBackFunction method and grab the results. Before that we have to declare a call-back method which takes 4 arguments (in our example). We declare this method in current class where we are calling processMyTasksWithCallBackFunction from. (Of course we can setup the call-back method from a remote object too.)
-(void)myFunctionWithArg1: (NSString*) arg1 Arg2: (NSString *) arg2 Arg3: (NSString *) arg3 Arg4: (NSString *) arg4
{
NSLog(@"I am a call-back method with 4 arguments: <%@> <%@> <%@> <%@>" , arg1, arg2, arg3, arg4);
}
1:
2:
3:
4:
Now we have to create the NSInvocation for our call-back method to be passed to processMyTasksWithCallBackFunction. Notice we don't set the arguments here because processMyTasksWithCallBackFunction will set them when it's done.
SEL CB_selector = @selector(myFunctionWithArg1:Arg2:Arg3:Arg4:);
NSMethodSignature *CB_signature = [self methodSignatureForSelector:CB_selector];
NSInvocation *CB_invocation = [NSInvocation invocationWithMethodSignature:CB_signature];
[CB_invocation setTarget:self];//Since we declared the call-back method in current class
[CB_invocation setSelector:CB_selector];
1:
2:
3:
4:
5:
Now we can call the asynchronous method:
[processMyTasksWithCallBackFunction: CB_invocation];
1:
2011-09-13 12:35:35.601 InvocationTest[6710:4903] Performing tasks like accessing a web service or preparing data for app
2011-09-13 12:35:38.603 InvocationTest[6710:4903] DONE! Now calling the callback function...
2011-09-13 12:35:38.604 InvocationTest[6710:4903] I am a call-back method with 4 arguments: <Result1> <Result2> <Result3> <Result4>
Conclusion
NSInvocation can bring great flexibility to your applications/frameworks in many situations. I hope this clarified NSInvocation and its usages. Please let me know if you have any question.
NSInvocation Basics的更多相关文章
- Objective-C中NSInvocation的使用
OC中调用方法某个对象的消息呦两种方式: #1. performanceSelector: withObject: #2. NSInvocation. 第一个PerformaceSelector比较常 ...
- Assembler : The Basics In Reversing
Assembler : The Basics In Reversing Indeed: the basics!! This is all far from complete but covers ab ...
- iOS开发——网络篇——UIWebview基本使用,NSInvocation(封装类),NSMethodSignature(签名),JavaScript,抛异常,消除警告
一.UIWebView简介 1.UIWebView什么是UIWebViewUIWebView是iOS内置的浏览器控件系统自带的Safari浏览器就是通过UIWebView实现的 UIWebView不但 ...
- The Basics of 3D Printing in 2015 - from someone with 16 WHOLE HOURS' experience
全文转载自 Scott Hanselman的博文. I bought a 3D printer on Friday, specifically a Printrbot Simple Metal fro ...
- Cadence UVM基础视频介绍(UVM SV Basics)
Cadence关于UVM的简单介绍,包括UVM的各个方面.有中文和英文两种版本. UVM SV Basics 1 – Introduction UVM SV Basics 2 – DUT Exampl ...
- C basics
C 日记目录 C basics ................ writing Numeration storage , structor space assigning pointer, a ...
- Xperf Basics: Recording a Trace(转)
http://randomascii.wordpress.com/2011/08/18/xperf-basics-recording-a-trace/ This post is obsolete ...
- Xperf Analysis Basics(转)
FQ不易,转载 http://randomascii.wordpress.com/2011/08/23/xperf-analysis-basics/ I started writing a des ...
- Radio Basics for RFID
Radio Basics for RFID The following is excerpted from Chapter 3: Radio Basics for UHF RFID from the ...
随机推荐
- memcached增删改查
1)add语法:add key flag expire byteskey 键flag 标志expire 过期时间,可以是秒或一个具体的时间戳bytes 要存的东西的bytes长度 PS:只能添加内存里 ...
- openssl安装
www.openssl.orgconfigure the environment:<pre lang="bash" escaped="true">t ...
- 警惕VPS服务商常用的超售手段
任何商业企业都希望将利益最大化,这是可以理解的.但如果做的过火最终损害的还是自己的利益.VPS服务提供商也一样,为了将利益最大化,他们往往会实用技术手段对所出售的VPS进行“超售”. 那么何谓“超售” ...
- 2016第20周四java基础概念
简单的说JDK=JRE+Java编译器.调试器.工具类库等:JRE=JVM(类似于jre目录下的bin)+必要运行的类库(类似于jre目录下的lib) JVM:Java Virtual Mechina ...
- RequireJS入门(一) 转
RequireJS由James Burke创建,他也是AMD规范的创始人. RequireJS会让你以不同于往常的方式去写JavaScript.你将不再使用script标签在HTML中引入JS文件,以 ...
- win下 golang 跨平台编译
mac 下编译其他平台的执行文件方式请参看这篇文章,http://www.cnblogs.com/ghj1976/archive/2013/04/19/3030703.html 本篇文章是win下的 ...
- [转]linux之nl命令
转自:http://www.cnblogs.com/peida/archive/2012/11/01/2749048.html nl命令在linux系统中用来计算文件中行号.nl 可以将输出的文件内容 ...
- HTML和URL比较
1.录制脚本的基本原则 2.HTML和URL based script介绍 3.选择录制方式原则 4.HTML based script设置
- org.unsaved transient instance - save the transient instance before flushing: bug解决方案
最近开发和学习过程中,遇到很多零碎的知识点,在此简单地记录下: 1.遇如下bug: org.unsaved transient instance - save the transient instan ...
- 【转】 Linux Shell 命令--rename
重命名文件,经常用到mv命令,批量重命名文件rename是最好的选择,Linux的rename 命令有两个版本,一个是C语言版本的,一个是Perl语言版本的,判断方法:输入man rename 看到第 ...