NSInvalidArgumentException原因 - [xxxx backdropView:willChangeToGraphicsQuality]

时间:2013-11-08 22:09:16

标签: c# ios objective-c xamarin.ios xamarin

我正在使用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 backdropView ...它的某个时候UIScrollViewPanGuestureRecognizer

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

我从here获得了该信息,因为另一个版本的错误是:

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

所以如果确实如此,我该怎么做呢。呈现视图控制器无法正确发布吗?并且呈现的视图控制器也在我的类中全局声明。

1 个答案:

答案 0 :(得分:0)

您不必使用.DismissViewController方法。我会试着解释原因。

导航到新的ViewController时,使用PushViewController方法。您在参数内创建的视图将添加到堆栈中。所以,例如:

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

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

|     |
|     |
|     |
|  A  |

使用PushViewController添加B和C时,它看起来像这样:

|     |
|  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时才有效,您可以在其中放置U​​I(public class ViewController_B : UIViewController)。

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

导航到另一个ViewController时,使用PopToViewControllerPushViewControllerVirtual方法(来自抽象类UIViewController){{1将永远被调用。如果您希望每次导航到ViewWillAppear时执行一次操作,则可以将其置于此重写方法中。

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

爱和问候, 的Björn