![](/img/trans.png)
[英]How to access data from multiple tabs in Multiplatform iOS Xamarin project
[英]Xamarin: How to return data to Shared Project from NSUrlSession task from Xamarin iOS Project?
我在 Xamarin iOS 项目中有一个类,例如:
public class NetworkUtility : INetworkUtility
{
public void GetData()
{
NSUrl url = new NSUrl("https://reqres.in/api/users?page=2");
NSUrlRequest request = new NSUrlRequest(url);
NSUrlSession session = null;
NSUrlSessionConfiguration myConfig = NSUrlSessionConfiguration.DefaultSessionConfiguration;
myConfig.MultipathServiceType = NSUrlSessionMultipathServiceType.Handover;
session = NSUrlSession.FromConfiguration(myConfig);
NSUrlSessionTask task = session.CreateDataTask(request, (data, response, error) => {
Console.WriteLine(data);
});
task.Resume();
}
}
我在后面的一些 Xaml 代码中从共享项目中调用它,例如:
DependencyService.Get<INetworkUtility>().GetStringData();
现在在GetData()
函数中,我从匿名函数部分的 Web 服务中获取数据:
NSUrlSessionTask task = session.CreateDataTask(request, (data, response, error) => {
Console.WriteLine(data);
});
如何将此数据返回给调用者(即返回到后面的 Xaml 代码)?
如果我将GetData()
函数的返回类型更改为 string 或 Task 并尝试在 lambda 表达式内部返回,则会出现编译错误。
我读过并且各种论坛都说我需要实现一个 NSUrlDelegate 来处理响应。 我为此尝试了多种变体,但没有成功。 请指教。
另外,(我认为这是不可能的或正确的方法)但是有没有办法将整个 NSUrlSession 返回到共享项目并从共享项目本身调用数据任务方法?
有一个简单的解决方案。 在您的INetworkUtility
接口中,像这样声明GetData()
方法:
Task<string> GetData();
在您的 iOS NetworkUtility 类中创建一个 TaskCompletionSource 并返回任务。 在您的 lambda 表达式中,您可以在设置并完成所有操作后,设置任务结果。
public Task<string> GetData()
{
TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
NSUrl url = new NSUrl("https://reqres.in/api/users?page=2");
NSUrlRequest request = new NSUrlRequest(url);
NSUrlSession session = null;
NSUrlSessionConfiguration myConfig = NSUrlSessionConfiguration.DefaultSessionConfiguration;
myConfig.MultipathServiceType = NSUrlSessionMultipathServiceType.Handover;
session = NSUrlSession.FromConfiguration(myConfig);
NSUrlSessionTask task = session.CreateDataTask(request, (data, response, error) => {
//Console.WriteLine(data);
//tell the TaskCompletionSource that we are done here:
tcs.TrySetResult(data); //assuming data is a string but i guess you can convert it if not
});
task.Resume();
return tcs.Task;
}
在您的共享代码中,您可以创建一个等待结果任务的异步函数:
public async Task ReceiveDataShared() {
string yourData = await DependencyService.Get<INetworkUtility>().GetData();
}
编辑:我想可能存在一个TrySetResult(...)
情况,即 lambda 表达式和TrySetResult(...)
永远不会被调用。 在这种情况下,您的共享代码将永远等待。 为了防止这种情况,您可以设置这样的超时:
Task<string> dataTask = DependencyService.Get<INetworkUtility>().GetData();
await Task.WhenAny(dataTask, Task.Delay(10000)); // 10.000ms timeout
if(dataTask.IsCompletedSuccessfully) {
//all good:
string dataString = dataTask.Result;
}else{
//we hit the time limit
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.