如何用代码禁用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实例对象的私有属性的更多相关文章

  1. python-面向对象-06_私有属性和私有方法

    私有属性和私有方法 01. 应用场景及定义方式 应用场景 在实际开发中,对象 的 某些属性或方法 可能只希望 在对象的内部被使用,而 不希望在外部被访问到 私有属性 就是 对象 不希望公开的 属性 私 ...

  2. Java反射机制(三):调用对象的私有属性和方法

    一. 通过反射调用类中的方法 在正常情况下,得到类的对象后,我们就可以直接调用类中的方法了,如果要想调用的话,则肯定必须清楚地知道要调用的方法是什么,之后通过Class类中的getMethod方法,可 ...

  3. python中类对象、实例对象、类属性、实例属性、类方法、实例方法、静态方法

    类对象.类属性与实例对象.实例属性的区别 在Python中一切皆是对象,类是一个特殊的对象即类对象,描述类的属性称为类属性.类属性在内存中只有一份,在__init__外部定义. 通过类创建的对象称为实 ...

  4. Java反射学习总结二(用反射调用对象的私有属性和方法)

    大家都知道正常的调用是不可以访问对象的private修饰的属性和方法的,这也是Java的封装性原则. 但是有没有方法可以强制去访问对象的private修饰的属性和方法呢?那就是用反射!(这个可能在面试 ...

  5. 理解Python中的类对象、实例对象、属性、方法

    class Animal(object): # 类对象 age = 0 # 公有类属性 __like = None # 私有类属性 def __init__(self): # 魔法方法 self.na ...

  6. 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 ...

  7. JS高级---实例对象使用属性和方法层层的搜索 (实例对象-->原型对象-->报错)

    实例对象使用属性和方法层层的搜索:   实例对象使用的属性或者方法, 先在实例中查找, 找到了则直接使用: 找不到则, 再去实例对象的__proto__指向的原型对象prototype中找, 找到了则 ...

  8. JavaScript基础对象创建模式之私有属性和方法(024)

    JavaScript没有特殊的语法来表示对象的私有属性和方法,默认的情况下,所有的属性和方法都是公有的.如下面用字面声明的对象: var myobj = { myprop: 1, getProp: f ...

  9. JavaScript中的 原型 property 构造函数 和实例对象之间的关系

    1 为什么要使用原型? /* * javascript当中 原型 prototype 对象 * * */ //首先引入 prototype的意义,为什么要使用这个对象 //先来写一个构造函数的面向对象 ...

随机推荐

  1. python模块:时间处理模块

    http://blog.csdn.net/pipisorry/article/details/53067168 常用python自带时间处理模块 python自带的时间处理模块参考[操作系统服务:ti ...

  2. mysql字符集,insert,update,delete,select

    发现有错误:数据太长了.//查看数据库的所有编码:show variables like 'character%';-----+| character_set_client     | utf8    ...

  3. Android自动打包工具aapt详解

    概念 在Android.mk中有LOCAL_AAPT_FLAGS配置项,在gradle中也有aaptOptions,那么aapt到底是干什么的呢? aapt即Android Asset Packagi ...

  4. ejabberd编译更新脚本

    ejabberd编译更新脚本 (金庆的专栏 2016.8) 用rebar编译ejabberd源码,然后复制编译所得beam文件到ejabberd安装目录, 调用ejabberdctl热更新. call ...

  5. 24 AIDL案例

    服务端 MainActivity.java package com.qf.day24_aidl_wordserver; import android.app.Activity; import andr ...

  6. Linux 高性能服务器编程——多线程编程

    问题聚焦:     在简单地介绍线程的基本知识之后,主要讨论三个方面的内容:    1 创建线程和结束线程:    2 读取和设置线程属性:    3 线程同步方式:POSIX信号量,互斥锁和条件变量 ...

  7. everything of people’s life can changed in their twenties

    还记得三年前,独自背着行李,流浪远方,来到曾经只在地理课本上才熟悉的北国,带着好奇,带着期望,带着激动的心情,想感受毛爷爷当年霸气的北国风光,千里冰封的美丽,想知道北方的面条到底有多少种花样,想走进那 ...

  8. iOS中 UITableViewCell cell划线那些事 韩俊强的博客

    每日更新关注:http://weibo.com/hanjunqiang 在开发中经常遇到cell分割线显示不全或者想自定义线的宽高等; 最近总结了一下,希望帮到大家: 1.不想划线怎么办? Table ...

  9. 使用TT模板+mvc+wcf实现简单查询

    今天是除夕,小编的这篇博客是掐着点儿发的,在此,祝各位小伙伴新年快乐,身体健康,万事如意:喜从天降,欣喜若狂:喜气盈门,好事成双:好人好运,金玉满堂:神采飞扬,如愿以偿,财源滚滚来,福如东海长:伴随着 ...

  10. C++对C的函数拓展 - 占位参数

    函数占位参数 占位参数只有参数类型声明,而没有参数名声明 一般情况下,在函数体内部无法使用占位参数 demo #include <iostream> using namespace std ...