如何取得ChipmunkConstraint实例对象的私有属性
在 如何用代码禁用SpriteBuilder中创建的关节 一篇中提到了要想禁用一个关节就需要将其无效化。
然后我们在重新创建新关节时,可以参考该关节的原始参数。
但是代码中只能直接访问到bodyA和bodyB两个属性,anchorA、anchorB以及minDistance、maxDistance等4个属性无法直接访问到,书上称之为这些属性为私有属性(private property)。其实只要你包含了对应的头文件,就可以在自己的代码中直接引用它们。
由于这些属性值在例子中永不变化,所以书中使用了硬编码的方法来赋给新的关节,代码如下:
_lockJoint = [CCPhysicsJoint connectedDistanceJointWithBodyA:_lockJoint.bodyA
bodyB:_lockJoint.bodyB anchorA:ccp(0.0, -300.0)
anchorB:ccp(32.0, 32.0) minDistance:223.0
maxDistance:223.0];
但是需要知道的是,以上4个属性毫无疑问是存放在_lockJoint中的,只是无法直接访问到,下面就想办法从代码中直接取到这4个属性。
首先,obj-c中不存在真正的所谓私有方法,我们一般将不在interface中或在interface () 中声明的方法称之为私有方法。这种私有方法,不能直接通过[obj privagteMethod]的方式调用,编译器会抱怨一个错误的:告知类中没有该实例方法。
我们首先可以尝试用performSelector来取得该属性(因为不管啥属性其实也就是对应的2个方法;这里不考虑set方法,只考虑get方法)。
[obj performSelector:@selector(privateMethod)];
这样是可以调用到该私有方法,看上去很美 ;)
但是且慢,返回值不是id类型怎么办!?
对于返回值小于等于4bytes(因为在我的mac上sizeof(id)返回4)的方法,或许可以试试强制转换。但是double和CGPoint都大于4bytes,这样返回的值会被截断,结果肯定不正确。
我们可以看一下这4个属性在对于头文件中的声明:
@interface ChipmunkSlideJoint : ChipmunkConstraint
/**
Create an autoreleased slide joint between the two bodies with the given anchor points and distance range.
*/
+ (ChipmunkSlideJoint *)slideJointWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB min:(cpFloat)min max:(cpFloat)max;
/**
Initialize a slide joint between the two bodies with the given anchor points and distance range.
*/
- (id)initWithBodyA:(ChipmunkBody *)a bodyB:(ChipmunkBody *)b anchorA:(cpVect)anchorA anchorB:(cpVect)anchorB min:(cpFloat)min max:(cpFloat)max;
/// The anchor point on the first body.
@property(nonatomic, assign) cpVect anchorA;
/// The anchor point on the second body.
@property(nonatomic, assign) cpVect anchorB;
/// The minimum allowed distance between anchor points.
@property(nonatomic, assign) cpFloat min;
/// The maximum allowed distance between anchor points.
@property(nonatomic, assign) cpFloat max;
@end
可以知道cpFloat和cpVect实际分别对应于double和CGPoint。
我们先来搞定返回值为double的属性(sizeof(double)为8)。大家知道调用对象的方法实际是向该对象发消息(performSelector内部也是如此),由此引出一个返回double的专有函数:
#import <objc/message.h>
objc_msgSend_fpret(instance,selector,...);
上面selector就是@selector(min)或者@selector(max),但是instance是神马呢?其实CCPhysicsJoint实例中有一个constraint属性,该属性又是另一个“私有”类ChipmunkConstraint的实例,所以我们要先取到constraint属性:
id cs = [_lockJoint performSelector:@selector(constraint)];
因为该私有方法正好返回一个id所以可以直接用performSelector来取得该属性。下面我们来取min和max的值:
double min = objc_msgSend_fpret(cs, @selector(min));
double max = objc_msgSend_fpret(cs, @selector(max));
that’s all!
接下来是返回CGPoint的anchorA、anchorB方法。
对于取得返回为结构这种情况,我们可以考虑用obj-c的invocation机制来完成。
首先用方法签名创建一个NSInvocation对象:
NSInvocation *invo = [NSInvocation invocationWithMethodSignature:[[Constraint class]
instanceMethodSignatureForSelector:@selector(anchorA)]];
这里的Constraint不可以用ChipmunkConstraint,而必须用其对应的子类ChipmunkSlideJoint。因为anchorA、anchorB方法是在这些子类中定义的。这个不像前面的向一个对象sendMsg的情况,前面会动态根据实际对象类型执行特定方法,这是在运行时完成的。而这里取得方法签名是在编译时完成的,如果该方法不在对应类类(即使在其子类中),instanceMethodSignaturForSelector会返回nil,从而使得invocationWithMethodSignature:抛出异常。
所以我们有:
Class Constraint = NSClassFromString(@"ChipmunkSlideJoint");
NSInvocation *invo = [NSInvocation invocationWithMethodSignature:[[Constraint class]
instanceMethodSignatureForSelector:@selector(anchorA)]];
[invo setSelector:@selector(anchorA)];
[invo setTarget:cs];
[invo invoke];
CGPoint pa;
[invo getReturnValue:&pa];
取anchorA和上面类似,不再赘述。
如何取得ChipmunkConstraint实例对象的私有属性的更多相关文章
- python-面向对象-06_私有属性和私有方法
私有属性和私有方法 01. 应用场景及定义方式 应用场景 在实际开发中,对象 的 某些属性或方法 可能只希望 在对象的内部被使用,而 不希望在外部被访问到 私有属性 就是 对象 不希望公开的 属性 私 ...
- Java反射机制(三):调用对象的私有属性和方法
一. 通过反射调用类中的方法 在正常情况下,得到类的对象后,我们就可以直接调用类中的方法了,如果要想调用的话,则肯定必须清楚地知道要调用的方法是什么,之后通过Class类中的getMethod方法,可 ...
- python中类对象、实例对象、类属性、实例属性、类方法、实例方法、静态方法
类对象.类属性与实例对象.实例属性的区别 在Python中一切皆是对象,类是一个特殊的对象即类对象,描述类的属性称为类属性.类属性在内存中只有一份,在__init__外部定义. 通过类创建的对象称为实 ...
- Java反射学习总结二(用反射调用对象的私有属性和方法)
大家都知道正常的调用是不可以访问对象的private修饰的属性和方法的,这也是Java的封装性原则. 但是有没有方法可以强制去访问对象的private修饰的属性和方法呢?那就是用反射!(这个可能在面试 ...
- 理解Python中的类对象、实例对象、属性、方法
class Animal(object): # 类对象 age = 0 # 公有类属性 __like = None # 私有类属性 def __init__(self): # 魔法方法 self.na ...
- vue-learning:41 - Vuex - 第二篇:const store = new Vue.Store(option)中option选项、store实例对象的属性和方法
vuex 第二篇:const store = new Vue.Store(option)中option选项.store实例对象的属性和方法 import Vuex from 'vuex' const ...
- JS高级---实例对象使用属性和方法层层的搜索 (实例对象-->原型对象-->报错)
实例对象使用属性和方法层层的搜索: 实例对象使用的属性或者方法, 先在实例中查找, 找到了则直接使用: 找不到则, 再去实例对象的__proto__指向的原型对象prototype中找, 找到了则 ...
- JavaScript基础对象创建模式之私有属性和方法(024)
JavaScript没有特殊的语法来表示对象的私有属性和方法,默认的情况下,所有的属性和方法都是公有的.如下面用字面声明的对象: var myobj = { myprop: 1, getProp: f ...
- JavaScript中的 原型 property 构造函数 和实例对象之间的关系
1 为什么要使用原型? /* * javascript当中 原型 prototype 对象 * * */ //首先引入 prototype的意义,为什么要使用这个对象 //先来写一个构造函数的面向对象 ...
随机推荐
- ThreadLocal深入剖析
JDK 1.2的版本中就提供java.lang.ThreadLocal,ThreadLocal为解决多线程程序的并发问题提供了一种新的思路.使用这个工具类可以很简洁地编写出优美的多线程程序,Threa ...
- logstash分析日志
待处理日志格式如下: [totalCount: 298006556, count: 287347623, queryCount: 259027994, exeCount: 28319629, tota ...
- Python 2.7的字典实现简化版(C语言)
这是一个能自动调整大小的哈希字典,外部接口实现了下列功能. 1.字典级别: 创建字典 dict_new 归零字典 dict_clear 2.键值级别: 查找 dict_search 强制查找 dict ...
- RxJava(五) onErrorResumeNext操作符实现app与服务器间token机制
欢迎转载,转载请标明出处: http://blog.csdn.net/johnny901114/article/details/51533586 本文出自:[余志强的博客] 一.需求场景: 在开发Ap ...
- xlsx批量转为utf8的csv
xlsx批量转为utf8的csv(金庆的专栏)策划的配置表为 xlsx 表格,可以有注释,公式.服务器和客户端使用的配置文件需要转成 csv 文件.使用 WPS 另存无法批量转换,并且结果不是utf8 ...
- Struts 2 之校验器
对于输入校验,Struts2提供了两种方式,1.使用validate方法:2.基于XML配置实现 . validate()方法 支持校验的Action必须实现Validateable接口,一般直接继承 ...
- 线程在Linux中的实现
早在以前,我们就知道,CPU调度的基本单位是线程,而进程是拥有资源的基本单位,进程是用进程描述符表示的,那么线程是怎么实现和表示的呢? 线程机制是现代编程技术中常用的一种抽象概 ...
- 利用Camera和Matrix实现有趣的卡片效果
这篇文章主要讲解一个翻转切换内容的卡片效果,主要利用Camera和Matrix来实现,主要是为了加深对Camera和Matrix的理解,如果对Camera和Matrix不清楚地童鞋可以看我的上篇文章: ...
- Java基础---Java---基础加强---类加载器、委托机制、AOP、 动态代理技术、让动态生成的类成为目标类的代理、实现Spring可配置的AOP框架
类加载器 Java虚拟机中可以安装多个类加载器,系统默认三个主要类加载器,每个类负责加载特定位置的类:BootStrap,ExtClassLoader,AppClassLoader 类加载器也是Jav ...
- HTML5中 HTML表单和PHP环境搭建及与PHP交互 韩俊强的博客
每日更新关注:http://weibo.com/hanjunqiang 新浪微博! 知识点概括:HTML表单/PHP环境搭建/表单提交数据与PHP交互 第一部分:HTML表单 <!DOCTYP ...