如何在iOS上使用Xamarin未公开的方法?

时间:2017-07-30 17:15:51

标签: c# ios xamarin xamarin.ios

我想使用NSString上存在的名为writeToFile:atomically:encoding:error:this method is not exposed to Xamarin.iOS的方法。

如何创建允许我使用此方法的绑定?我找到的所有资源都解释了如何绑定库。

我知道有更好的方法可以将字符串写入文件,但这不是关于这个方法,而是如何绑定这些方法。

2 个答案:

答案 0 :(得分:5)

所以最后我设法通过绑定库来解决它。

我创建了一个类型为“Binding Library(iOS)”的新项目。之后我添加了一个新文件NSStringWriteToFileExtension.cs,并在属性中确保 Build Action 设置为ObjcBindingApiDefinition并将以下代码放在那里

using Foundation;
using ObjCRuntime;

namespace Foundation
{
    [Category]
    [BaseType(typeof(NSString))]
    public interface NSStringWriteToFileExtension
    {
        [Export("writeToFile:atomically:encoding:error:")]
        bool Write(string filePath, bool atomically, NSStringEncoding encoding, out NSError error);
    }
}

这会在NSString上创建一个新扩展程序,以便我访问该方法。

答案 1 :(得分:4)

在ObjC实例上调用方法是关于消息传递。您不直接调用该方法,但ObjC objc_msgSend函数将在调用对象时调用它,描述要调用的方法的选择器以及方法的参数。

定义objc_msgSend入口点:

注意:这包括您希望调用选择器的对象,使用选择器名称创建的选择器,然后是要传递的参数

// NSString writeToFile:atomically:encoding:error:
[DllImport(Constants.ObjectiveCLibrary, EntryPoint = "objc_msgSend")]
static extern bool NSString_bool_obj_msgSend_IntPtr_bool_NSStringEncoding_IntPtr(
        IntPtr target,
        IntPtr selector,
        IntPtr path,
        bool atomically,
        NSStringEncoding encoding,
        IntPtr error
);

创建匹配选择器:

注意:如果您要反复调用它,请将其缓存

var nsStringWriteToFileSelector = new Selector("writeToFile:atomically:encoding:error:");

呼叫示例:

// Selector for NSString writeToFile:atomically:encoding:error:
var nsStringWriteToFileSelector = new Selector("writeToFile:atomically:encoding:error:");

// Parameters to be passed via `objc_msgSend` 
var nsString = new NSString("StackOverflow");
var path = new NSString("nsstring.txt");
var error = new NSError();

// Call objc_msgSend with the object, selector and parameters
var success = NSString_bool_obj_msgSend_IntPtr_bool_NSStringEncoding_IntPtr(
    nsString.Handle,
    nsStringWriteToFileSelector.Handle,
    path.Handle,
    true,
    NSStringEncoding.UTF8,
    error.Handle);

if (success && File.Exists(path.ToString()))
    Console.WriteLine("success");
else
    Console.WriteLine(error.Description);