2

我正在使用 Xamarin,在更新到 iOS 7 sdk 后,我的应用程序不断崩溃......我有一个函数,我从我的第一个视图控制器传递到我的第二个视图控制器作为一个简单的操作:

    public void Dismiss()
    {
     try{
        this.PresentedViewController.DismissViewController (false, null);
        }    
    catch(Exception ex)
            {
                string filePath = Path.Combine(path, "log.txt");
                File.AppendAllText(filePath,"\n" + DateTime.Now + "\tISSUE:\t Closing colletions detail tab...\n\n" + ex.Message + " " + ex.StackTrace);
            }
    }

现在,即使在捕获异常之后,应用程序也会崩溃。我的日志中打印的是:

Objective-C exception thrown. Name: NSInvalidArgumentException Reason: [UILabel backdropView:willChangeToGraphicsQuality:]: unrecognized selector sent to instance 0x18c8ee40 at (wrapper managed-to-native) MonoTouch.ObjCRuntime.Messaging:void_objc_msgSendSuper_bool_IntPtr (intptr,intptr, bool, intptr) at MonoTouch.UIKit.UIViewController.DismissViewController(Boolean animated, MonoTouch.Foundation.NSAction completionHandler) [0x00057] in /Developer/MonoTouch/Source/monotouch/src/UIKit/UIViewController.g.cs 747 at YltraRoute.MainViewController.CloseCollectionDetailTab()[0x00011]...

我什至不知道从哪里开始。那里没有太多帮助。

哦,它并不总是 [UILabel 背景视图...有时是 UIScrollViewPanGuestureRecognizer

所以我做了更多的搜索,似乎这可能是一个内存问题(对象已经被垃圾收集了)。

我从这里获得了该信息,因为另一个版本的故障是:

Objective-C exception thrown.  Name: NSInvalidArgumentException Reason: -[__NSCFType backdropView:willChangeToGraphicsQuality:]: unrecognized selector sent to instance 0x1eb3ad70 

因此,如果情况确实如此,我该怎么做。呈现视图控制器不可能已经被释放,对吗?并且呈现的视图控制器也在我的类中全局声明。

4

1 回答 1

0

您不必使用该.DismissViewController方法。我将尝试解释原因。

当导航到一个新的 ViewController 时,您使用该PushViewController方法。您在参数中创建的视图被添加到堆栈中。因此,例如:

  • 你有 ViewController A、B 和 C
  • 您的主 ViewController 在 AppDelegate 中设置为 A

因此,当您打开应用程序时,堆栈如下所示:

|     |
|     |
|     |
|  A  |

将 B 和 C 与 相加时PushViewController,如下所示:

|     |
|  C  |
|  B  |
|  A  |

现在,我听到你在问:但为什么我不必使用该DismissViewController方法?嗯,还有另一种方法叫做PopToViewController. 这用于导航到另一个已经在堆栈上的 ViewController。在示例中,您当前位于 ViewController C 中(因为它位于堆栈的顶部)。如果您想导航到 ViewController B,您可以搜索堆栈以确定它是否在其中,然后导航到它。这是它的一小段代码:

ViewController_B view_B = null;

foreach (var item in this.NavigationController.ViewControllers) 
{
    if (item is ViewController_B) 
    {
        view_B = (ViewController_B)item;
    }
}

if (view_B != null) 
{
    this.NavigationController.PopToViewController (view_B, true);
}

现在,发生的情况是,您将弹出到 ViewController B,但由于它不是堆栈的顶部,它会丢弃(垃圾收集)ViewController C。这样,您不需要手动关闭 C。

如果您想从 ViewController C 导航到 ViewController A,同样如此。同样的方法,但现在,它丢弃了 ViewController C 和 ViewController B。

但是如果我想要导航到的 ViewController 不存在怎么办?else您可以在我刚刚粘贴的示例代码下方添加一条语句,如下所示:

if (view_B != null) 
{
    this.NavigationController.PopToViewController (view_B, true);
}

else
{
    this.NavigationController.PushViewController (new ViewController_D, true);
}

请注意,此方法仅在使用 ViewControllers 时有效,您将 UI ( public class ViewController_B : UIViewController) 存放在其中。

要添加如何从一个方法调用方法ViewController to another(导航到它时)的问题的答案,有几个选项。我将列出我使用的方法。

当导航到另一个ViewController时,无论 this 是PopToViewController还是PushViewControllerVirtual方法(来自抽象类UIViewControllerViewWillAppear都会被调用。如果您希望每次导航到 a 时执行一次操作ViewController,则可以将其放在此覆盖的方法中。

我希望这些信息对您有所帮助。祝你好运!

爱与问候,比约恩

于 2015-04-01T11:30:13.983 回答