iOS NSInvocation的学习
用途:
NSInvocation的作用和performSelector:withObject:的作用是一样的:用于iOS编程中调用某个对象的消息。
performSelector:withObject:调用一些参数较少的消息是比较方便的,但是对于参数个数大于2的消息,使用NSInvocation还是比较方便的。
因为NSInvocation是静态的呈现Objective-C的消息,也就是说,它把一个行动变成了一个对象。NSInvocation对象用于对象之间和应用程序之间存储和转发消息,主要通过NSTimer对象和分布式对象系统来完成。
代码:
//
// NSInvocation+Improved.h
// InvocationDemo
//
// Created by 李振杰 on 13-12-11.
// Copyright (c) 2013年 swplzj. All rights reserved.
// #import <Foundation/Foundation.h> @interface NSInvocation (Improved) + (NSInvocation *)invocationWithTarget:(id)_target andSelector:(SEL)_selector;
+ (NSInvocation *)invocationWithTarget:(id)_target andSelector:(SEL)_selector andArguments:(void *)_addressOfFirstArgument, ...;
- (void)invokeOnMainThreadWaitUntilDone:(BOOL)wait; @end
//
// NSInvocation+Improved.m
// InvocationDemo
//
// Created by 李振杰 on 13-12-11.
// Copyright (c) 2013年 swplzj. All rights reserved.
// #import "NSInvocation+Improved.h" @implementation NSInvocation (Improved) + (NSInvocation *)invocationWithTarget:(id)_target andSelector:(SEL)_selector
{
//方法签名类
//需要给定一个方法,用于必须创建一个NSInvocation对象的情况下,例如在消息的转发。
NSMethodSignature *methodSig = [_target methodSignatureForSelector:_selector];
//根据方法签名类来创建一个NSInvocation
/*
一个NSInvocation是静态的呈现Objective-C的消息,也就是说,它是一个行动变成了一个对象。 NSInvocation对象用于对象之间和在应用程序之间存储和转发消息,主要通过NSTimer对象和分布式对象系统来完成。
*/
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
[invocation setTarget:_target];
[invocation setSelector:_selector];
return invocation;
} + (NSInvocation *)invocationWithTarget:(id)_target andSelector:(SEL)_selector andArguments:(void *)_addressOfFirstArgument, ...
{
NSMethodSignature *methodSig = [_target methodSignatureForSelector:_selector];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:methodSig];
[invocation setTarget:_target];
[invocation setSelector:_selector];
//获得签名类对象的参数个数
unsigned int numArgs = [methodSig numberOfArguments];
//PS:atIndex的下标必须从2开始。原因:0 1 两个参数已经被target 和selector占用
if (2 < numArgs) {
/*
VA_LIST 是在C语言中解决变参问题的一组宏,所在头文件:#include <stdarg.h>
VA_START宏,获取可变参数列表的第一个参数的地址(ap是类型为va_list的指针,v是可变参数最左边的参数)
VA_ARG宏,获取可变参数的当前参数,返回指定类型并将指针指向下一参数(t参数描述了当前参数的类型)
VA_END宏,清空va_list可变参数列表
*/ /*
用法:
(1)首先在函数里定义一具VA_LIST型的变量,这个变量是指向参数的指针;
(2)然后用VA_START宏初始化刚定义的VA_LIST变量;
(3)然后用VA_ARG返回可变的参数,VA_ARG的第二个参数是你要返回的参数的类型(如果函数有多个可变参数的,依次调用VA_ARG获取各个参数);
(4)最后用VA_END宏结束可变参数的获取。
*/
va_list varargs; va_start(varargs, _addressOfFirstArgument);
[invocation setArgument:_addressOfFirstArgument atIndex:2]; for (int argIndex = 3; argIndex < numArgs; argIndex++) {
void *argp = va_arg(varargs, void *);
[invocation setArgument:argp atIndex:argIndex];
} va_end(varargs);
}
return invocation;
} - (void)invokeOnMainThreadWaitUntilDone:(BOOL)wait
{
[self performSelectorOnMainThread:@selector(invoke) withObject:nil waitUntilDone:wait];
} @end
自定义类:
//
// SomeClass.h
// InvocationDemo
//
// Created by 李振杰 on 13-12-11.
// Copyright (c) 2013年 swplzj. All rights reserved.
// #import <Foundation/Foundation.h> @interface SomeClass : NSObject - (void)commonOperation;
- (void)improvedOperation;
- (void)fireTimer:(NSDictionary *)user andDate:(NSDate *)startTime; @end
//
// SomeClass.m
// InvocationDemo
//
// Created by 李振杰 on 13-12-11.
// Copyright (c) 2013年 swplzj. All rights reserved.
// #import "SomeClass.h"
#import "NSInvocation+Improved.h" @implementation SomeClass - (void)commonOperation
{
NSDate *date = [NSDate date];
NSDictionary *user = [NSDictionary dictionaryWithObjectsAndKeys:@"value1", @"key1", nil];
SEL method = @selector(fireTimer:andDate:);
NSMethodSignature *signature = [[self class] instanceMethodSignatureForSelector:method];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setTarget:self];
[invocation setSelector:method];
[invocation setArgument:&user atIndex:2];
[invocation setArgument:&date atIndex:3];
// [NSTimer scheduledTimerWithTimeInterval:0.1 invocation:invocation repeats:YES];
[invocation invoke];
} - (void)improvedOperation
{
//1.创建一个没有参数的NSInvocation
// SEL selector = @selector(fireTimer:andDate:);
// NSInvocation *invocation = [NSInvocation invocationWithTarget:self andSelector:selector]; //2.创建带有两个参数的NSInvocation
NSDate *date = [NSDate date];
NSDictionary *user = [NSDictionary dictionaryWithObjectsAndKeys:@"value1", @"key1", nil];
NSInvocation *invocation = [NSInvocation invocationWithTarget:self andSelector:@selector(fireTimer:andDate:) andArguments:&user, &date];
[invocation invoke];
} - (void)fireTimer:(NSDictionary *)user andDate:(NSDate *)startTime
{
/*
sleep 与 sleepForTimeInterval的区别
sleep直接让线程停掉,sleepForTimeInterval是让runLoop停掉。比如说,你有2个APP,分别是A和B,A启动B,然后去取B的进程号,如果你用sleep等B启动再去取,你会发现取不到,因为你只是把代码加到runloop里面去,而runloop并没有执行到这句,sleep就直接让系统停在那里,所以取不到,而后者就没问题,因为它是让runloop执行到这句的时候停1s
*/ [NSThread sleepForTimeInterval:2];
NSTimeInterval timeInterval = -1 * [startTime timeIntervalSinceNow];
NSString *timeStr = [NSString stringWithFormat:@"%.2f", timeInterval];
NSLog(@"fireTime: %@", timeStr);
} @end
调用SomeClass:
//
// AppDelegate.m
// InvocationDemo
//
// Created by 李振杰 on 13-12-11.
// Copyright (c) 2013年 swplzj. All rights reserved.
// #import "AppDelegate.h"
#import "SomeClass.h" @implementation AppDelegate - (void)dealloc
{
[_window release];
[super dealloc];
} - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.window = [[[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]] autorelease];
// Override point for customization after application launch. SomeClass *some = [[SomeClass alloc] init];
[some commonOperation];
[some improvedOperation];
[some release]; self.window.backgroundColor = [UIColor whiteColor];
[self.window makeKeyAndVisible];
return YES;
} @end
Demo源码:
iOS NSInvocation的学习的更多相关文章
- IOS NSInvocation用法简介
IOS NSInvocation用法简介 2012-10-25 19:59 来源:博客园 作者:csj007523 字号:T|T [摘要]在 iOS中可以直接调用某个对象的消息方式有两种,其中一种就是 ...
- iOS开发如何学习前端(2)
iOS开发如何学习前端(2) 上一篇成果如下. 实现的效果如下. 实现了一个横放的<ul>,也既iOS中的UITableView. 实现了当鼠标移动到列表中的某一个<li>,也 ...
- iOS开发如何学习前端(1)
iOS开发如何学习前端(1) 我为何学前端?因为无聊. 概念 前端大概三大块. HTML CSS JavaScript 基本上每个概念在iOS中都有对应的.HTML请想象成只能拉Autolayout或 ...
- 移动开发iOS&Android对比学习--异步处理
在移动开发里很多时候需要用到异步处理.Android的主线程如果等待超过一定时间的时候直接出现ANR(对不熟悉Android的朋友这里需要解释一下什么叫ANR.ANR就是Application Not ...
- 关于iOS开发的学习
关于iOS开发的学习,打个比方就像把汽车分解: 最底层的原料有塑料,钢铁 再用这些底层的东西造出来发动机,座椅 最后再加上写螺丝,胶水等,把汽车就拼起来了 iOS基本都是英文的资料, ...
- IOS科研IOS开发笔记学习基础知识
这篇文章是我的IOS学习笔记,他们是知识的基础,在这里,根据记录的查询后的条款. 1,UIScrollView能完毕滚动的功能. 示比例如以下: UIScrollView *tableScrollVi ...
- iOS核心动画学习整理
最近利用业余时间终于把iOS核心动画高级技巧(https://zsisme.gitbooks.io/ios-/content/chapter1/the-layer-tree.html)看完,对应其中一 ...
- iOS CoreData技术学习资源汇总
一.CoreData学习指引 1. 苹果官方:Core Data Programming Guide 什么是CoreData? 创建托管对象模型 初始化Core Data堆栈 提取对象 创建和修改自定 ...
- IOS内存管理学习笔记
内存管理作为iOS中非常重要的部分,每一个iOS开发者都应该深入了解iOS内存管理,最近在学习iOS中整理出了一些知识点,先从MRC开始说起. 1.当一个对象在创建之后它的引用计数器为1,当调用这个对 ...
随机推荐
- flash文件运动节奏的控制
flash里面,比较难的是控制运动的节奏.参考了几个韩国网站的fla源文件,提出以下几个建议与参考. 1,flash文件里面,每秒的帧数 设置为 120,或者一个比较大的数字(90,60).普通的文件 ...
- nuc900 nand flash mtd 驱动
nuc900 nand flash mtd 驱动,请参考! /* * Copyright © 2009 Nuvoton technology corporation. * * Wan ZongShun ...
- SASS type-of 函数
今儿写个type-of,算是备忘录吧. 1.number type-of(0) // number type-of(1px) // number 2.string type-of(a) // stri ...
- PHP转换IP地址到真实地址的方法详解
本篇文章是对PHP转换IP地址到真实地址的方法进行了详细的分析介绍,需要的朋友参考下 想要把IPv4地址转为真实的地址,肯定要参考IP数据库,商业的IP数据库存储在关系型数据库中,查询和使用都非常 ...
- C语言基础学习运算符-赋值运算符
简单赋值 在C语言里,运算符=并不表示相等,而是一个赋值运算符.这意味着,符号=的左边该是一个可修改的变量名,而右边是赋给该变量的值. 如下程序语句: i = i+; 在数学上,该等式无法成立.而作为 ...
- linux修改环境变量
/etc/profile 系统全局环境变量设定,所有用户共享,修改后,需要重启系统才能生效 ~/.bash_profile,~/.bashrc 用户目录下的私有环境变量设定,常用来个性化定制功能,修改 ...
- WinPcap编程(前言&&学习)
计算机网络课设要求用WinPcap写对ARP包的接收与发送. 所以学了一下WinPcap的内容. 参考的博客: http://blog.csdn.net/htttw/article/details/7 ...
- Linux文本操作三大利器总结:sed、awk、grep
grep:(去除一行中需要的信息,同类与cut) grep全称是Global Regular Expression Print #常规用法 # grep -n root /etc/passwd :ro ...
- WebApi 4.0 默认方式不支持HttpGet 请求
如果Controller方法中没有指定请求方式,在RC版本中默认是HttpPost ,Beta版本中支持所有方法GET, PUT, POST and Delete,而在RC版本后做了改变只支持Http ...
- 『Python』 ThreadPool 线程池模板
Python 的 简单多线程实现 用 dummy 模块 一句话就可以搞定,但需要对线程,队列做进一步的操作,最好自己写个线程池类来实现. Code: # coding:utf-8 # version: ...