如何使用 Objective-C 桥将"completion handler"从 Unity 传递到 Swift



我正在尝试创建一个IOS插件,为我的Unity游戏做一些API调用。

我从这篇文章开始,让它运行起来,这样基本的结构就完成了。

现在调用任何API并在Unity中获得其响应,我查找了这个问题,但我无法找出如何在Objective-C中声明我的_addTwoNumberInIOS函数,以便它可以将completionHandler作为参数(基本上是一个以string为参数并返回void的函数)并将其传递给Swift代码,稍后在它有东西返回时调用它。

我的Unity代码是:
using System.Runtime.InteropServices;
using UnityEngine;
using TMPro;
using AOT;
using System;
public class PluginHelper : MonoBehaviour
{
public static TextMeshProUGUI myText;
[DllImport("__Internal")]
private static extern void _addTwoNumberInIOS(int a, int b, Action<string> completionHandler);
[MonoPInvokeCallback ( typeof ( Action<string> ) )]
private static void completionHandler ( string s )
{
myText.text = "25 + 5  is : " + s;
}
void Start()
{
AddTwoNumber();
}
public void AddTwoNumber()
{
_addTwoNumberInIOS(25, 5, completionHandler);
}
}
我的swift代码是:
import Foundation
@objc public class UnityPlugin : NSObject {
@objc public static let shared = UnityPlugin()
@objc public func AddTwoNumber(a:Int,b:Int,onComplete:@escaping(String)->Void) -> Void {
let url : String = "https://restcountries.eu/rest/v2/all"
var result: String = "1111"
result = "2222"

URLSession.shared.dataTask(with: NSURL(string: url) as! URL, completionHandler: { (data, response, error) in
// Handle result
result = "data "
//            do api call
onComplete(result)

}).resume();
}
}

现在我的Objective-C代码(我有麻烦):

#import <Foundation/Foundation.h>
#include "UnityFramework/UnityFramework-Swift.h"
extern "C" {
#pragma mark - Functions
void _addTwoNumberInIOS(int a , int b, void onComplete(NSString*)) {
[[UnityPlugin shared] AddTwoNumberWithA:a b:b onComplete:onComplete]; // problem here
}
}

I am getting

Cannot initialize a parameter of type 'void (^ _Nonnull)(NSString * _Nonnull __strong)' with an lvalue of type 'void (*)(NSString *__strong)'在线[[UnityPlugin shared] AddTwoNumberWithA:a b:b onComplete:onComplete];

如果我将函数改为:

void _addTwoNumberInIOS(int a , int b, void (^_Nonnull)onComplete(NSString*)) {
[[UnityPlugin shared] AddTwoNumberWithA:a b:b onComplete:onComplete];
}

得到

Block pointer to non-function type is invalid在线void _addTwoNumberInIOS(int a , int b, void (^_Nonnull)onComplete(NSString*))

问题:我如何在Objective-C中声明和定义_addTwoNumberInIOS来使用共享UnityPluginSwift代码,以便我可以返回并使用Unity中的API响应?

谢谢。

当我为我的应用程序编写本机通信时,我广泛使用回调,所以我使用的快捷方式是这样做的:

extern "C"
{
typedef void (*CallbackFunction)();
typedef void (*CallbackFunctionWithString)( const char * );
typedef void (*CallbackFunctionWithInt)( NSInteger );
typedef void (*CallbackFunctionWithFloat)( float );
// Sometimes I also wanted to send back a 'success' bool, with the string data, so I did that like this:
typedef void (*CallbackFunctionWithBoolAndString)( bool, const char * );
// etc ...
#pragma mark - Functions
void _addTwoNumberInIOS( int a , int b, CallbackFunctionWithString onComplete )
{ 
[[UnityPlugin shared] AddTwoNumberWithA:a:b:onComplete];
}
}

Swift文件看起来像这样:

import Foundation
typealias CCallbackFunction = @convention(c) () -> Void;
typealias CCallbackFunctionWithString = @convention(c) (UnsafePointer<CChar>) -> Void;
typealias CCallbackFunctionWithInt = @convention(c) (Int) -> Void;
typealias CCallbackFunctionWithFloat = @convention(c) (Float) -> Void;
typealias CCallbackFunctionWithBool = @convention(c) (Bool) -> Void;
typealias CCallbackFunctionWithBoolAndString = @convention(c) (Bool, UnsafePointer<CChar>) -> Void;
// etc ..
@objc public class UnityPlugin : NSObject
{
@objc public static let shared = UnityPlugin()
@objc public func AddTwoNumber( _ a:Int, _ b:Int, _ onComplete:@escaping CCallbackFunctionWithString ) -> Void {

let url : String = "https://restcountries.eu/rest/v2/all"
var result: String = "1111"
result = "2222"

URLSession.shared.dataTask(with: NSURL(string: url) as! URL, completionHandler: { (data, response, error) in
// Handle result
result = "data "
onComplete(result)

}).resume();
}
}

请注意,这是在Swift 4的狂野西部时代,所以YMMV。但这是一种享受,因为,正如前面提到的,我非常依赖于回调来告诉Unity本地库中的任务何时完成。

最新更新