react-native解决xcode16下ios18的分享到微信和微信分享朋友圈问题

一、原因

ios18下不允许使用openUrl,微信ios sdk需要更新到2.0.4解决此问题。
"jshare-react-native": "1.4.2""react-native-wechat-lib": "1.1.26",都还没有解决分享到微信的问题。

二、解决方法

在ios的runtime运行时,将所有的openUrl替换成open,则解决react-native-wechat-lib的分享问题。
注意没有解决jshare-react-native的分享问题(因为jshare他也写了一个runtime替换openUrl,我得先删除这个)。

1、在ios下编辑AppDelegate.m文件
添加以下头文件,注意靠前面一些引入,否则会报错

// 导入 Runtime 头文件  
#import <objc/runtime.h>

2、在下面方法的最前面

  • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
// ⚠️ 首先进行方法交换!放在最前面!  
[AppDelegate hookOldOpenUrl:AppDelegate.class];

在@end 之前添加

// 你提供的替换方法  
- (BOOL)g_openURL:(NSURL*)url{  
    // 使用新的 API,并添加 completionHandler  
    [UIApplication.sharedApplication openURL:url options:@{} completionHandler:nil];  
    return YES;  
}  
  
// 你提供的交换方法  
+ (void)hookOldOpenUrl:(Class)targetCls{  
    Class cls = [UIApplication class];  
    if (cls) {  
        Method originalMethod = class_getInstanceMethod(cls, @selector(openURL:));  
        Method swizzledMethod = class_getInstanceMethod(targetCls, @selector(g_openURL:));  
        if (!originalMethod || !swizzledMethod) {  
            return;  
        }  
        IMP originalIMP = method_getImplementation(originalMethod);  
        IMP swizzledIMP = method_getImplementation(swizzledMethod);  
        const char *originalType = method_getTypeEncoding(originalMethod);  
        const char *swizzledType = method_getTypeEncoding(swizzledMethod);  
          
        // 核心交换操作  
        class_replaceMethod(cls, @selector(openURL:), swizzledIMP, swizzledType);  
        class_replaceMethod(cls, @selector(g_openURL:), originalIMP, originalType);  
    }  
}  
  
// ... 其他可能存在的 React Native 相关方法(如 deep linking 处理)保持不变  
// 这些方法会在你交换后的 g_openURL: 中被调用  
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {  
  return [RCTLinkingManager application:application openURL:url options:options];  
}

注意,openURL和JShare重复了
删除掉

// work in iOS(9_0,++)  
// - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {  
//   [JSHAREService handleOpenUrl:url];  
//   return YES;  
// }

三、怕你们还搞不清楚,我直接全贴上来

#import "AppDelegate.h"

#import <RCTJPushModule.h>
#import <RCTJShareModule.h>

#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>
#import <React/RCTLinkingManager.h>

// 导入 Runtime 头文件
#import <objc/runtime.h>

#ifdef NSFoundationVersionNumber_iOS_9_x_Max
#import <UserNotifications/UserNotifications.h>
#endif

#ifdef FB_SONARKIT_ENABLED
#import <FlipperKit/FlipperClient.h>
#import <FlipperKitLayoutPlugin/FlipperKitLayoutPlugin.h>
#import <FlipperKitUserDefaultsPlugin/FKUserDefaultsPlugin.h>
#import <FlipperKitNetworkPlugin/FlipperKitNetworkPlugin.h>
#import <SKIOSNetworkPlugin/SKIOSNetworkAdapter.h>
#import <FlipperKitReactPlugin/FlipperKitReactPlugin.h>



static void InitializeFlipper(UIApplication *application) {
  FlipperClient *client = [FlipperClient sharedClient];
  SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
  [client addPlugin:[[FlipperKitLayoutPlugin alloc] initWithRootNode:application withDescriptorMapper:layoutDescriptorMapper]];
  [client addPlugin:[[FKUserDefaultsPlugin alloc] initWithSuiteName:nil]];
  [client addPlugin:[FlipperKitReactPlugin new]];
  [client addPlugin:[[FlipperKitNetworkPlugin alloc] initWithNetworkAdapter:[SKIOSNetworkAdapter new]]];
  [client start];
}
#endif

