• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    公众号

c# - UIControllerView 不会从委托(delegate)函数更新

[复制链接]
菜鸟教程小白 发表于 2022-12-13 01:02:08 | 显示全部楼层 |阅读模式 打印 上一主题 下一主题

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

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

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

从现在开始我做了什么:

  • UIViewController 我有一个 UIView 代表一个 Overlay 上面有一些消息。 UIView 也被设置为一个静态帮助类,以帮助从外部引用它。

  • 当用户按下下载按钮时,Overlay 会显示并通知用户操作已被触发。

  • 将操作传递给下载类时,Overlay 文本会更新为“您的下载正在进行中”

  • 下载完成后,下载类中处理响应的方法将 Overlay 文本更新为“下载完成,正在处理接收到的数据...”

  • 由于收到的数据是一个 C# 对象,我从该对象调用 SaveToDatabase 方法。

  • SaveToDatabase 方法使用进度指示器更新 Overlay

到目前为止,除了 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/

回复

使用道具 举报

懒得打字嘛,点击右侧快捷回复 【右侧内容,后台自定义】
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关注0

粉丝2

帖子830918

发布主题
阅读排行 更多
广告位

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap