如何从 iOS 传递信息以在启动时做出本机反应?

Posted

技术标签:

【中文标题】如何从 iOS 传递信息以在启动时做出本机反应?【英文标题】:How do I pass information from iOS to react native on startup? 【发布时间】:2018-05-31 03:28:17 【问题描述】:

编辑

为了澄清,我试图在我的应用程序中打开电子邮件中的附件。因此,数据需要在应用程序初始化以及打开时传递给 React。

原创

我对移动应用开发非常陌生,但我正在尝试通过 ios 传递文件名以响应本机。

应用启动时传递props的RN代码

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions

  NSURL *jsCodeLocation;

  jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];

  RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                                      moduleName:@"driveby"
                                               initialProperties:nil
                                                   launchOptions:launchOptions];
  rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];

  self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
  UIViewController *rootViewController = [UIViewController new];
  rootViewController.view = rootView;
  self.window.rootViewController = rootViewController;
  [self.window makeKeyAndVisible];
  return YES;

但是,这个方法似乎只在应用启动时执行。当我们打开文件时,我们需要使用openFile 方法。 openURL 方法正确获取文件的 URL,但我不知道如何将其传递给 RCTRootView。

如果我可以只编辑 rootViewController 中的道具,我会很高兴,但我无法通过阅读 RN 源代码找到一种方法(尽管我是 Objective C 的新手并且不完全理解代码)。我的直觉是我必须用新的道具重新渲染视图。

我不认为这是正确的,但我尝试创建一个新的 rootview 并将其提供给 rootViewController,但我收到了“TypeError: expected dynamic type not null/object/array’, but had typenull”。

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation

  NSURL *jsCodeLocation;

  NSDictionary *urlDict = [NSDictionary dictionaryWithObjectsAndKeys: @"url", url, nil];

  NSLog(@"####################### Open URL");
  NSLog(@"Open URL:\t%@\n" "From source:\t%@\n" "With annotation:%@", url, sourceApplication, annotation);  //url is shown here!
  //NSString *filepath = [url path];
   //...

   jsCodeLocation = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];

   RCTRootView *rootView = [[RCTRootView alloc] initWithBundleURL:jsCodeLocation
                                                       moduleName:@"driveby"
                                                initialProperties:urlDict
                                                    launchOptions:urlDict];
   rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];

   self.window.rootViewController.view = rootView;
   [self.window makeKeyAndVisible];

   return YES;

谁能指出我正确的方向?提前致谢!

【问题讨论】:

我认为你过于复杂了。如果你使用 Native Modules,你可以从你的 JS 代码中调用一个 ObjC 函数。在这种情况下,您不需要访问 RCTRootView 或 AppDelegate,并且可以减少需要编写的 ObjC 代码量 @dentemm 感谢您的回复。我在下面的回复中添加了评论,并附有后续问题 【参考方案1】:

在 React Native 中,您在 javascript 代码和本机代码之间传递信息的机制是通过本机模块。

您可以创建一个桥接模块并从 JS 端调用该特定方法,以向您的视图提供您指定的 URL。

另一方面,您还可以使用事件发射器向 JS 端的事件处理程序发出 URL,然后在收到事件时打开该文件。

看看here,这应该可以帮助您找到所需的东西。

【讨论】:

好的,我已经设置了本地模块来工作。令人困惑的是,该文件被应用程序打开,而我唯一能找到对其位置的引用的地方是 AppDelegate 中的 openUrl 方法。您是否建议我将文件 URL 存储在应用程序单例中的某个位置并通过本机模块检索它? 为什么只有 AppDelegate 可以访问该文件?就我个人而言,我不会通过应用单例访问它,而是尝试使其更可重用 @dentemm 该文件是从电子邮件附件或网站打开的。 ios documentation 表示它应该包含在application:didFinishLaunchingWithOptions 的启动选项中,但它不存在。我见过的唯一获取 URL 的地方是在 openUrl 回调中。 @dentemm 特别是我一直在处理这些说明:***.com/questions/44285506/… 好的,我还没有这样做,但您也可以从 AppDelegate 创建一个本机模块。让你的 AppDelegate 符合 RCTBridgeModule 协议,我想你应该可以通过原生模块访问文件。

以上是关于如何从 iOS 传递信息以在启动时做出本机反应?的主要内容,如果未能解决你的问题,请参考以下文章

反应本机推送通知以在收到通知时运行功能

如何使 iOS UIPicker 与多个列和标题做出本机反应?

如何从 Java Activity 传递数据以响应本机?

您如何使用面部 ID 登录以使用 Firebase 做出本机反应?

如何将值传递给正在加载反应本机应用程序的 Web 视图

如何在不点击通知的情况下从通知中获取数据(firebase 云消息传递和本机反应)