UIControllerView不能从委托函数更新

时间:2017-04-13 07:57:52

标签: c# ios uiview uiviewcontroller xamarin.ios

我想从委托方法更新*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);
        }
    }
}

1 个答案:

答案 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("...");