我正在尝试编写一些动态代码,用户可以尝试从类的特定实例调用方法,并在运行时解析它.检索信息的实现存在,但访问它的方法不存在,因为它基于每个实例.
例如,用户可能想要调用类中不存在的名为"getSomething"的方法:
[someInstance getSomething]
Run Code Online (Sandbox Code Playgroud)
在这种情况下,我希望有一个实现已解析,它具有一个仅适用于正在处理的实例的变量返回类型.我正在考虑使用Objective-C中的class_addMethod,但我并不是100%肯定它的行为.在文档中,它声称这可以用于添加类或实例方法.调用此类是否仅将方法添加到特定实例或类中,以便之后创建的每个实例都将具有该方法?我还读到,一旦添加了一个方法,你就无法删除它.
也许我的方法不正确,所以如果知道任何替代方案我会很感激.我不能使用消息转发,因为没有类可以理解已经实现的选择器.
我正在寻找一种方法来获取某个类的静态方法列表.我只获得了运行时函数的实例方法列表class_copyMethodList().
有没有办法列出静态方法?
我有一个返回a的类方法CGSize,我想通过Objective-C运行时函数调用它,因为我将类和方法名称作为字符串值.
我正在使用XCode 4.2中的ARC标志进行编译.
方法签名:
+(CGSize)contentSize:(NSString *)text;
Run Code Online (Sandbox Code Playgroud)
我尝试的第一件事是用objc_msgSend这样调用它:
Class clazz = NSClassFromString(@"someClassName);
SEL method = NSSelectorFromString(@"contentSize:");
id result = objc_msgSend(clazz, method, text);
Run Code Online (Sandbox Code Playgroud)
这与"EXC_BAD_ACCESS"崩溃并且没有堆栈跟踪.我首先使用了这个,因为文档objc_msgSend说,
当遇到一个方法调用,编译器生成到的功能之一的呼叫
objc_msgSend,objc_msgSend_stret,objc_msgSendSuper,或objc_msgSendSuper_stret.[...]使用objc_msgSendSuper_stret和发送具有数据结构作为返回值的方法objc_msgSend_stret.
接下来,我用objc_msgSend_stret这样的:
Class clazz = NSClassFromString(@"someClassName);
SEL method = NSSelectorFromString(@"contentSize:");
CGSize size = CGSizeMake(0, 0);
objc_msgSend_stret(&size, clazz, method, text);
Run Code Online (Sandbox Code Playgroud)
使用上面的签名给出了以下两个编译器错误和两个警告:
错误:自动引用计数问题:ARC不允许将非Objective-C指针类型'CGSize*'(又名'struct CGSize*')隐式转换为'id'
警告:语义问题:不兼容的指针类型将'CGSize*'(又名'struct CGSize*')传递给'id'类型的参数
错误:自动引用计数问题:ARC不允许将Objective-C指针隐式转换为"SEL"
警告:语义问题:不兼容的指针类型将'__unsafe_unretained Class'传递给'SEL'类型的参数
如果我查看方法的声明,它是:
OBJC_EXPORT void objc_msgSend_stret(id self, SEL op, ...)
__OSX_AVAILABLE_STARTING(__MAC_10_0, __IPHONE_2_0);
Run Code Online (Sandbox Code Playgroud)
这与 …
struct objective-c objective-c-runtime class-method automatic-ref-counting
我正在搞乱Objective-C运行时,尝试编译Objective-c代码而不将其链接起来libobjc,并且我对程序有一些分段错误问题,所以我从中生成了一个汇编文件.我认为没有必要显示整个程序集文件.在我的main功能的某些方面,我有以下一行(顺便说一句,这是我得到seg错误之后的行):
callq *l_objc_msgSend_fixup_alloc
Run Code Online (Sandbox Code Playgroud)
这是以下定义l_objc_msgSend_fixup_alloc:
.hidden l_objc_msgSend_fixup_alloc # @"\01l_objc_msgSend_fixup_alloc"
.type l_objc_msgSend_fixup_alloc,@object
.section "__DATA, __objc_msgrefs, coalesced","aw",@progbits
.weak l_objc_msgSend_fixup_alloc
.align 16
l_objc_msgSend_fixup_alloc:
.quad objc_msgSend_fixup
.quad L_OBJC_METH_VAR_NAME_
.size l_objc_msgSend_fixup_alloc, 16
Run Code Online (Sandbox Code Playgroud)
我重新实现objc_msgSend_fixup了一个函数(id objc_msgSend_fixup(id self, SEL op, ...))返回nil(只是为了看看会发生什么),但是这个函数甚至没有被调用(程序在调用之前崩溃).
所以,我的问题是,callq *l_objc_msgSend_fixup_alloc应该做什么以及objc_msgSend_fixup(之后l_objc_msgSend_fixup_alloc:)应该是什么(一个函数或一个对象)?
编辑
为了更好地解释,我没有将我的源文件与objc库链接.我想要做的是实现libray的一些部分,只是为了看它是如何工作的.这是我所做的一种方法:
#include <stdio.h>
#include <objc/runtime.h>
@interface MyClass {
}
+(id) alloc;
@end
@implementation MyClass
+(id) alloc {
// alloc the object
return nil;
}
@end
id objc_msgSend_fixup(id …Run Code Online (Sandbox Code Playgroud) 是否有可能在类层次结构中找到检索方法的class_getInstanceMethod来源?例如,假设A类实现了myMethod.现在说我已经在A1类中继承了A类.如果我打电话class_getInstanceMethod(ClassA1, myMethod),是否可以判断结果方法是否已在ClassA1中被覆盖或直接来自A1?
我想如果你有权访问ClassA和ClassA1,就可以比较IMP的内存地址,但是我没有直接访问A.
Class bah = [NSString class];
id object = [bah new];
Run Code Online (Sandbox Code Playgroud)
编译完全没有问题.
Class<NSSecureCoding> bah = [NSString class];
id object = [bah new];
Run Code Online (Sandbox Code Playgroud)
返回错误"选择器'new'没有已知的类方法".
为什么第一个实例理解它可以调用+newNSObject上定义的方法但第二个实例不能?
在对矢量类型和ObjC运行时进行一些处理时,我遇到了一个非常令人困惑的问题.
就我所知,clang或GCC都不会为任何SIMD矢量类型提供"正确的"类型编码.
#import <Foundation/Foundation.h>
int main() {
typedef int int4 __attribute__((vector_size(16)));
typedef float float4 __attribute__((vector_size(16)));
NSLog(@"Int4: %s", @encode(int4));
NSLog(@"Float4: %s", @encode(float4));
}
Run Code Online (Sandbox Code Playgroud)
当使用GCC或clang编译和运行时,我得到以下输出:
2014-04-09 06:21:01.102 test[1707:507] Int4: 2014-04-09 06:21:01.103 test[1707:507] Float4:
而不是我期望的,这将是这样的:
2014-04-09 06:21:01.102 test[1707:507] Int4: ![16,16i] 2014-04-09 06:21:01.103 test[1707:507] Float4: ![16,16f]
根据此处的文档:
vectors'!['后跟vector_size(构成向量的字节数),后跟逗号,后跟向量的对齐(以字节为单位),后跟元素的类型,后跟']'
尝试从ObjC方法返回这些类型时会出现问题,而不是像![16,16i]@:以下方法的编码那样获得逻辑:
-(int4) foo;
Run Code Online (Sandbox Code Playgroud)
我只得到了这个字符串@:,这会导致他们两个NSMethodSignature并且NSInvocation基本上扯掉他们的裤子和段错误.
是否有一些编译器选项可以启用以恢复矢量类型的正确编码?或者这里唯一的解决方案是"不从ObjC方法返回向量"?
注意:返回(或传递)指向向量的指针也没有帮助,因为指向矢量的指针的编码很简单^,然后贪婪地匹配列表中的下一个参数,导致我的参数计数关闭再来一次.我想我可以将矢量转换为a void *,但那时真的是一个丑陋的黑客.
我正在尝试使用以下代码来理解NSObject的C结构布局.首先,我使用NSData打印其结构布局,然后直接使用打印类指针[NSObject class].
id obj = [NSObject new];
long nsSize = class_getInstanceSize([NSObject class]);
NSData *nsData = [NSData dataWithBytes:(__bridge const void *)obj length:nsSize];
NSLog(@"obj: %@", nsData);
NSLog(@"NSObject Class: %p", [NSObject class]);
Run Code Online (Sandbox Code Playgroud)
我得到了结果:
2015-10-15 08:11:53.913 ObjC_CMD[11406:1999149] obj: <f1e06573 ffff1d00>
2015-10-15 08:11:53.913 ObjC_CMD[11406:1999149] NSObject Class: 0x7fff7365e0f0
Run Code Online (Sandbox Code Playgroud)
有趣的是类指针的结尾是e0f0,而NSData打印结果显示它的isa为eof1(由于小端,它的顺序相反).我在书中读到isa指针在对象的结构布局中是最顶层的,那么为什么它有1个偏移?
顺便说一句,我也试过其他类型的对象,isa和类指针之间总有1个偏移量.它们不应该是一样的吗?
PS我刚注意到类指针以0x7fff开头,但C struct中的isa似乎是0xffff,这种差异也很有趣.isa字段和类指针之间的确切关系是[NSObject class]什么?
我在Objective-C和Objective-C运行时暴露了swift API.
当我在函数抛出错误之前添加"@objc"时"无法将方法标记为@objc,因为其结果类型无法在Objective-C中表示"
我的代码在这里
@objc public static func logIn(_ userId: String) -> User? { }
Run Code Online (Sandbox Code Playgroud)
用户是可选的结构.怎么解决这个问题.
objective-c optional-parameters objective-c-runtime ios swift
如何在运行时找出类是否覆盖其超类的方法?
例如,我想找出一个类有它自己的执行isEqual:或hash,而不是依赖于一个超类.