OStack程序员社区-中国程序员成长平台

标题: c# - UIControllerView 不会从委托(delegate)函数更新 [打印本页]

作者: 菜鸟教程小白    时间: 2022-12-13 01:02
标题: c# - UIControllerView 不会从委托(delegate)函数更新

我想通过委托(delegate)方法更新 UIViewController 中的 UIView

有草图: 用户从 UIViewController 触发下载,下载由一个类管理,当 UploadAsyncData 完成时,下载方法将处理后的响应传递给另一个类。该类将接收到的数据写入本地数据库。

我想通知用户将 UIViewController 从进程进度中扔到哪里。

从现在开始我做了什么:

到目前为止,除了 SaveToDatabase 步骤之外,所有步骤都正确更新了 Overlay 消息。 调试时,我可以看到更新 Overlay 文本的方法在每一步都被调用,但 UIView 文本没有更新。

我不能使用 InvokeOnMainThread 因为 SaveToDatabase 不是 UIViewController 我不明白为什么所有步骤都正确更新 UIView 但最后一个没有.

这是所有这一步的一些提取代码。

主要方法

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);
        }
    }
}

处理downloadAction的方法

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, "OST", bytes);
        {...}
    }

    void OnUploadDataCompleted(object sender, UploadDataCompletedEventArgs e)
    {
        Helpers.UpdateOverlayMessage("rocessing recieved response...");
        {...}
        HandleResponse handler = new HandleResponse(myParameters, e.Result);
        {...}
    }
}

处理服务器响应的类

public class HttpResponseAction
{
    {...}
    public void ExecuteAction(HandleResponse handled, Request request)
    {
        {...}
        Helpers.UpdateOverlayMessage("rocessing response...");
        {...}
        HandleTrainings(queryId, action, JsonConvert.DeserializeObject<List<TrainingContainer>>(json, Settings));
        {...}
    }

    void HandleFormation(string queryId, string action, object nestedResult)
    {
        {...}
        if (action == "display") {
            result.SaveToDatabase();
            {...}
        }
        {...}
    }

}

最后一步,即不更新 UIView(之前的所有步骤都在正确更新它)

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.
                    {...}
                }
            }
        }
        {...}
    }
}

助手类

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);
        }
    }
}

编辑:从对 Helper 的调用中记录的一些跟踪记录。

Helpers <UpdateOverlayMessage> :Transmitting request to the server...(called from Apply) -2037862263
Helpers <UpdateOverlayMessage> rocessing recieved response...(called from Apply) -2037862263
Helpers <UpdateOverlayMessage> rocessing response...(called from Apply) -2037862263
Helpers <UpdateOverlayMessage> :Updating sign list in progress, may be take a while...(called from Apply) -2037862263
Helpers <UpdateProgressValue> (called from Apply)-2037862263
Helpers <UpdateProgressValue> (called from Apply)-2037862263
Helpers <UpdateProgressValue> (called from Apply)-2037862263
Helpers <UpdateProgressValue> (called from Apply)-2037862263
Helpers <UpdateProgressValue> (called from Apply)-2037862263
Helpers <UpdateProgressValue> (called from Apply)-2037862263
Helpers <UpdateProgressValue> (called from Apply)-2037862263
Helpers <UpdateProgressValue> (called from Apply)-2037862263
Helpers <UpdateProgressValue> (called from Apply)-2037862263
Helpers <UpdateProgressValue> (called from Apply)-2037862263
Helpers <UpdateProgressValue> (called from Apply)-2037862263
Helpers <UpdateProgressValue> (called from Apply)-2037862263
Helpers <UpdateProgressValue> (called from Apply)-2037862263
Helpers <UpdateProgressValue> (called from Apply)-2037862263

更新 2: 忘记显示 Overlay 类

public class LoadingOverlay : UIView {
        // control declarations
        UIActivityIndicatorView activitySpinner;
        UILabel loadingLabel;
        UIProgressView progressView;

        public LoadingOverlay (CGRect frame) : base (frame)
        {
            // configurable bits

            BackgroundColor = UIColor.Black;
            Alpha = 0.55f;
            AutoresizingMask = UIViewAutoresizing.All;

            nfloat labelHeight = 22;
            nfloat labelWidth = Frame.Width - 20;

            // derive the center x and y
            nfloat centerX = Frame.Width / 2;
            nfloat centerY = Frame.Height / 2;

            // create the activity spinner, center it horizontall and put it 5 points above center x
            activitySpinner = new UIActivityIndicatorView(UIActivityIndicatorViewStyle.WhiteLarge);
            activitySpinner.Frame = new CGRect ( 
                centerX - (activitySpinner.Frame.Width / 2) ,
                centerY - activitySpinner.Frame.Height - 20 ,
                activitySpinner.Frame.Width,
                activitySpinner.Frame.Height);
            activitySpinner.AutoresizingMask = UIViewAutoresizing.All;
            AddSubview (activitySpinner);
            activitySpinner.StartAnimating ();

            // create and configure the "Loading Data" label
            loadingLabel = new UILabel(new CGRect (
                centerX - (labelWidth / 2),
                centerY + 20 ,
                labelWidth ,
                labelHeight
            ));
            loadingLabel.BackgroundColor = UIColor.Clear;
            loadingLabel.TextColor = UIColor.White;
            loadingLabel.Text = "Wait a moment...";
            loadingLabel.TextAlignment = UITextAlignment.Center;
            loadingLabel.AutoresizingMask = UIViewAutoresizing.All;
            AddSubview (loadingLabel);

            progressView = new UIProgressView();
            progressView.Progress = 0.0f;
            var screenParts = Frame.Width / 3;
            progressView.Frame = new CGRect(new CGPoint(screenParts,loadingLabel.Frame.Y + loadingLabel.Frame.Height + 20), new CGSize(screenParts,40));
            progressView.Hidden = true;

            AddSubview(progressView);
        }

        /// <summary>
        /// Fades out the control and then removes it from the super view
        /// </summary>
        public void Hide ()
        {
            progressView.Progress = 0.0f;
            InvokeOnMainThread(() => {
                UIView.Animate(
                    0.5, // duration
                    () => { Alpha = 0; },
                    () => { RemoveFromSuperview(); }
                );
            });
        }

        public void SetLoadingLabel(String text)
        {
            InvokeOnMainThread(() => {
                loadingLabel.Text = text;
            });
        }

        public void UpdateProgress(float progressValue){
            if(progressView.Hidden){
                progressView.Hidden = false;
            }
            if(progressValue > 1){
                progressValue = 1;
            }
            InvokeOnMainThread(() => {
                progressView.SetProgress(progressValue, true);
            });
        }
    }



Best Answer-推荐答案


确保在更新 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("...");

关于c# - UIControllerView 不会从委托(delegate)函数更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43386614/






欢迎光临 OStack程序员社区-中国程序员成长平台 (https://ostack.cn/) Powered by Discuz! X3.4