我想从委托方法更新*headRef
中的UIView
。
有草图:
用户从UIViewController
触发下载,下载由类管理,当UIViewController
完成时,下载方法将处理后的响应传递给另一个类。该类将收到的数据写入本地数据库。
我想告知用户将UploadAsyncData
从流程进度中抛出。
我从现在开始做了什么:
在UIViewController
我有一个代表UIViewController
的{{1}},上面有一些消息。 UIView
也设置为静态辅助类,以帮助从外部引用它。
当用户按下载按钮时,Overlay
会显示并通知用户已触发操作。
当操作传递到下载类时,UIView
文本将更新为“您的下载正在进行中”
下载完成后,处理响应的下载类中的方法会将Overlay
文本更新为“下载完成,处理收到的数据......”
由于收到的数据是C#对象,我从该对象调用SaveToDatabase方法。
SaveToDatabase方法使用进度指示器更新Overlay
。
到目前为止,除了Overlay
步骤之外,所有步骤都正确地更新了Overlay
消息。
调试时,我可以看到在每一步都调用了更新Overlay
文本的方法,但SaveToDatabase
文本未更新。
我无法使用Overlay
,因为SaveToDatabase不是UIView
我不明白为什么所有步骤都正确更新UIView而不是最后一步。
以下是所有这一步的提取代码。
主要方法
InvokeOnMainThread
处理downloadAction的方法
UIViewController
处理服务器响应的类
public class Program:UIViewController
{
{...}
public override void ViewDidLoad()
{
base.ViewDidLoad();
AddOverlay();
}
public void AddOverlay()
{
var bounds = UIScreen.MainScreen.Bounds;
bounds.Size = new CGSize(bounds.Size.Width, bounds.Size.Height);
loadingOverlay = new LoadingOverlay(bounds);
loadingOverlay.Hidden = true;
View.Add(loadingOverlay);
System.Diagnostics.Debug.WriteLine(this.GetType().Name + loadingOverlay.GetHashCode());
Helpers.LoadingOverlay = loadingOverlay;
}
public void DisplayOverlay(string text)
{
if(loadingOverlay != null){
View.BringSubviewToFront(loadingOverlay);
System.Diagnostics.Debug.WriteLine(this.GetType().Name + loadingOverlay.GetHashCode());
loadingOverlay.Hidden = false;
loadingOverlay.SetLoadingLabel( text );
}
}
void Tablesource_OnRowSelected(object sender, eConversion5.DownloadTableSource.RowSelectedEventArgs e)
{
bool isReacheable = myParameters.IsReachable();
if (isReacheable) {
DisplayOverlay("Your download is about to start...");
Request request = new Request(url, myParameters);
request.CanBeSaved = false;
request.Action = "display";
httpCommunication.DoRequest(request);
}
}
}
最后一步,不更新UIView(之前的所有步骤都正确更新)
public class HttpCommunication
{
{...}
public HttpCommunication(Parametrage parameters, HttpResponseAction responseAction)
{
client = new XSWebClient();
client.UploadDataCompleted += OnUploadDataCompleted;
}
public void DoRequest(Request JRequest)
{
{...}
SendRequest();
}
void SendRequest()
{
{...}
client.UploadDataAsync(Request.Uri, "POST", bytes);
{...}
}
void OnUploadDataCompleted(object sender, UploadDataCompletedEventArgs e)
{
Helpers.UpdateOverlayMessage("Processing recieved response...");
{...}
HandleResponse handler = new HandleResponse(myParameters, e.Result);
{...}
}
}
助手类
public class HttpResponseAction
{
{...}
public void ExecuteAction(HandleResponse handled, Request request)
{
{...}
Helpers.UpdateOverlayMessage("Processing response...");
{...}
HandleTrainings(queryId, action, JsonConvert.DeserializeObject<List<TrainingContainer>>(json, Settings));
{...}
}
void HandleFormation(string queryId, string action, object nestedResult)
{
{...}
if (action == "display") {
result.SaveToDatabase();
{...}
}
{...}
}
}
编辑:一些跟踪记录从对Helper的调用。
public class TrainingContainer
{
{...}
public void SaveToDatabase()
{
if(SignList != null){
Helpers.UpdateOverlayMessage("Updating sign list in progress, may be take a while...");
int updated = 0;
int total = SignList.Count();
if(total > 0){
foreach (Training training in SignList) {
updated++;
float progress = (float) updated / total;
Helpers.UpdateProgressValue(progress); //From debbuging, i can see that this method is called, and Overlay object is the same throw all class calls from the starting point.
{...}
}
}
}
{...}
}
}
更新2: 忘了显示Overlay类
public static class Helpers
{
public static LoadingOverlay LoadingOverlay;
{...}
public static void UpdateOverlayMessage(string message)
{
if(LoadingOverlay != null){
StackTrace stackTrace = new StackTrace();
System.Diagnostics.Debug.WriteLine(typeof(Helpers).Name + " (called from " + stackTrace.GetFrame(1).GetMethod().Name + ")" + LoadingOverlay.GetHashCode());
LoadingOverlay.SetLoadingLabel(message);
}
}
public static void UpdateProgressValue(float progessValue)
{
if (LoadingOverlay != null) {
StackTrace stackTrace = new StackTrace();
System.Diagnostics.Debug.WriteLine(typeof(Helpers).Name + " (called from " + stackTrace.GetFrame(1).GetMethod().Name + ")" + LoadingOverlay.GetHashCode());
LoadingOverlay.UpdateProgress(progessValue);
}
}
}
答案 0 :(得分:2)
确保在更新UI时它在主线程上运行。 InvokeOnMainThread方法在NSObject上定义,因此使得Helper类继承自NSObject。所以Helper类可以改进如下:
public sealed class Helpers:NSObject
{
public LoadingOverlay LoadingOverlay;
private static readonly Helpers instance = new Helpers();
private Helpers(){}
public static Helpers Instance
{
get
{
return instance;
}
}
public void UpdateOverlayMessage(string message)
{
InvokeOnMainThread ( () => {
if(LoadingOverlay != null){
StackTrace stackTrace = new StackTrace();
System.Diagnostics.Debug.WriteLine(typeof(Helpers).Name + " (called from " + stackTrace.GetFrame(1).GetMethod().Name + ")" + LoadingOverlay.GetHashCode());
LoadingOverlay.SetLoadingLabel(message);
}
});
}
//So does the method "UpdateProgressValue".
}
主要方法:
Helpers.Instance.LoadingOverlay = loadingOverlay;
更新用户界面时:
Helpers.Instance.UpdateOverlayMessage("...");