2017-04-13 64 views
2

更新我想從一個委託方法更新的UIViewControllerUIViewUIControllerView不能從委託功能

有一個簡介: 用戶觸發從UIViewController下載,下載由類管理,當UploadAsyncData完成後,下載方法將處理的響應傳遞給另一個類。該類將數據寫入本地數據庫。

我想告訴用戶拋出UIViewController,他是從進程取得進展。

我從現在做:

  • UIViewController我得到一個UIView代表與它的一些消息的OverlayUIView也被設置爲一個靜態輔助類,以幫助從外部引用它。

  • 當用戶按下下載按鈕,將Overlay顯示出來,並告知行動已經觸發用戶。

  • 當動作被傳遞到下載類中,Overlay文字更新爲「您的下載都在進步」

  • 當下載完成的下載類處理響應更新Overlay文本的方法爲「下載已經結束,處理收到的數據...」

  • 作爲收到的數據是一個C#目標i從調用此對象的SaveToDatabase方法。

  • 的SaveToDatabase方法更新Overlay與進度指示器。

到目前爲止,所有步驟都正確更新Overlay消息除了SaveToDatabase步驟。 調試時,我可以看到更新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, "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(); 
      {...} 
     } 
     {...} 
    } 

} 

最後的一步,不是更新的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); 
     } 
    } 
} 

編輯:一些痕跡從通話記錄幫手。

Helpers <UpdateOverlayMessage> :Transmitting request to the server...(called from Apply) -2037862263 
Helpers <UpdateOverlayMessage> :Processing recieved response...(called from Apply) -2037862263 
Helpers <UpdateOverlayMessage> :Processing 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: 忘記展示覆蓋類

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

回答

2

確保它在主線程上運行時,您在更新UI。 InvokeOnMainThread方法在NSObject上定義,因此使得Helper類從NSObject繼承。

 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; 

當更新UI:

Helpers.Instance.UpdateOverlayMessage("..."); 
+0

我必須改變類類型,靜態類不能從Object派生。所以我需要重新思考類模型,我想避免可以在對象之間做出強有力參考的模式,因爲我的應用程序已經存在內存問題。 – SunLiker67

+0

啊,因爲靜態類不能從NSObject繼承,所以你可以使用Singleton模式來完成它。我將在我的答案中更新它。 –

+0

通過此更新,覆蓋停止從DoRequest更新 – SunLiker67