2016-12-06 160 views
0

我最近在iOS的Xamarin應用程序中遇到了這個奇怪的異常。我現在努力在HockeyApp正確symbolicate,但反正這裏是崩潰報告日誌從HA:Xamarin.Forms.NavigationProxy.PopAsync:System.ArgumentOutOfRangeException:索引超出範圍

Hardware Model:  iPhone4,1 
Process:   trucker_rolspedi [625] 
Path:   /var/containers/Bundle/Application/B028371C-62B4-4BCD-8491-C78EFE825D22/trucker_rolspediOS.app/trucker_rolspediOS 
Identifier:  com.rolsped.TruckerApp 
Version:   1.1 (60) 
Code Type:  ARM 
Parent Process: ??? [1] 

Date/Time:  2016-12-04T04:53:09Z 
Launch Time:  2016-12-04T04:46:07Z 
OS Version:  iPhone OS 9.3.5 (13G36) 
Report Version: 104-Xamarin 

Exception Type: SIGABRT 
Exception Codes: #0 at 0x21efec5c 
Crashed Thread: 0 

Application Specific Information: 
*** Terminating app due to uncaught exception 'System.ArgumentOutOfRangeException', reason: 'System.ArgumentOutOfRangeException: Index was out of range. Must be non-negative and less than the size of the collection.' 

