我公司开发了一个广告SDK,用于调解其他广告网络.在运行时,它通过使用检查其他广告网络是否存在NSClassFromString,并在它们存在时发送这些类消息.
这适用于Objective-C对象,但如何在运行时加载字符串常量?在这种情况下,我想检查只能通过字符串常量(extern NSString* VungleSDKVersion;)获得的SDK版本
在 Swift 3 中,我有一段代码调用 Objective-C 运行时来检查某个类是否存在。
guard let managerClass = NSClassFromString("ASIdentifierManager") as? NSObjectProtocol else {
return nil
}
Run Code Online (Sandbox Code Playgroud)
这将返回AnyClass实例并且它可以转换为NSObjectProtocol- 所以我可以调用像responds和perform使用选择器这样的方法。
在 Swift 4 中,这在运行时仍然有效,但会发出警告:
来自“AnyClass?”的演员表 (又名“可选”)到不相关的类型“NSObjectProtocol”总是失败
奇怪的是它仍然有效,但我担心某个 Swift 版本会杀死代码。
摆脱此警告的正确方法是什么?我应该将对象转换为什么,以便能够对其动态执行选择器?
上下文:我正在开发Pharo/Smalltalk -> Objective-C 桥
场景:在以下 Objective-C ScriptingBridge 片段中:
iTunesApplication *iTunes = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"];
iTunesTrack *currentTrack = iTunes.currentTrack; //[1]
// This low level way works too
//iTunesTrack *currentTrack = [iTunes propertyWithCode: 'pTrk']; //[2]
[iTunes playpause]; //[3]
Run Code Online (Sandbox Code Playgroud)
问题:桥用于class_getInstanceMethod确定对象是否理解消息/选择器,但对于脚本消息,如playpause
问题#1
为什么class_getInstanceMethod像这样的脚本消息会返回 NULL playpause?同样的问题class_copyMethodList?脚本消息有什么特别之处,它们的行为与其他 Obj-C 消息不同(除非它们这样做!)?
问题 #2 [已解决 - 请参阅@Matt 的回答]
根据文档,SB 在“iTunes 应用程序的动态定义子类”中放置了“自动处理 Apple 事件发送的应用程序特定方法”?并且,鉴于class_getInstanceMethod无法找到这种行为(见下文),桥接器测试它的可靠方法是什么(即是否存在这样的方法/消息)?
Objective-C 运行时 API 报告的结果好坏参半。一方面,该类iTunesApplication似乎没有任何方法(或与此相关的属性):
class_copyMethodList([iTunes class]...返回零的方法class_getInstanceMethod桥接器用来查找和执行方法的 失败。另一方面,#playpause …
smalltalk objective-c objective-c-runtime pharo scripting-bridge
正如标题所说.如果我这样做,没有立即出错:
- (void) associateSelector:(SEL)value withPointer:(void*)key
{
objc_SetAssociatedObject(self, key, (id) value, OBJC_ASSOCIATION_ASSIGN);
}
Run Code Online (Sandbox Code Playgroud)
是否有充分理由谨慎使用它?
我在这里搜索了一些关于SO的问题,寻找任何暗示,为什么我看到这种行为,什么都没有.
考虑一个类(实际上是两个表现出相同问题的类),构建在静态库中,包装在框架包中(使用的步骤).它们继承自Foundation框架类集群(NSMutableDictionary和NSMutableArray).
这些类的使用依赖于在静态函数(不是类方法!)用于分配和初始化实例(我猜是一种工厂帮助函数?)之前初始化的一些静态变量.
当iOS应用程序项目链接到该框架时,模拟器和设备之间的Objective-C运行时类加载行为存在差异.
具体来说,在设备(iPhone 4,iOS 4.3.3)上加载应用程序时,这些类不会收到+load消息,并且静态变量不会初始化,因此静态工厂方法失败.在模拟器上,消息被发送,并且所有消息都按预期工作.设备运行时有问题可能是一个问题
我的问题是,我的框架可以配置不同以确保+load邮件发送?或者我遇到了iOS中静态库/框架类加载的错误?
这些类来自JSONKit库(JKArray,JKDictionary).
这个问题的示例项目在这里 - https://github.com/ohhorob/JSONKit-in-framework-demo
编辑:根据@ bbum的建议,我已经验证了在应用程序运行时,JKDictionary和JKArray类实际上已加载并可用.DeviceBrokenGitHub项目的分支使用所使用的验证进行更新.
我向Apple提交了一份bug报告(#9461567).
我最近在这里读到,一个objective-c对象作为结构存储在堆上.该结构包含对象iVars,继承的iVars和isa指针.
我想弄清楚当我向这个对象发送消息时,运行时如何计算出要运行的代码?
我知道每个类都有一个类对象.这也存储在堆上吗?
我认为它的工作方式是运行时从结构中获取isa指针,使用它来调用类对象上的消息.它是否正确?
在某些上下文中(例如,当挂钩到内部进行测试时),能够创建不采用NSCopying(不实现-copyWithZone:)的类的实例的副本将是方便的.怎么能实现这一目标?(注意:在类别中实现协议是不够的,因为并非所有类的实例变量都在其标题中可见.)
我已经试过遍历对象的Ivars和(1)对象类型递归(或保留),和(2)的基本类型,获得在原有的实例化而这正在取得和拷贝伊娃的地址memcpy荷兰国际集团缓冲区从源ivar的地址开始到目的地ivar的地址.
@interface NSObject (ADDLCopy)
- (id)addl_generateCopyDeep:(BOOL)deepCopy;
@end
@implementation NSObject (ADDLCopy)
//modified from http://stackoverflow.com/a/12265664/1052673
- (void *)addl_ivarPointerForName:(const char *)name
{
void *res = NULL;
Ivar ivar = class_getInstanceVariable(self.class, name);
if (ivar) {
res = (void *)self + ivar_getOffset(ivar);
}
return res;
}
- (id)addl_generateCopyDeep:(BOOL)deepCopy;
{
id res = [[self.class alloc] init];
unsigned int count = 0;
Ivar *ivars = class_copyIvarList(self.class, &count);
for (unsigned int i = 0; i < count; i++) { …Run Code Online (Sandbox Code Playgroud) 我有一个与objc_msgSend运行时调用有关的问题,当我有返回一些union的方法时.
我通过libffi调用objc_msgSend函数,如果我有小于16B的union,一切都很好,但是如果union的大小大于16B,我就会遇到seg错误.我尝试使用objc_msgSend_stret函数,并且它通过了,但是我得到了返回union的错误值,并且我不确定哪个函数被称为联合.
有没有人对目标c中的联合有所了解,它们如何在objc运行时中处理?
我想将一个对象的实例转换为该对象类的子类的实例,以便我可以在Objective-C中使用该子类的其他方法和属性.
如何以不需要在复制方法中对该对象类的属性进行硬编码的方式执行此操作?
我在现有的Objective-C项目中编写了一个Swift类.到目前为止,桥接工作非常顺利.我确实有一个方法,我在运行时使用NSClassFromString()生成一个类.当字符串是我的Swift类名时,它返回nil.
class MySwiftClass : NSObject {}
Run Code Online (Sandbox Code Playgroud)
在Objective-C中:
Class myClass = NSClassFromString(@"MySwiftClass");
Run Code Online (Sandbox Code Playgroud)
而myClass每次都是零.我也尝试过:
Class myClass = NSClassFromString(@"MyAppName.MySwiftClass");
Run Code Online (Sandbox Code Playgroud)
仍然没有.
objective-c ×8
ios ×4
cocoa ×2
swift ×2
foundation ×1
iphone ×1
macos ×1
pharo ×1
smalltalk ×1
swift4 ×1