Unity和iOS 原生专题二 Unity和iOS原生交互相互传值的两个方案

一 、方案一 通过指针传值和使用 MonoPInvokeCallback 从C#层向C层注册回调函数

1.1 iOS调用Unity函数Unity 给iOS传值

第一步C#端 定义 C#调用 ios 原生函数标识 固定写法

 /// <summary>/// 定义 C#调用 ios 原生函数标识 固定写法/// </summary>private const string DLLName = "__Internal";[UsedImplicitly, DllImport(DLLName)]private static extern void MobileNumberAuthiOS_Initialize(string secret, AliMobileAuthLogCallback logCallback,NumberAuthInitCallback initCallback);

第二步C#端 定义c# 传递到原生的的委托代理

 /// <summary>/// 定义c# 传递到原生的的委托代理,接收ios原生回传的值/// </summary>private delegate void AliMobileAuthLogCallback(string log);private delegate void NumberAuthInitCallback(int success, string msg);

第三步C# 端 定义C#端的代理函数,接收ios 传递过来的值

 /// <summary>/// 定义C#端的代理函数,用于接收ios 传递过来的值/// </summary>/// <param name="log"></param>[MonoPInvokeCallback(typeof(AliMobileAuthLogCallback))]private static void HandleOnAliMobileAuthLogCallback(string log){InfoLog(log);}[MonoPInvokeCallback(typeof(NumberAuthInitCallback))]private static void HandleOnSmsAuthInitCallback(int success, string msg){InfoLog($"开始初始化回调,success:{success} msg: {msg}");_initializeCallback?.Invoke(success, msg);}

第四步 C#端 调用上面定的调用ios 的函数

  /// C# 调用上面定的调用ios 的函数 ,secret 参数,HandleOnAliMobileAuthLogCallback,HandleOnSmsAuthInitCallback 要传递过去的代理函数MobileNumberAuthiOS_Initialize(secret, HandleOnAliMobileAuthLogCallback, HandleOnSmsAuthInitCallback);

第五步 ios 端 ios 定义c#调用的ios 方法  固定写法

///ios 定义c#调用的ios 方法  固定写法
#if defined(__cplusplus)
extern "C" {
#endifvoid MobileNumberAuthiOS_Initialize(const char* secret ,void(*aliMobileAuthLogCallback)(const char* log), void(*initSDKCallback)(int, const char * )){///将c#的代理指针赋值给ios的块指针AliMobileAuthLogCallback = aliMobileAuthLogCallback;InitSDKCallback = initSDKCallback;///调用ios的方法[[AliMobileNumberAuth sharedManager] Initialize:secret];}#if defined(__cplusplus)
}
#endif

第六步ios 端  定义接收c#要传递过来的代理指针


///定义接收c#要传递过来的代理指针
static void (*AliMobileAuthLogCallback)(const char* log);
static void(*InitSDKCallback)(int,const char *);

第七步ios 端 在ios函数中 回调c#的代码函数,将ios这边的值传递到c#

