首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >本机iOS类中的j2objc反射支持

本机iOS类中的j2objc反射支持
EN

Stack Overflow用户
提问于 2021-10-20 08:01:39
回答 1查看 36关注 0票数 0

我刚刚将我的j2objc工具从1.0.2更新到2.8。据我所知,从1.1版本开始,反射发生了一些变化。现在代码不再起作用了。

我们有IApplicationSupport.java接口。如下所示:

代码语言:javascript
复制
public interface IApplicationSupport
{
    void openSupport();
}

使用j2objc成功地将此代码转换为Objective-С

然后我们有与平台相关的类AndroidApplicationSupportIosApplicationSupport,它们不会被翻译。Android部分没问题,但iOS有一些问题。

稍后在代码中的某个地方,我需要调用[IOSClass classForIosName:@"IosApplicationSupport"]。这就是问题所在。每次com.google.j2objc.ReflectionStrippedError: IosApplicationSupport: Reflection is unavailable. Fix this by avoiding reflection or building without --strip-reflection.时我都会得到下一个异常,当然我在翻译过程中没有使用--strip-reflection标志(但我相信问题不在这里)。在我的例子中,避免反射似乎非常困难,因为使用了太多带有反射的类。

据我所知,翻译后的类有相当大的__metadata方法。有没有办法模拟本地类的元数据来启用反射支持?如果我必须添加元数据,是否有关于如何生成元数据的规则?我们的项目是沉重的依赖于它。

谢谢你的帮助!

EN

回答 1

Stack Overflow用户

发布于 2021-10-20 15:40:22

当然,可以很容易地添加__metadata method。最简单的方法是创建一个简单的存根文件,它定义了包、类和方法,然后转换它一次,并将生成的方法复制到您的本机类中。下面是IosApplicationSupport.java的一个示例存根(我不得不猜测IApplicationSupport在哪个包中):

代码语言:javascript
复制
import foo.bar.IApplicationSupport;

public class IosApplicationSupport implements IApplicationSupport {
  public void openSupport() {
  }
}

在这个类上运行j2objc之后,它的元数据是:

代码语言:javascript
复制
+ (const J2ObjcClassInfo *)__metadata {
  static J2ObjcMethodInfo methods[] = {
    { NULL, NULL, 0x1, -1, -1, -1, -1, -1, -1 },
    { NULL, "V", 0x1, -1, -1, -1, -1, -1, -1 },
  };
  #pragma clang diagnostic push
  #pragma clang diagnostic ignored "-Wobjc-multiple-method-names"
  #pragma clang diagnostic ignored "-Wundeclared-selector"
  methods[0].selector = @selector(init);
  methods[1].selector = @selector(openSupport);
  #pragma clang diagnostic pop
  static const J2ObjcClassInfo _IosApplicationSupport = { "IosApplicationSupport", NULL, NULL, methods, NULL, 7, 0x1, 2, 0, -1, -1, -1, -1, -1 };
  return &_IosApplicationSupport;
}

(这看起来很大,但在64位处理器(NSLog(@"sizeof metadata: %ld", sizeof(_IosApplicationSupport) + sizeof(methods));)上只有128字节。)

但是,如果您只是加载一个类并创建它的一个默认实例,那么元数据就不是必需的,因为Objective-C运行时直接支持它。由于您没有说明IApplicationSupport在哪个包中,因此使用foo.bar包可以在没有元数据的情况下成功执行此代码:

代码语言:javascript
复制
  IOSClass *appSupportClass = [IOSClass classForIosName:@"IosApplicationSupport"];
  id<FooBarIApplicationSupport> appSupport = [appSupportClass newInstance];
  [appSupport openSupport];

由于类加载和实例创建工作正常,所以听起来像是IosApplicationSupport使用了需要元数据的java.lang.reflect应用程序接口。然而,从1.0.2开始,有一种比手工编写IosApplicationSupport更简单的方法:使用OCNI。OCNI允许您将Objective-C直接嵌入到Java本地方法中。我们在JRE模拟库中经常使用它,比如here, where native iOS MD5 signing is done in a Java class。这避免了定义和维护元数据结构,只需用Java编写代码并在必要的地方插入Objective-C即可。

因此,我的建议是用Java语言重写IosApplicationSupport,并在需要本机代码的地方用OCNI定义本机Java方法。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/69642359

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档