IOS开发反射和动态调用总结

和java一样,Object-C也提供了反射的机制。

每一个类都有一个Class,获取Class有以下三种方法。

// insert code here...
        //通过字符串获取class
        Class   clazz = NSClassFromString(@"NSString");
        NSLog(@"clazz的类型是%@",clazz);
        //直接用calzz 来创建对象
        id str  = [[clazz alloc] init];
        //通过对象来获取class
        NSLog(@"%@",[str class]);
        //通过类来获取class
        NSLog(@"%d",clazz==NSString.class);
        NSLog(@"Hello, World!");

/**

2015-04-28 17:03:18.907 反射[1322:303] clazz的类型是NSString

2015-04-28 17:03:19.279 反射[1322:303] __NSCFConstantString

2015-04-28 17:03:19.280 反射[1322:303] 1

2015-04-28 17:03:19.281 反射[1322:303] Hello, World!

Program ended with exit code: 0

打印出来的结果是这样,_NSString只是类簇的前端而已

**/

对与第一种和第二种方式,都是根据类获取Class对象,比较之下,第一种代码安全性更高,程序再编译阶段就可以检测所需要访问的Class是否存在。性能更高,因为无需调用方法。

动态调用的方法如下。直接上代码

#import <Foundation/Foundation.h>
@interface JQCar : NSObject

@end
#import "JQCar.h"
#import <objc/message.h>
@implementation JQCar
- (void)move:(NSNumber*)count{
    int num  = [count intValue];
    for (int i=0; i<num; i++) {
        NSLog(@"%@",[NSString stringWithFormat:@"汽车正在路上行走%d",i]);
    }
}
- (double)addSpeed:(double)factor{
  //动态调用move方法
 //使用performSelector动态调用move方法
    [self performSelector:@selector(move:) withObject:[NSNumber numberWithInt:2]];
    [self performSelector:NSSelectorFromString(@"move:") withObject:[NSNumber numberWithInt:2]];
    //使用objc_msgSend()函数动态调用
    objc_msgSend(self,@selector(move:),[NSNumber numberWithInt:2]);
    objc_msgSend(self, NSSelectorFromString(@"move:"),[NSNumber numberWithInt:3]);
    NSLog(@"正在加速%g",factor);
    return 100*factor;
}
@end

使用objc_msgSend可能报错

//objc_msgSend()报错Too many arguments to function call ,expected 0,have3

解决方法

//Build Setting--> Apple LLVM 6.0 - Preprocessing--> Enable Strict Checking of objc_msgSend Calls  改为 NO

#import <Foundation/Foundation.h>
#import <objc/message.h>
#import "JQCar.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        // insert code here...
        //获取JQCar类
        Class clazz = NSClassFromString(@"JQCar");
        //动态创建car
        id car  = [[clazz alloc] init];
        //使用performSelector方法来动态调用
        [car performSelector:@selector(addSpeed:) withObject:[NSNumber numberWithLong:2]];
        //使用Objec_send来动态调用
        objc_send(car,@selector(addSpeed:),3.4);
        //定义函数指针变量
        double (*addSpeed)(id ,SEL,double);
        //获取car对象的addSpeed方法,再把addSpeed方法赋值给addSpeed指针变量
        addSpeed = (double (*)(id,SEL,double))[car methodForSelector:NSSelectorFromString(@"addSpeed:")];
        //调用addSpeed
        double speed = addSpeed(car, @selector(addSpeed:), 3.4);
        NSLog(@"加速后的速度是%g",speed);

        NSLog(@"Hello, World!");
    }
    return 0;
}
时间: 2024-08-05 07:07:19

IOS开发反射和动态调用总结的相关文章

基于反射的动态调用-不止是code和oop,还有类加载方案

先给出基础类资源的代码,很容易理解,不做过多介绍: 1 package oop; 2 interface t { 3 public static final String name="zhangph"; 4 } 5 public class Father implements t{ 6 private static int mem; 7 static { 8 System.out.println("这是父类");//因为你不曾常用反射,所以加上这段代码显示区别 9

IOS开发之──应用之间调用(2)

在上一篇文章中,讲解了如何在自己应用之间调用问题,今天介绍一下如果调用IOS自带的app的方法 一.调用app store界面方法 在实际开发中,往往要推荐自己其他应用和推荐自己的收费软件,那么我们就需要在程序中直接连接到app store的相应页面. 实际上的做法很简单,使用的还是UIApplication类的OpenURL方法: [[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"程序的相应连接"]];

iOS开发-编译使用动态库

bogon:AlipaySDK.framework loyinglin$ lipo -info AlipaySDK Architectures in the fat file: AlipaySDK are: i386 x86_64 armv7 armv7s arm64 bogon:lib loyinglin$ lipo -info libssl.a Architectures in the fat file: libssl.a are: armv7 armv7s i386 x86_64 arm6

iOS开发&mdash;&mdash;Autolayout下动态调整单元格高度

情景描述: 有时候我们希望更新某一个单元格的数据,通常的做法是使用reloadData方法更新整个单元格.但是对一些情况是不适用的或者说实现起来比较麻烦.比如说这种简单的"点开"一个单元格 在没点开时,英雄的简介被替换为"点击查看详情",下载按钮被设为隐藏. 这样的话如果在点开时reload整个表格的数据,表格因为重载数据还是会恢复成没有点开的状态.   解决步骤: 使用Autolayout的优点是可以让内容决定单元格的高度.那么有什么办法能在内容改变后动态地调整单

ios开发,javascript直接调用oc代码而非通过改变url回调方式

之前一个ios项目中,需要通过UIWebview来打开一个静态页面,并在静态页面中 调用相关object-c代码. 一.以前使用js调用object-c的方法 关于如何使用javascript调用object-c中的函数和方法,我搜索了好久 网上所有的方法,基本都指明了一个方向,那就是在UIWebview中载入的js代码中 通过改变document.locations="",然后回调UIWebview的 -(BOOL)webView:(UIWebView *)webView shoul

C# 通过反射类动态调用DLL方法

网上看了很多关于反射的思路和方法,发现这个还算不错 //使用反射方: using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Reflection; namespace ConsoleApplication1 { class Program { static void Main(string[] args) { //声明一个反射类对象 Assembly a

iOS开发笔记--什么时候调用layoutSubviews

今天在写程序时候遇见layoutSubviews触发时候引起的问题.特来总结一下什么时候会触发layoutSubviews:layoutSubviews在以下情况下会被调用: 1.init初始化不会触发layoutSubviews 2.addSubview会触发layoutSubviews 3.设置view的Frame会触发layoutSubviews,当然前提是frame的值设置前后发生了变化 4.滚动一个UIScrollView会触发layoutSubviews 5.旋转Screen会触发父

[IOS 开发] 反射

首先我们要知道,这使用的是运行时的反射机制 所以我们需要头文件 runtime.h +(BOOL)checkoutOneTabByName:(NSString*)oneName { //openDB FMDatabase *db = [DatabaseOperation openDataBase]; NSArray *array = [DatabaseOperation queryTable:oneName QueryString:[NSString stringWithFormat:@"sel

IOS开发之──应用之间调用(1)

iphone应用之间调用步骤: 1)在plist文件中,注册对外接口 在xcode group&files 里面,展开 resources选择<app>info.plist 鼠标右击information property list ,然后从列表中选择URL types 右击 add row 添加一个对象(item)右击item add row 从列表中选择 URL  Schemes 再右击添加一个对象(item1) 将item1得值设置为:myapp 这个myapp就是对外接口,其它