-(void)Initialize:(const char*)key {///接收c#传递过来的值NSString * dataString  = [NSString stringWithFormat:@"%s",key];///ios 回调c#的代码函数,将ios这边的值传递到c#if (InitSDKCallback) {NSString * dataString = @"回传值";int code = 1;InitSDKCallback(code,[dataString UTF8String]);}}

以上就是unity和ios 原生交互 通过指针传值和代理(delegate)回传值 定义和接收值的完整实现过程

第八步 C# 和ios 完整代码部分

8.1 ios 代码
//ios 代码
#import "AliMobileNumberAuth.h"///定义接收c#要传递过来的代理指针
static void (*AliMobileAuthLogCallback)(const char* log);
static void(*InitSDKCallback)(int,const char *);static bool EnableLog;
@interface  AliMobileNumberAuth()
@end@implementation AliMobileNumberAuth///ios 定义c#调用的ios 方法  固定写法
#if defined(__cplusplus)
extern "C" {
#endifvoid MobileNumberAuthiOS_Initialize(const char* secret ,void(*aliMobileAuthLogCallback)(const char* log), void(*initSDKCallback)(int, const char * )){///将c#的代理指针赋值给ios的块指针AliMobileAuthLogCallback = aliMobileAuthLogCallback;InitSDKCallback = initSDKCallback;///调用ios的方法[[AliMobileNumberAuth sharedManager] Initialize:secret];}#if defined(__cplusplus)
}
#endif-(void)Initialize:(const char*)key {///接收c#传递过来的值NSString * dataString  = [NSString stringWithFormat:@"%s",key];///ios 回调c#的代码函数,将ios这边的值传递到c#if (InitSDKCallback) {NSString * dataString = @"回传值";int code = 1;InitSDKCallback(code,[dataString UTF8String]);}}
#pragma mark - LifeCycle
+(instancetype)sharedManager {static dispatch_once_t onceToken;static AliMobileNumberAuth *instance;dispatch_once(&onceToken, ^{instance = [[AliMobileNumberAuth alloc] init];});return instance;
}-(void)MobileNumberAuthiOS_CheckEnvironment{[self LogMessage:@"开始检测当前环境是否支持一键登录"];__block BOOL support = YES;[[TXCommonHandler sharedInstance] checkEnvAvailableWithAuthType:PNSAuthTypeLoginToken complete:^(NSDictionary * _Nullable resultDic) {NSString *dataStirng = [[resultDic objectForKey:@"msg"] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];NSString * code = [resultDic objectForKey:@"resultCode"];if (CheckEnvironmentCallback) {support = [PNSCodeSuccess isEqualToString:code];CheckEnvironmentCallback(support ? 1 : [code intValue],[dataStirng UTF8String]);CheckEnvironmentCallback = nil;}[self LogMessage:[NSString stringWithFormat:@"检测一键登录resultmsg:%@  resultCode:%@,是否支持一键登录:%d",[resultDic objectForKey:@"resultCode"],dataStirng,support]];}];
}
-(void)MobileNumberAuthiOS_GetToken{//3. 开始一键登录流程//3.1 调用加速授权页弹起接口,提前获取必要参数,为后面弹起授权页加速
UIViewController *rootViewController = [self topViewController];self.rootViewController = rootViewController;
__weak typeof(self) weakSelf = self;
TXCustomModel *model = [DoraemonModelCreate createAlert];[[TXCommonHandler sharedInstance] accelerateLoginPageWithTimeout:3.0 complete:^(NSDictionary * _Nonnull resultDic) {NSString *code = [resultDic objectForKey:@"resultCode"];NSString *dataStirng = [[resultDic objectForKey:@"msg"] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];[self LogMessage:[NSString stringWithFormat:@"dataStirng%@",dataStirng]];if ([PNSCodeSuccess isEqualToString:[resultDic objectForKey:@"resultCode"]] == NO) {if (NumberAuthGetTokenCallback) {NumberAuthGetTokenCallback([code UTF8String] ,[dataStirng UTF8String]);[rootViewController dismissViewControllerAnimated:YES completion:nil];NumberAuthGetTokenCallback = nil;}[self LogMessage:[NSString stringWithFormat:@"加速授权页弹起失败%@",dataStirng]];return ;}//3.2 调用获取登录Token接口,可以立马弹起授权页,model的创建需要放在主线程[[TXCommonHandler sharedInstance] getLoginTokenWithTimeout:1.0 controller:rootViewController model:model complete:^(NSDictionary * _Nonnull resultDic) {NSString *code = [resultDic objectForKey:@"resultCode"];NSString *dataStirng = [[resultDic objectForKey:@"msg"] stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];if ([PNSCodeLoginControllerPresentSuccess isEqualToString:code]) {[self LogMessage:@"弹起授权页成功"];} else if ([PNSCodeLoginControllerClickCancel isEqualToString:code]) {[self LogMessage:@"点击了授权页的返回"];if (NumberAuthGetTokenCallback) {NumberAuthGetTokenCallback([code UTF8String] ,[dataStirng UTF8String]);NumberAuthGetTokenCallback = nil;}[rootViewController dismissViewControllerAnimated:YES completion:nil];} else if ([PNSCodeLoginControllerClickChangeBtn isEqualToString:code]) {[self LogMessage:@"点击切换其他登录方式按钮"];} else if ([PNSCodeLoginControllerClickLoginBtn isEqualToString:code]) {if ([[resultDic objectForKey:@"isChecked"] boolValue] == YES) {[self LogMessage:@"点击了登录按钮,check box选中,SDK内部接着会去获取登陆Token"];} else {[[ToastUtil toast] showToast:@"请先同意协议"];[self LogMessage:@"点击了登录按钮,check box未选中,SDK内部不会去获取登陆Token"];}} else if ([PNSCodeLoginControllerClickCheckBoxBtn isEqualToString:code]) {[self LogMessage:@"点击check box"];} else if ([PNSCodeLoginControllerClickProtocol isEqualToString:code]) {[self LogMessage:@"点击了协议富文本"];} else if ([PNSCodeSuccess isEqualToString:code]) {//点击登录按钮获取登录Token成功回调NSString *token = [resultDic objectForKey:@"token"];if (NumberAuthGetTokenCallback) {NumberAuthGetTokenCallback([code UTF8String],[token UTF8String]);[rootViewController dismissViewControllerAnimated:YES completion:nil];NumberAuthGetTokenCallback = nil;}[[TXCommonHandler sharedInstance] hideLoginLoading];[self LogMessage:[NSString stringWithFormat:@"获取登录Token成功"]];} else{if (NumberAuthGetTokenCallback) {NumberAuthGetTokenCallback([code UTF8String] ,[dataStirng UTF8String]);NumberAuthGetTokenCallback = nil;}[[TXCommonHandler sharedInstance] hideLoginLoading];[self LogMessage:[NSString stringWithFormat:@"获取登录Token失败 "]];}[self LogMessage:[NSString stringWithFormat:@"授权框框操作日志msg:%@ code %@",dataStirng,code]];}];}];}
-(void)MobileNumberAuthiOS_Dispose{[self.rootViewController dismissViewControllerAnimated:YES completion:nil];
}
#pragma mark - LifeCycle
+(instancetype)sharedManager {static dispatch_once_t onceToken;static AliMobileNumberAuth *instance;dispatch_once(&onceToken, ^{instance = [[AliMobileNumberAuth alloc] init];});return instance;
}
8.2 c# 代码

using System;
using System.Runtime.InteropServices;
using AOT;
using Bao.Debug;
using JetBrains.Annotations;namespace Bao.Account.SDK
{public class MobileNumberAuthiOS {#region 初始化🇭相关public static MobileNumberAuthiOS _instance;public static  Action<int, string> _initializeCallback;private Action<bool, string> _heckEnvironmentCallback;private Action<bool, string> _getTokenCallback;/// <summary>/// 定义c# 传递到原生的的委托代理,接收ios原生回传的值/// </summary>private delegate void AliMobileAuthLogCallback(string log);private delegate void NumberAuthInitCallback(int success, string msg);#endregion#region Native Methods
#if UNITY_IOS /// <summary>/// 定义 C#调用 ios 原生函数标识 固定写法/// </summary>private const string DLLName = "__Internal";[UsedImplicitly, DllImport(DLLName)]private static extern void MobileNumberAuthiOS_Initialize(string secret, AliMobileAuthLogCallback logCallback,NumberAuthInitCallback initCallback);
#endif#endregionprivate static void InfoLog(string msg){LogFile.get.Log($"阿里一键登录, iOS, {msg}");}public void Initialize(string secret, Action<int, string> callback, bool enableLog){/// C# 调用上面定的调用ios 的函数 ,secret 参数,HandleOnAliMobileAuthLogCallback,HandleOnSmsAuthInitCallback 要传递过去的代理函数MobileNumberAuthiOS_Initialize(secret, HandleOnAliMobileAuthLogCallback, HandleOnSmsAuthInitCallback);}/// <summary>/// 定义C#端的代理函数,用于接收ios 传递过来的值/// </summary>/// <param name="log"></param>[MonoPInvokeCallback(typeof(AliMobileAuthLogCallback))]private static void HandleOnAliMobileAuthLogCallback(string log){InfoLog(log);}[MonoPInvokeCallback(typeof(NumberAuthInitCallback))]private static void HandleOnSmsAuthInitCallback(int success, string msg){InfoLog($"开始初始化回调,success:{success} msg: {msg}");_initializeCallback?.Invoke(success, msg);}}
}private delegate void OnViewClosed(int result, string msg);   // [MonoPInvokeCallback(OnViewClosed)]
static void CalledByNativeC(int result, string msg)
{// some logic here
}// ... #if UNITY_IPHONE || UNITY_IOS
[DllImport("__Internal")]
private static extern void SetOnViewClosed(OnViewClosed);
#endif// ...
SetOnViewClosed(CalledByNativeC);    // 把C#中的回调函数传给C

二 、方案二 UnitySendMessage

2.1 使用 UnitySendMessage 时具有以下限制:

1.通过原生代码,只能调用与以下签名对应的脚本方法:void MethodName(string message);。

2.对 UnitySendMessage 的调用是异步的,并有一帧延迟

3.如果两个或多个游戏对象具有相同的名称,则在使用 UnitySendMessage 时可能导致冲突

4.无论使用什么方式调用UnitySendMessage方法,方法最终会使用主线程运行。

2.2 UnitySendMessage 使用方法

UnitySendMessage("[gameobject_name]", "[method_name]", "[string_param]");
这个方法要求场景中有个特定名称的GameObject对象,同时该对象上应该挂载某个MonoBehaviour脚本,在该脚本中包含有一个特定的方法(如下所示),当然如果该对象上挂载了多个脚本,并且这些脚本中都有该方法,那么这些方法都会被调用的!

2.3 iOS 向C# 发送消息

 MessageReceiver (MessageReceiver脚本绑定到MessageReceiver该游戏对象上)

UnitySendMessage("MessageReceiver", "OnMessageReceived", "Hello from iOS!");
using UnityEngine;public class MessageReceiver : MonoBehaviour
{public void OnMessageReceived(string message){Debug.Log("Received message from iOS: " + message);}
}

2.4 Unity调用iOS原生方法

using UnityEngine;
using System.Runtime.InteropServices;public class NativeMethodCaller : MonoBehaviour
{[DllImport("__Internal")]private static extern void CallNativeMethod(string message);public void CalliOSMethod(string message){CallNativeMethod(message);}
}

2.5 ios 实现方法

extern "C" {int CallNativeMethod(const char *msg) {}
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/3836.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【SpringCloud】CircuitBreaker断路器之Resilience4J快速入门

【SpringCloud】CircuitBreaker断路器之Resilience4J快速入门 文章目录 【SpringCloud】CircuitBreaker断路器之Resilience4J快速入门1. 概述2. 服务熔断服务降级(CircuitBreaker)2.1 案例说明2.1.1 基于计数的滑动窗口2.1.2 测试2.2.1 基于时间的滑动窗口2.2.2 测试 3. 隔离(B…

前端单元测试的艺术:专业化策略与Vue项目高效实践指南

单元测试是软件开发中的基石&#xff0c;尤其对于前端领域&#xff0c;它为保证代码质量、提升开发效率、强化项目稳定性提供了不可或缺的支持。本文将深入剖析单元测试的核心理念&#xff0c;揭示其在前端开发中的独特价值&#xff0c;并提炼出一套专业且高效的实践策略&#…

git 基础知识(全能版)

文章目录 一 、git 有三个分区二、git 基本操作1、克隆—git clone2、拉取—git fetch / git pull3、查看—git status / git diff3.1 多人开发代码暂存技巧 本地代码4、提交—git add / git commit / git push5、日志—git log / git reflog6、删除—git rm ‘name’7、撤销恢…

阿里云服务器(Ubuntu22)上的MySQL8更改为大小写不敏感

因为windows上默认的mysql8.0是大小写不敏感的&#xff0c;部署到服务器上之后发现ubuntu默认的是大小写敏感&#xff0c;所以为了不更改代码&#xff0c;需要将mysql数据库设置为大小写不敏感的。 &#xff01;&#xff01;&#xff01;重要一定要做好数据库的备份&#xff0…

MyBatis特殊SQL的执行

文章目录 一、模糊查询二、批量删除三、动态设置表名四、添加功能获取自增的主键 一、模糊查询 /*** 通过用户名模糊查询用户信息* param mohu* return*/List<User> getUserByLike(Param("mohu") String mohu);<!--List<User> getUserByLike(Param(&q…

微服务与单体应用之间的调用问题

前言 本文转自 www.microblog.store,且已获得授权 一、问题背景 microblog.store微博客使用了微服务架构,并且docker容器化部署; 另有一个独立的单体应用,功能是: 作为ip地址解析中心; 微服务集群以及该单体应用都部署到同一台服务器上面,有需要的时候微服务集群里面某个微服务…

使用JavaScript日历小部件和DHTMLX Gantt的应用场景(一)

DHTMLX Suite UI 组件库允许您更快地构建跨平台、跨浏览器 Web 和移动应用程序。它包括一组丰富的即用式 HTML5 组件&#xff0c;这些组件可以轻松组合到单个应用程序界面中。 DHTMLX Gantt是用于跨浏览器和跨平台应用程序的功能齐全的Gantt图表&#xff0c;可满足项目管理应用…

「51媒体」城市推介会,地方旅游推荐,怎么做好媒体宣传

传媒如春雨&#xff0c;润物细无声&#xff0c;大家好&#xff0c;我是51媒体网胡老师。 城市推介会和地方旅游推荐是城市形象宣传的重要组成部分&#xff0c;通过有效的媒体宣传可以提升城市的知名度和吸引力。&#xff1a; 一&#xff0c;活动内容层面&#xff1a; 突出亮点…

pyqt设置标签显示图片并设置大小

pyqt设置标签显示图片并设置大小 标签显示图片效果代码 标签显示图片 使用 QPixmap 加载图片进行图片大小设置把图片对象设置到标签上 效果 代码 from PyQt5.QtWidgets import QApplication, QLabel, QVBoxLayout, QWidget from PyQt5.QtGui import QPixmap import sys from…

某赛通电子文档安全管理系统 多处 SQL注入漏洞复现

0x01 产品简介 某赛通电子文档安全管理系统(简称:CDG)是一款电子文档安全加密软件,该系统利用驱动层透明加密技术,通过对电子文档的加密保护,防止内部员工泄密和外部人员非法窃取企业核心重要数据资产,对电子文档进行全生命周期防护,系统具有透明加密、主动加密、智能…

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK在相机图像中绑定元数据和块数据(C#)

Baumer工业相机堡盟工业相机如何通过NEOAPI SDK在相机图像中绑定元数据和块数据&#xff08;C#&#xff09; Baumer工业相机Baumer工业相机NEOAPI SDK和元数据和块数据的技术背景Baumer工业相机通过NEOAPISDK在相机图像中绑定元数据和块数据功能1.引用合适的类文件2.通过NEOAPI…

采购数据分析驾驶舱分享,照着它抄作业

今天我们来看一张采购管理驾驶舱。这是一张充分运用了多种数据可视化图表、智能分析功能&#xff0c;从物料和供应商的角度全面分析采购情况的BI数据可视化报表&#xff0c;主要分为三个部分&#xff0c;接下来就分部分来了解一下。 第一部分&#xff1a;关键指标计算及颜色预…

从零入门区块链和比特币(第一期)

欢迎来到我的区块链与比特币入门指南&#xff01;如果你对区块链和比特币感兴趣&#xff0c;但不知道从何开始&#xff0c;那么你来对地方了。本博客将为你提供一个简明扼要的介绍&#xff0c;帮助你了解这个领域的基础知识&#xff0c;并引导你进一步探索这个激动人心的领域。…

2024.4.26力扣每日一题——快照数组

2024.4.26 题目来源我的题解方法一 TreeMap方法二 哈希表二分法 题目来源 力扣每日一题&#xff1b;题序&#xff1a;1146 我的题解 方法一 TreeMap 使用TreeMap记录每个snip_id下的修改记录。 在set时&#xff0c;判断snip_id下是否有修改记录&#xff0c;若无则将最后一次…

rabbitmq集群配置

1&#xff0c;配置环境变量 MY_POD_NAME&#xff1a;当前Pod的名称 RABBITMQ_ERLANG_COOKIE&#xff1a;设置Erlang Cookie用于节点间通信安全验证&#xff0c;值来自/nfs/rabbitmq/lib/.erlang.cookie文件内容 RABBITMQ_NODENAME&#xff1a;根据Pod名称动态生成了RabbitMQ…

【GO】命令行解析 os 与 flag

目录 OS解析命令 简单用法 进阶用法 flag命令解析 基础实例 1. 自定义数据类型 2. 创建多个 FlagSet 3. 整合环境变量和配置文件 os与flag 关键点解析 程序的作用 示例命令行调用 在 Go 语言中&#xff0c;命令行解析是一项基本且常用的功能&#xff0c;它允许开发者…

微信小程序简单实现购物车功能

微信小程序简单实现购物车结算和购物车列表展示功能 实现在微信小程序中对每一个购物车界面的商品订单&#xff0c;进行勾选结算和取消结算的功能&#xff0c;相关界面截图如下&#xff1a; 具体实现示例代码为&#xff1a; 1、js代码&#xff1a; Page({/*** 页面的初始数…

K8s: 公有镜像中心和私有镜像中心的搭建

公有镜像中心的搭建和使用 1 &#xff09;在 官方docker镜像中心推送 在 hub.docker.com 上注册账号 (国内一般访问不了&#xff0c;原因不多说) 找到 Create Repository 按钮就行仓库的创建 这样就在官方创建了一个仓库&#xff0c;比如地址为: xx/y-y xx 是我的账户名y-y 是…

【早晨读书会】深入理解rust并发编程

第一章 线程 线程 线程是调度的最小单位 同一进程中的多条线程将共享该进程中的全部系统资源&#xff0c;如虚拟地址空间&#xff0c;文件描述符和信号处理等等。但同一进程中的多个线程有各自的调用栈&#xff08;call stack&#xff09;&#xff0c;自己的寄存器上下文&am…

数之寻软件怎么样?

数之寻软件是一款功能强大的数据恢复和备份软件&#xff0c;以下是对其特点和功能的详细评价&#xff1a; 一、数据恢复方面&#xff1a; 高效的数据恢复能力&#xff1a;数之寻软件采用了先进的算法和数据恢复技术&#xff0c;能够快速有效地恢复丢失或损坏的数据。无论是文…