语境:
我有一个依赖注入容器 - www.typhoonframework.org
它允许使用接口定义组件以在运行时解析它们 - 使用resolveInstanceMethod和implementntationWithBlock将请求拖拽到DI容器.
用户一直在要求在运行时提供一些参数.例如:
[assembly dangerousEnemyWithWeapon:id<BigGun>]
Run Code Online (Sandbox Code Playgroud)
..敌人是由DI容器中的合作类组装而成,但枪是在运行时提供的...
问题:
是否可以使用resolveInstanceMethod来定义预先知道参数数量的实现?
我想打包这些论点,并将它们转发给另一个响应者.
参数可以按顺序打包或添加到字典中,匹配的选择器部分作为键.
我理解一个类实际上是struct的object/typedef(objc_class*).每个类都有一个"支持"元类,它又有一个指向元类的isa指针NSObject.
并且NSObject基本上有一个isa指针指向自身.
我们可以通过这一行获得元类:
objc_getMetaClass("<CLASS_NAME>");
Run Code Online (Sandbox Code Playgroud)
我希望到目前为止我对meta class的理解并不在这里(请纠正我,如果是的话).
我的问题是:
1.)
我们什么时候需要处理元类?您能否在我们需要的时候引用代码中的示例/场景?
2.)
背景:
我正在思考第三方库以及它们的结构.
通常它们为您提供一个类方法并返回一个类,所有其他方法都是私有/"隐藏".而且大多数时候,虽然它们可以被子类化,但由于我们不知道该init方法,因此子类化是没有用的.
突然间我开始考虑Objective-C类别,从而引导我思考Objective-C元类.
这导致我的问题#2:
是否可以通过使用Objective-C类和/或使用元类来破解这种结构(通过抓住它并在元类中直接插入类方法)?或者甚至查找私有实例方法的名称?
我的意图不是"打破"任何东西,我只是非常好奇这些第三方图书馆是如何"牢不可破"的,如果它们的结构不能通过使用类别和元类来"打破" .
@Leo Natan:
1.)
什么是method_*()?
2.)
对于Objective-C Runtime的热爱:
您能否举一个示例实现 - 调整实例方法,比方说,
(我不确定这种方法是否是一个很好的例子,因为我们可以首先覆盖它)
NSArray的-count实例方法(让它使它返回总是计数100,例如)
3.)
所以理论上所有类(包括所有第三方库)都可以中断(破坏)?换句话说,没有办法创建一个"只调用此类方法 - 或者你不能使用我"的API /库?
非常感谢.
metaclass objective-c objective-c-runtime ios objective-c-category
这里的问题更多的是教育问题.我在一小时前开始想到这一点,同时翻转一个乐高积木(傻,我知道).
根据我的理解,块是在堆栈上创建的对象.
让我们说A是一个对象,这意味着我们可以做到:
[A message];
Run Code Online (Sandbox Code Playgroud)
基于此,如果块是一个对象,我们也可以这样做:
[block message];
Run Code Online (Sandbox Code Playgroud)
我对么?
当运行时看到它时,它会调用:
objc_msgSend(block, @selector(message), nil);
Run Code Online (Sandbox Code Playgroud)
所以我的问题是,我们如何发送一个消息块?
如果这是可能的,我会想象也可以发送一个块参数为块的消息?
并且,如果我们可以通过执行以下操作来调用块:
block();
Run Code Online (Sandbox Code Playgroud)
这是否意味着我们甚至可以将一个块作为message(SEL),因为块具有void (^)(void)类似于方法的签名?
因为如果有可能,那么下面的内容会让我感到惊讶:
objc_msgSend(block, @selector(block), block);
Run Code Online (Sandbox Code Playgroud)
要么:
objc_msgSend(block1, @selector(block2), block3);
Run Code Online (Sandbox Code Playgroud)
我希望我的想象力不会有点疯狂,我的理解不在这里(如果是的话,请纠正我).
macos objective-c objective-c-runtime ios objective-c-blocks
我有一些Swift 3代码来解码iOS Objective-C协议(有一个Swift对应版本)。在总结完Swift 3反射后,我发现反射还不够完善,无法满足我的需要,我偶然发现了objc运行时方法protocol_copyMethodDescriptionList(),该方法返回以下C结构的数组:
struct objc_method_description
SEL name;
char *types;
};
Run Code Online (Sandbox Code Playgroud)
该代码获取协议选择器名称的列表,但不确定在该type字段中返回什么。我对如何正确解码objc_method_description.type值感到困惑。
什么我得到在该type领域是一个神秘的格式,例如,"B48@0:8@16{_NSRange=QQ}24@40"起初我还以为是在我是如何转换C字符串的一个问题,但一些研究之后,我怀疑它实际上是参数的编码,类似Java的JVM如何传递方法签名。但是我仍然没有参考来解码它。
import UIKit
class ViewController: UIViewController, UITextViewDelegate {
@IBOutlet weak var noteView : UITextView!
func decodeProto() {
var methodCount : UInt32 = 1
if let methodList = protocol_copyMethodDescriptionList(UITextViewDelegate.self,
false, true, UnsafeMutablePointer<UInt32>(&methodCount)) {
for i in 0..<Int(methodCount) {
let methodDesc = methodList[i];
let name = methodDesc.name
let types = String(validatingUTF8: methodDesc.types)
print("\(name) \(types)")
}
}
}
override …Run Code Online (Sandbox Code Playgroud) 我已经读过,objective-c程序需要objective-c运行时才能运行.
AFAIK,两个C/C++程序都不需要运行任何运行时环境.因为生成的二进制代码正由底层OS直接执行.
那么这意味着Objective-c程序需要一个冗余层来运行,正确吗?如果是这样,这个层看起来像Java VM和.net运行时还是看起来像Qt运行时(在一些额外的库中)?
EDIT:
一些读出后,我发现,在objc编译器生成在生成的编译代码一些更多的信息,其负责的许多东西,如方法通过(objc_sendMsg(),introspection及其他)
谢谢.
我正在理解"选择器"功能的一部分,如Apple指南中所述.我把那些让我感到困惑的部分加粗了:
在Objective-C中,selector有两个含义.它可以用于简单地引用方法的名称,当它在对象的源代码消息中使用时.但是,它也指的是在编译源代码时替换名称的唯一标识符.编译选择器的类型为SEL.具有相同名称的所有方法都具有相同的选择器.您可以使用选择器来调用对象上的方法 - 这为在Cocoa中实现目标操作设计模式提供了基础.
方法和选择器为了提高效率,完整的ASCII名称不用作编译代码中的方法选择器.相反,编译器将每个方法名称写入表中,然后将名称与表示运行时方法的唯一标识符配对.运行时系统确保每个标识符都是唯一的:没有两个选择器是相同的,并且所有具有相同名称的方法都具有相同的选择器.
任何人都能解释这些位吗?另外,如果不同的类具有相同名称的方法,它们是否也具有相同的选择器?
是否可以在使用运行时创建的类中添加归零弱引用(在ARC意义上,而不是GC中)实例变量?如果是这样的话?
有一个函数调用class_setWeakIvarLayout()似乎与此相关,但遗憾的是文档(对于此函数和非弱对应函数)都非常薄.
weak-references objective-c objective-c-runtime automatic-ref-counting
我注意到了对XCode(4.6)的最新更新,我收到了关于几行的警告JSONKit.m.特别是,设置对象类的行:
dictionary->isa = _JKDictionaryClass;
Run Code Online (Sandbox Code Playgroud)
这些标记为已弃用,并注明首选方法是使用object_setClass():
object_setClass(dictionary, _JKDictionaryClass);
Run Code Online (Sandbox Code Playgroud)
当我问为什么最好只是让警告静音时,回答是:
即使新的Xcode版本抱怨,一切都运行正常,我不想:
1)测试每个项目我使用JSONKit来检查在object_setClass()后是否一切正常
2)松散的cpu周期,这就是我使用JSONKit的原因以NSJSONSerialization为例.我当前的应用程序解析权重为600K-1M的json文件
我们在这里讨论了多少性能影响?
注意:
我更感兴趣
dictionary->isa = _JKDictionaryClass VS object_setClass()
比JSONKitVS NSJSONSerialization.
所以我上课了MyClass.它的名字是其中的一部分char * myclasses[].我想使用objc运行时api来分配它.
1)这是最好的方法吗?我的目标是不分配10或15个ViewControllers,直到它们实际需要使用,并且还没有巨大的switch语句来创建它们.
Class aClass = NSClassFromString ( [NSString stringWithUTF8String:myclasses[1]] );
id myClass = class_createInstance(aClass, 0);
Run Code Online (Sandbox Code Playgroud)
我正在努力理解注册课程..
2)因为我不是在运行时创建一个新类(只是分配),所以我不应该注册它,对吗?
3)班级注册通常如何运作?(随意指点我某处的文件).
当使用Objective-C编译器编译时,Grand Central Dispatch对象的行为类似于Objective-C对象.但这对我来说有点不清楚.
事实上,Objective-C对象是至少有一个字段的结构:指向isa对象类结构的指针(指针).其他字段(如果有)对应于对象的ivars.
那么,可以将GCD对象转换为第一个字段是指向Objective-C类结构的指针的结构吗?由于调度对象参与ARC,什么是编译器的更多信息:它发送retain和release邮件的对象(如objc_msgSend(obj, @selector(retain)),例如)或它生成dispatch_object_retain和dispatch_object_release电话?我的意思是,GCD对象是否以[obj mesg]时尚方式响应ObjC消息?