// #import "Orientation.h"

@implementation AppDelegate

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

  // ⚠️ 首先进行方法交换!放在最前面!
  [AppDelegate hookOldOpenUrl:AppDelegate.class];

#ifdef FB_SONARKIT_ENABLED
  InitializeFlipper(application);
#endif

  // *** 极光推送start ***
  // APNS
  JPUSHRegisterEntity * entity = [[JPUSHRegisterEntity alloc] init];
  if (@available(iOS 12.0, *)) {
    entity.types = JPAuthorizationOptionAlert|JPAuthorizationOptionBadge|JPAuthorizationOptionSound|JPAuthorizationOptionProvidesAppNotificationSettings;
  }
  [JPUSHService registerForRemoteNotificationConfig:entity delegate:self];
  [launchOptions objectForKey: UIApplicationLaunchOptionsRemoteNotificationKey];
  // 自定义消息
  NSNotificationCenter *defaultCenter = [NSNotificationCenter defaultCenter];
  [defaultCenter addObserver:self selector:@selector(networkDidReceiveMessage:) name:kJPFNetworkDidReceiveMessageNotification object:nil];
  // 地理围栏
  [JPUSHService registerLbsGeofenceDelegate:self withLaunchOptions:launchOptions];
   // *** 极光推送end ***


  RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
  RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
                                                   moduleName:@"xxxxxxx"
                                            initialProperties:nil];

  if (@available(iOS 13.0, *)) {
      rootView.backgroundColor = [UIColor systemBackgroundColor];
  } else {
      rootView.backgroundColor = [UIColor whiteColor];
  }

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

  // 启动图片延时: 1秒
  [NSThread sleepForTimeInterval:1];

  return YES;
}


//************************************************JPush start************************************************

//注册 APNS 成功并上报 DeviceToken
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken {
  [JPUSHService registerDeviceToken:deviceToken];
}

//iOS 7 APNS
- (void)application:(UIApplication *)application didReceiveRemoteNotification:  (NSDictionary *)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult))completionHandler {
  // iOS 10 以下 Required
  NSLog(@"iOS 7 APNS");
  [JPUSHService handleRemoteNotification:userInfo];
  [[NSNotificationCenter defaultCenter] postNotificationName:J_APNS_NOTIFICATION_ARRIVED_EVENT object:userInfo];
  completionHandler(UIBackgroundFetchResultNewData);
}