Xamarin Exception Stack: 
Parameter name: index 
    at System.ThrowHelper.ThrowArgumentOutOfRangeException (System.ExceptionArgument argument, System.ExceptionResource resource) <0x384df0 + 0x00040> in <15e850188d9f425bbeae90f0bbc51e17#ddbdd0f52c53581cb2d9c691bfe34183>:0 
    at System.ThrowHelper.ThrowArgumentOutOfRangeException() <0x384b68 + 0x0001b> in <15e850188d9f425bbeae90f0bbc51e17#ddbdd0f52c53581cb2d9c691bfe34183>:0 
    at System.Collections.Generic.List`1[T].get_Item (System.Int32 index) <0x24a68c + 0x0002f> in <15e850188d9f425bbeae90f0bbc51e17#ddbdd0f52c53581cb2d9c691bfe34183>:0 
    at Xamarin.Forms.NavigationProxy.Pop() <0x5678b4 + 0x00047> in <f9095492ed2b43559d0236ac22ab7223#ddbdd0f52c53581cb2d9c691bfe34183>:0 
    at Xamarin.Forms.NavigationProxy.OnPopAsync (System.Boolean animated) <0x567518 + 0x0005b> in <f9095492ed2b43559d0236ac22ab7223#ddbdd0f52c53581cb2d9c691bfe34183>:0 
    at Xamarin.Forms.NavigationProxy.PopAsync (System.Boolean animated) <0x56708c + 0x0002f> in <f9095492ed2b43559d0236ac22ab7223#ddbdd0f52c53581cb2d9c691bfe34183>:0 
    at trucker_rolsped.Pages.Media.TaskPhotoUploadPage+<SendMediaOnClicked>d__9.MoveNext() <0xe86944 + 0x013bf> in <3fbc044b4d76429b8dee1ec91e769c22#ddbdd0f52c53581cb2d9c691bfe34183>:0 

這裏的代碼從根源堆棧跟蹤線。

 private async void SendMediaOnClicked(object sender, EventArgs e) 
     { 
      SendMedia.IsEnabled = false; 

      try 
      { 
       SelectedMedia.DokArt = _dokArt; 
       SelectedMedia.TruckAppId = _truckAppId; 

       UserDialogs.Instance.ShowLoading("Foto wird hochgeladen..."); 

       await AzureBlobStorageManager.Instance.UploadMediaAsync(SelectedMedia); 

       UserDialogs.Instance.HideLoading(); 

       switch (SelectedMedia.MediaState) 
       { 
        case MediaState.Uploaded: 

         if (IsTakenPhoto) 
         { 
          var result = await DisplayAlert("Foto Upload", "Foto wurde erfolgreich hochgeladen. Möchten Sie das Foto jetzt vom Handy löschen?", "Ja", "Nein"); 

          if (result) 
          { 
           //Platform specific file delete 
           var truckerappMedia = SelectedMedia.File.Path; 

           var platformFileHandler = DependencyService.Get<IFileHandling>(); 

           if (platformFileHandler != null) 
            if (await platformFileHandler.FileExistsAsync(truckerappMedia)) 
            { 
             var deleted = await platformFileHandler.DeleteFileAsync(truckerappMedia); 

             if (deleted) 
              UserDialogs.Instance.Toast("Foto wurde erfolgreich hochgeladen und am Handy gelöscht!!", TimeSpan.FromSeconds(value: 2)); 

             else 
              UserDialogs.Instance.Toast("Foto konnte nicht gelöscht werden! Falls Sie das Foto nicht benötigen " + 
                       "bitte in der Fotogallery selbst löschen", TimeSpan.FromSeconds(value: 5)); 

            } 
          } 
         } 
         else 
          UserDialogs.Instance.Toast("Upload erfolgreich!", TimeSpan.FromSeconds(value: 2)); 


         break; 
        case MediaState.Queued: 
         UserDialogs.Instance.Toast("Upload erfolgt automatisch wenn Sie wieder mit Internet oder dem mobilem Netz verbunden sind!"); 
         break; 
        case MediaState.Created: 
         await DisplayAlert("Media Info", "Upload MediaState.Created!", "Ok"); 
         break; 
        case MediaState.Error: 
         await DisplayAlert("Media Info", "Upload MediaState.Error!", "Ok"); 
         break; 
        default: 
         await DisplayAlert("Media Info", "Upload MediaState Unknown!", "Ok"); 
         break; 
       } 
      } 
      catch (Exception ex) 
      { 
       SelectedMedia.MediaState = MediaState.Error; 
       await DisplayAlert("Sende Media Fehler", ex.Message, "Ok"); 
      } 
      finally 
      { 
       if (SelectedMedia.MediaState == MediaState.Uploaded) 
       { 
        SelectedMedia?.Dispose(); 
        SelectedMedia = null; 
       } 

       _workflowItem.TruckAuftragWorkFlow.TaskStatusId = 80; 

       await Navigation.PopAsync(animated: false); 
       _tcs.SetResult(true); 
      } 
     } 

這裏,我實例化和使用TakePhotoUploadPage 2個方面:它必須在await Navigation.PopAsync(animated: false)聲明發生

1,用途:從所謂Task40ActionPage

在另一個頁面** Task40ActionPage **我調用該方法來顯示TakePhotoUploadPage:

private async void RejectLoadInTimeClicked(object sender, EventArgs e) 
{ 
    _workflowItem.TruckAuftragLauf.FlagFotoLadezeit = null; 

    try 
    { 
     await ShowPhotoPageAsync(this, _workflowItem); 
    } 
    catch (Exception ex) 
    { 
     await MetricsManagerHelper.Instance.SendExceptionToApplicationInsights(ex); 
    } 

    await Navigation.PopAsync(animated: false); 
    _tcs.SetResult(true); 
} 

public async Task<bool> ShowPhotoPageAsync(Page page, WorkflowItem workflowItem) 
{ 
    TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>(); 

    try 
    { 
     await Navigation.PushAsync(new TaskPhotoUploadPage(tcs, workflowItem, dokArt: "50"), animated: false); 
    } 
    catch (Exception e) 
    { 
     tcs.SetException(e); 
    } 

    return await tcs.Task; 
} 

2.用途:從一個ICommand Action委託:

public async Task Task50ActionAsync(WorkflowItem workflowItem) 
    { 
     bool isLastWorkItem = false; 
     var page = Application.Current.MainPage.Navigation.NavigationStack.LastOrDefault(); 

     try 
     { 
      if (workflowItem.QuestionYn) 
      { 
       if (page != null) 
        Device.BeginInvokeOnMainThread(
         async() => 
         { 
          try 
          { 
           bool isOk = await page.DisplayAlert("Todo Command", "Task50ActionAsync ausführen?", "Ja", "Nein"); 

           if (isOk) 
           { 
            await ShowPhotoPageAsync(page, workflowItem, dokArt: "60"); 

            UserDialogs.Instance.ShowLoading("Aufgabe wird gespeichert...", MaskType.Black); 
            isLastWorkItem = await InnerTask50ActionAsync(workflowItem); 

            //PUSH changes to remote.db 
            await OfflineSyncStoreManager.Instance.PushAsync(OfflineSyncStoreManager.Instance.TruckAuftragWorkFlowTable.TableName); 

            if (isLastWorkItem) 
            { 
             // Set TAL to completed 
             workflowItem.TruckAuftragLauf.IsCompleted = true; 

             // Pop Workflow UI View 
             Device.BeginInvokeOnMainThread(async() => await page.Navigation.PopAsync(animated: false)); 
            } 
            UserDialogs.Instance.HideLoading(); 
           } 
          } 
          catch (Exception e) 
          { 
           await MetricsManagerHelper.Instance.SendExceptionToApplicationInsights(e); 

           Device.BeginInvokeOnMainThread(
            async() => 
            { 
             await 
              page.DisplayAlert("Todo Command Error", 
               $"TaskId={workflowItem.TaskId} Action Error:{e}", "Ok"); 
            }); 
          } 
         }); 
      } 
      else 
      { 
       await ShowPhotoPageAsync(page, workflowItem, dokArt: "60"); 

       UserDialogs.Instance.ShowLoading("Aufgabe wird gespeichert...", MaskType.Black); 
       isLastWorkItem = await InnerTask50ActionAsync(workflowItem); 

       //PUSH changes to remote.db 
       await OfflineSyncStoreManager.Instance.PushAsync(OfflineSyncStoreManager.Instance.TruckAuftragWorkFlowTable.TableName); 

       if (isLastWorkItem) 
       { 
        // Set TAL to completed 
        workflowItem.TruckAuftragLauf.IsCompleted = true; 

        // Pop Workflow UI View 
        Device.BeginInvokeOnMainThread(async() => await page.Navigation.PopAsync(animated: false)); 
       } 
       UserDialogs.Instance.HideLoading(); 
      } 
     } 
     catch (Exception e) 
     { 
      await MetricsManagerHelper.Instance.SendExceptionToApplicationInsights(e); 

      if (page != null) 
       Device.BeginInvokeOnMainThread(
        async() => 
        { 
         await 
          page.DisplayAlert("Todo Command Error", $"TaskId={workflowItem.TaskId} Action Error:{e}", 
           "Ok"); 
        }); 
     } 
    } 

    public async Task<bool> ShowPhotoPageAsync(Page page, WorkflowItem workflowItem, string dokArt) 
    { 
     TaskCompletionSource<bool> tcs = new TaskCompletionSource<bool>(); 

     try 
     { 
      await page.Navigation.PushAsync(new TaskPhotoUploadPage(tcs, workflowItem, dokArt: dokArt), animated: false); 
     } 
     catch (Exception e) 
     { 
      tcs.SetException(e); 
     } 

     return await tcs.Task; 
    } 

感謝提供有用的建議大家提前,

埃裏克

+1

在您調用Pop put斷點並檢查導航堆棧之前,從異常看起來你彈出太多次,堆棧是空的 –

+0

我絕對相信你是對的。問題是這種情況很少發生。大多數時候它工作。 –

+0

你有辦法不斷重現它,或者它發生在不可預知的方式?然後,它可能是由雙擊按鈕引起的,您可能想要防止這種情況。在Pop之前添加檢查堆棧的代碼,並在那裏放置中斷點,這樣在正常情況下不會被打中,但只會出現問題。如果您提供完整的調試解決方案,我可能會了解更多信息。因爲我不能在不使用服務的情況下複製它。 –

回答

1

由於Yuri S。建議當代碼堆棧爲空時,代碼可以修復NavigationStack PopAsync:

   if (Navigation.NavigationStack.Count == 1) 
      { 
       await MetricsManagerHelper.Instance.SendErrorToApplicationInsightsAsync($"Navigationstack Count == 1"); 
      } 
      else 
      { 
       await Navigation.PopAsync(animated: false); 
      } 

感謝您的支持!

Eric