//iOS 10 前台收到消息
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center  willPresentNotification:(UNNotification *)notification withCompletionHandler:(void (^)(NSInteger))completionHandler {
  NSDictionary * userInfo = notification.request.content.userInfo;
  if([notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
    // Apns
    NSLog(@"iOS 10 APNS 前台收到消息");
    [JPUSHService handleRemoteNotification:userInfo];
    [[NSNotificationCenter defaultCenter] postNotificationName:J_APNS_NOTIFICATION_ARRIVED_EVENT object:userInfo];
  }
  else {
    // 本地通知 todo
    NSLog(@"iOS 10 本地通知 前台收到消息");
    [[NSNotificationCenter defaultCenter] postNotificationName:J_LOCAL_NOTIFICATION_ARRIVED_EVENT object:userInfo];
  }
  //需要执行这个方法,选择是否提醒用户,有 Badge、Sound、Alert 三种类型可以选择设置
  completionHandler(UNNotificationPresentationOptionAlert);
}

//iOS 10 消息事件回调
- (void)jpushNotificationCenter:(UNUserNotificationCenter *)center didReceiveNotificationResponse:(UNNotificationResponse *)response withCompletionHandler: (void (^)(void))completionHandler {
  NSDictionary * userInfo = response.notification.request.content.userInfo;
  if([response.notification.request.trigger isKindOfClass:[UNPushNotificationTrigger class]]) {
    // Apns
    NSLog(@"iOS 10 APNS 消息事件回调");
    [JPUSHService handleRemoteNotification:userInfo];
    // 保障应用被杀死状态下,用户点击推送消息,打开app后可以收到点击通知事件
    [[RCTJPushEventQueue sharedInstance]._notificationQueue insertObject:userInfo atIndex:0];
    [[NSNotificationCenter defaultCenter] postNotificationName:J_APNS_NOTIFICATION_OPENED_EVENT object:userInfo];
  }
  else {
    // 本地通知
    NSLog(@"iOS 10 本地通知 消息事件回调");
    // 保障应用被杀死状态下,用户点击推送消息,打开app后可以收到点击通知事件
    [[RCTJPushEventQueue sharedInstance]._localNotificationQueue insertObject:userInfo atIndex:0];
    [[NSNotificationCenter defaultCenter] postNotificationName:J_LOCAL_NOTIFICATION_OPENED_EVENT object:userInfo];
  }
  // 系统要求执行这个方法
  completionHandler();
}

//自定义消息
- (void)networkDidReceiveMessage:(NSNotification *)notification {
  NSDictionary * userInfo = [notification userInfo];
  [[NSNotificationCenter defaultCenter] postNotificationName:J_CUSTOM_NOTIFICATION_EVENT object:userInfo];
}

//************************************************JPush end************************************************



- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
    return  [WXApi handleOpenURL:url delegate:self];
}

- (BOOL)application:(UIApplication *)application
  continueUserActivity:(NSUserActivity *)userActivity
  restorationHandler:(void(^)(NSArray<id<UIUserActivityRestoring>> * __nullable
  restorableObjects))restorationHandler {
  // 触发回调方法
  [RCTLinkingManager application:application continueUserActivity:userActivity restorationHandler:restorationHandler];
  return [WXApi handleOpenUniversalLink:userActivity
  delegate:self];
}

// - (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
//             options:(NSDictionary<NSString*, id> *)options
// {
//   // Triggers a callback event.
//   // 触发回调事件
//   [RCTLinkingManager application:application openURL:url options:options];
//   return [WXApi handleOpenURL:url delegate:self];
// }

// work in iOS(9_0,++)
// - (BOOL)application:(UIApplication *)app openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
//   [JSHAREService handleOpenUrl:url];
//   return YES;
// }

- (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
{
#if DEBUG
  return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
#else
  return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
#endif
}

//- (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(UIWindow *)window {
//  return [Orientation getOrientation];
// }



// 你提供的替换方法
- (BOOL)g_openURL:(NSURL*)url{
    // 使用新的 API,并添加 completionHandler
    [UIApplication.sharedApplication openURL:url options:@{} completionHandler:nil];
    return YES;
}

// 你提供的交换方法
+ (void)hookOldOpenUrl:(Class)targetCls{
    Class cls = [UIApplication class];
    if (cls) {
        Method originalMethod = class_getInstanceMethod(cls, @selector(openURL:));
        Method swizzledMethod = class_getInstanceMethod(targetCls, @selector(g_openURL:));
        if (!originalMethod || !swizzledMethod) {
            return;
        }
        IMP originalIMP = method_getImplementation(originalMethod);
        IMP swizzledIMP = method_getImplementation(swizzledMethod);
        const char *originalType = method_getTypeEncoding(originalMethod);
        const char *swizzledType = method_getTypeEncoding(swizzledMethod);
        
        // 核心交换操作
        class_replaceMethod(cls, @selector(openURL:), swizzledIMP, swizzledType);
        class_replaceMethod(cls, @selector(g_openURL:), originalIMP, originalType);
    }
}

// ... 其他可能存在的 React Native 相关方法(如 deep linking 处理)保持不变
// 这些方法会在你交换后的 g_openURL: 中被调用
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url options:(NSDictionary<UIApplicationOpenURLOptionsKey,id> *)options {
  return [RCTLinkingManager application:application openURL:url options:options];
}


@end


©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容