iOS应用错误-无法将自己添加为子视图


157

我收到了此崩溃报告,但是我不知道如何调试它。

Fatal Exception NSInvalidArgumentException
Can't add self as subview
0 ...    CoreFoundation  __exceptionPreprocess + 130
1    libobjc.A.dylib     objc_exception_throw + 38
2    CoreFoundation  -[NSException initWithCoder:]
3    UIKit   -[UIView(Internal) _addSubview:positioned:relativeTo:] + 110
4    UIKit   -[UIView(Hierarchy) addSubview:] + 30
5    UIKit   __53-[_UINavigationParallaxTransition animateTransition:]_block_invoke + 1196
6    UIKit   +[UIView(Animation) performWithoutAnimation:] + 72
7    UIKit   -[_UINavigationParallaxTransition animateTransition:] + 732
8    UIKit   -[UINavigationController _startCustomTransition:] + 2616
9    UIKit   -[UINavigationController _startDeferredTransitionIfNeeded:] + 418
10   UIKit   -[UINavigationController __viewWillLayoutSubviews] + 44
11   UIKit   -[UILayoutContainerView layoutSubviews] + 184
12   UIKit   -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 346
13   QuartzCore  -[CALayer layoutSublayers] + 142
14   QuartzCore  CA::Layer::layout_if_needed(CA::Transaction*) + 350
15   QuartzCore  CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 16
16   QuartzCore  CA::Context::commit_transaction(CA::Transaction*) + 228
17   QuartzCore  CA::Transaction::commit() + 314
18   QuartzCore  CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 56

iOS版本是7.0.3。有人遇到过这种奇怪的崩溃吗?

更新:

我不知道代码在何处导致此崩溃,因此抱歉,我无法在此处发布代码。

第二次更新

请参阅下面的答案。


3
您能告诉我们您的代码吗?
DavidGölzhäuser13年

43
抱歉,我不明白你的反应过度。堆栈错误在问题上很明显。因此,首先,您可以让用户按要求输入更多代码(仅在问了问题1小时后,您便要求立即将其关闭)。其次,由于我的回答很明确,我无缘无故地接受了投票。问题是“有人遇到这种奇怪的崩溃吗?”。我告诉了他为什么得到这个。即使它不是专门位于其代码中。
Tancrede Chazallet

9
这个问题是正确的。在这种情况下,用户无法提供确切的错误代码。因为他不知道在哪个视图控制器中出了点问题
Ravindra Bagale 2013年

16
我们使用Crashlytics,并且有30多个用户使用“无法将自己添加为子视图”使我们的应用程序崩溃,当然,我们没有试图将自身添加为子视图的代码。从回溯来看,根本没有引用我们的应用程序。
Richie Hyatt

49
投票重新开放;显然,关闭它的人并没有做太多的iOS开发,因为这是iOS7引入的一个常见问题,并且杀死了很多在iOS6上还不错的应用程序(我在不同公司的多个项目中都看到过)。遗憾的是,这个问题在Google上名列前茅,但一些近视眼的人将其关闭。
亚当

Answers:


51

我基于最近调试过的类似内容进行推测...如果您使用Animated:推送(或弹出)视图控制器,是的,它不会立即完成,如果您在动画之前进行另一次推送或弹出,则会发生不良情况完成。您可以通过将Push和Pop操作临时更改为Animated:NO(以便它们同步完成),然后查看是否可以消除崩溃,来轻松测试是否确实如此。如果这确实是您的问题,并且您希望将动画重新打开,则正确的策略是实现UINavigationControllerDelegate协议。这包括以下方法,在动画完成后会调用此方法:

navigationController:didShowViewController:animated:

基本上,您希望根据需要将一些代码移入此方法,以确保在动画完成并且堆栈准备好进行更多更改之前,不会发生其他可能导致NavigationController堆栈发生更改的动作。


回到iOS 4的年代,我在我们的一个应用程序中看到了类似的东西-IIRC,如果您弹出动画然后立即将其推入动画,则UI代码将被严重破坏。最终只是更改为从不进行两个背靠背的动画推/弹出操作。当然,此后所有的基本逻辑都已被重写,但是不难相信仍然没有类似的错误。
Hot Licks

我遇到过同样的问题。在我的情况下,发生这种情况是因为该应用程序[newViewController setLabelTitle:...]在使用调用pushViewController之后执行了更改新视图控制器的ui的指令,Animated:YES.并且解决了将setLabelTitle方法移动到newViewController上的viewDidLoad的问题。感谢您给我的提示。
jeprubio 2014年

很高兴提供了帮助!如果您知道它将是哪个类,那么将代码移动到新的ViewController也是一个不错的选择。无论如何,我越来越发现捕获UINavigationControllerDelegate协议的各种方法很有用。而且我发现,在iOS8中,事件以不同的顺序触发,并且某些过去几乎同步的事件现在可以快速返回,但可以安排它们在后台异步完成,从而产生了许多新的计时错误。谢谢,苹果!
RobP 2014年

14

我们也开始遇到此问题,很有可能我们是由同一问题引起的。

在我们的情况下,在某些情况下,我们必须从后端提取数据,这意味着用户可能会轻按某些内容,然后在进行导航推送之前会稍有延迟。如果用户快速四处移动,他们可能最终会从同一个视图控制器中被两次导航,这触发了这个异常。

我们的解决方案是UINavigationController上的一个类别,除非在给定的时间点顶部的vc是相同的,否则它可以防止推送/弹出。

.h文件:

@interface UINavigationController (SafePushing)

- (id)navigationLock; ///< Obtain "lock" for pushing onto the navigation controller

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated navigationLock:(id)navigationLock; ///< Uses a horizontal slide transition. Has no effect if the view controller is already in the stack. Has no effect if navigationLock is not the current lock.
- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated navigationLock:(id)navigationLock; ///< Pops view controllers until the one specified is on top. Returns the popped controllers. Has no effect if navigationLock is not the current lock.
- (NSArray *)popToRootViewControllerAnimated:(BOOL)animated navigationLock:(id)navigationLock; ///< Pops until there's only a single view controller left on the stack. Returns the popped controllers. Has no effect if navigationLock is not the current lock.

@end

.m文件:

@implementation UINavigationController (SafePushing)

- (id)navigationLock
{
    return self.topViewController;
}

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated navigationLock:(id)navigationLock
{
    if (!navigationLock || self.topViewController == navigationLock) 
        [self pushViewController:viewController animated:animated];
}

- (NSArray *)popToRootViewControllerAnimated:(BOOL)animated navigationLock:(id)navigationLock
{
    if (!navigationLock || self.topViewController == navigationLock)
        return [self popToRootViewControllerAnimated:animated];
    return @[];
}

- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated navigationLock:(id)navigationLock
{
    if (!navigationLock || self.topViewController == navigationLock)
        return [self popToViewController:viewController animated:animated];
    return @[];
}

@end

到目前为止,这似乎已经为我们解决了问题。例:

id lock = _dataViewController.navigationController.navigationLock;
[[MyApi sharedClient] getUserProfile:_user.id success:^(MyUser *user) {
    ProfileViewController *pvc = [[ProfileViewController alloc] initWithUser:user];
    [_dataViewController.navigationController pushViewController:pvc animated:YES navigationLock:lock];
}];

基本上,规则是:在任何与用户无关的延迟之前,请从相关的导航控制器获取一个锁,并将其包括在对push / pop的调用中。

“锁定”一词的措辞可能略逊一筹,因为它暗示某种形式的锁定需要解锁,但是由于任何地方都没有“解锁”方法,因此可能还可以。

(作为一个旁注,“与用户无关的延迟”是代码所引起的任何延迟,即异步的任何情况。用户点击以动画方式推送的导航控制器不会计算在内,因此不需要为这些操作执行navigationLock:版本案例。)


既然您说您正在尝试此解决方案,那么它为您解决了这个问题吗?
Mike D

到目前为止,是的。问题尚未浮出水面。我将更新答案。
Kalle 2014年

4
我使用了基于您的修改版本:gist.github.com/mdewolfe/9369751。看起来已经修复了。
Mike D

2
@Kalle此解决方案适用于推/弹出。但是如果我使用segue怎么解决这个错误?
极客

@Kadle能帮我实现这个吗?请看stackoverflow.com/q/23247713/1323014 THX
Marckaraujo 2014年

12

这段代码解决了这个问题:https : //gist.github.com/nonamelive/9334458

它使用私有API,但我可以确认它在App Store中是安全的。(我的其中一个使用此代码的应用已获得App Store的批准。)

@interface UINavigationController (DMNavigationController)

- (void)didShowViewController:(UIViewController *)viewController animated:(BOOL)animated;

@end

@interface DMNavigationController ()

@property (nonatomic, assign) BOOL shouldIgnorePushingViewControllers;

@end

@implementation DMNavigationViewController

#pragma mark - Push

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    if (!self.shouldIgnorePushingViewControllers)
    {
        [super pushViewController:viewController animated:animated];
    }

    self.shouldIgnorePushingViewControllers = YES;
}

#pragma mark - Private API

// This is confirmed to be App Store safe.
// If you feel uncomfortable to use Private API, you could also use the delegate method navigationController:didShowViewController:animated:.
- (void)didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    [super didShowViewController:viewController animated:animated];
    self.shouldIgnorePushingViewControllers = NO;
}

到目前为止,这是最好的解决方案,与其他一些解决方案相比,我要么仍然会随机遇到两次推送问题,要么会得到冻结的导航控制器。
blueice 2014年

这段代码无法为我编译,缺少一些内容吗?
Maxime B

8

我将在我的应用中描述有关此崩溃的更多详细信息,并将其标记为已回答。

我的应用程序有一个UINavigationController,根控制器是一个UITableViewController,其中包含笔记对象列表。注释对象具有html的content属性。选择一个便笺将转到详细信息控制器。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    //get note object
    DetailViewController *controller = [[DetailViewController alloc] initWithNote:note];
    [self.navigationController pushViewController:controller animated:YES];
}

细节控制器

该控制器具有UIWebView,显示从根控制器传递来的注释内容。

- (void)viewDidLoad
{
    ...
    [_webView loadHTMLString:note.content baseURL:nil];
    ...
}

该控制器是webview控件的委托。如果注释包含链接,请点击一个链接将转到应用内网络浏览器。

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    WebBrowserViewController *browserController = [[WebBrowserViewController alloc] init];
    browserController.startupURL = request.URL;
    [self.navigationController pushViewController:webViewController animated:YES];
    return NO;
}

我每天都收到上述崩溃报告。我不知道我的代码在哪里导致了崩溃。在用户的帮助下进行了一些调查之后,我终于能够修复此崩溃。此html内容将导致崩溃:

...
<iframe src="http://google.com"></iframe>
...

在详细信息控制器的viewDidLoad方法中,我将此html加载到了webview控件中,此后,立即使用request.URL调用了上述委托方法。URL是iframe的源(google.com)。此委托方法在viewDidLoad =>崩溃时调用pushViewController方法!

我通过检查navigationType修复了此崩溃:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    if (navigationType != UIWebViewNavigationTypeOther)
    {
        //go to web browser controller
    }
}

希望这可以帮助


1
从调用时将控制器推入没有动画的不是很好的选择viewDidLoad吗?
里维拉2014年

6

我遇到了同样的问题,对我来说简单的工作就是将Animated:Yes更改为Animated:No。

看来问题出在动画未及时完成。

希望这对某人有帮助。


3

要重现此错误,请尝试同时推送两个视图控制器。或同时推动和弹出。例:

在此处输入图片说明 我创建了一个类别,可以拦截这些呼叫,并通过确保在进行过程中没有其他推送来确保它们的安全性。只需将代码复制到您的项目中,由于方法混乱,您就可以使用了。

#import "UINavigationController+Consistent.h"
#import <objc/runtime.h>
/// This char is used to add storage for the isPushingViewController property.
static char const * const ObjectTagKey = "ObjectTag";

@interface UINavigationController ()
@property (readwrite,getter = isViewTransitionInProgress) BOOL viewTransitionInProgress;

@end

@implementation UINavigationController (Consistent)

- (void)setViewTransitionInProgress:(BOOL)property {
    NSNumber *number = [NSNumber numberWithBool:property];
    objc_setAssociatedObject(self, ObjectTagKey, number , OBJC_ASSOCIATION_RETAIN);
}


- (BOOL)isViewTransitionInProgress {
    NSNumber *number = objc_getAssociatedObject(self, ObjectTagKey);

    return [number boolValue];
}


#pragma mark - Intercept Pop, Push, PopToRootVC
/// @name Intercept Pop, Push, PopToRootVC

- (NSArray *)safePopToRootViewControllerAnimated:(BOOL)animated {
    if (self.viewTransitionInProgress) return nil;
    if (animated) {
        self.viewTransitionInProgress = YES;
    }
    //-- This is not a recursion, due to method swizzling the call below calls the original  method.
    return [self safePopToRootViewControllerAnimated:animated];

}


- (NSArray *)safePopToViewController:(UIViewController *)viewController animated:(BOOL)animated {
    if (self.viewTransitionInProgress) return nil;
    if (animated) {
        self.viewTransitionInProgress = YES;
    }
    //-- This is not a recursion, due to method swizzling the call below calls the original  method.
    return [self safePopToViewController:viewController animated:animated];
}


- (UIViewController *)safePopViewControllerAnimated:(BOOL)animated {
    if (self.viewTransitionInProgress) return nil;
    if (animated) {
        self.viewTransitionInProgress = YES;
    }
    //-- This is not a recursion, due to method swizzling the call below calls the original  method.
    return [self safePopViewControllerAnimated:animated];
}



- (void)safePushViewController:(UIViewController *)viewController animated:(BOOL)animated {
    self.delegate = self;
    //-- If we are already pushing a view controller, we dont push another one.
    if (self.isViewTransitionInProgress == NO) {
        //-- This is not a recursion, due to method swizzling the call below calls the original  method.
        [self safePushViewController:viewController animated:animated];
        if (animated) {
            self.viewTransitionInProgress = YES;
        }
    }
}


// This is confirmed to be App Store safe.
// If you feel uncomfortable to use Private API, you could also use the delegate method navigationController:didShowViewController:animated:.
- (void)safeDidShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    //-- This is not a recursion. Due to method swizzling this is calling the original method.
    [self safeDidShowViewController:viewController animated:animated];
    self.viewTransitionInProgress = NO;
}


// If the user doesnt complete the swipe-to-go-back gesture, we need to intercept it and set the flag to NO again.
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    id<UIViewControllerTransitionCoordinator> tc = navigationController.topViewController.transitionCoordinator;
    [tc notifyWhenInteractionEndsUsingBlock:^(id<UIViewControllerTransitionCoordinatorContext> context) {
        self.viewTransitionInProgress = NO;
        //--Reenable swipe back gesture.
        self.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)viewController;
        [self.interactivePopGestureRecognizer setEnabled:YES];
    }];
    //-- Method swizzling wont work in the case of a delegate so:
    //-- forward this method to the original delegate if there is one different than ourselves.
    if (navigationController.delegate != self) {
        [navigationController.delegate navigationController:navigationController
                                     willShowViewController:viewController
                                                   animated:animated];
    }
}


+ (void)load {
    //-- Exchange the original implementation with our custom one.
    method_exchangeImplementations(class_getInstanceMethod(self, @selector(pushViewController:animated:)), class_getInstanceMethod(self, @selector(safePushViewController:animated:)));
    method_exchangeImplementations(class_getInstanceMethod(self, @selector(didShowViewController:animated:)), class_getInstanceMethod(self, @selector(safeDidShowViewController:animated:)));
    method_exchangeImplementations(class_getInstanceMethod(self, @selector(popViewControllerAnimated:)), class_getInstanceMethod(self, @selector(safePopViewControllerAnimated:)));
    method_exchangeImplementations(class_getInstanceMethod(self, @selector(popToRootViewControllerAnimated:)), class_getInstanceMethod(self, @selector(safePopToRootViewControllerAnimated:)));
    method_exchangeImplementations(class_getInstanceMethod(self, @selector(popToViewController:animated:)), class_getInstanceMethod(self, @selector(safePopToViewController:animated:)));
}

@end

这种解决方案的一个问题是,如果您调用,popToRootViewController或者popToViewController:已经在根视图控制器或viewController上弹出,则didShowViewController不会被调用,它将被卡在中viewTransitionInProgress
divergio”

1
您能否解释以下几行:self.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)viewController; [self.interactivePopGestureRecognizer setEnabled:YES]; 识别器何时被禁用?您怎么知道代表应该是什么?有了这些行,对我来说,它弹出一次后就打破了弹出手势。
divergio”

我尝试实现此功能,过一会儿它锁定了导航控制器,这可能是由于@divergio提到的。
blueice 2014年

2

刚刚也遇到了这个问题。让我告诉你我的代码:

override func viewDidLoad() { 
  super.viewDidLoad()

  //First, I create a UIView
  let firstFrame = CGRect(x: 50, y: 70, height: 200, width: 200)
  let firstView = UIView(frame: firstFrame)
  firstView.addBackgroundColor = UIColor.yellow
  view.addSubview(firstView) 

  //Now, I want to add a subview inside firstView
  let secondFrame = CGRect(x: 20, y:50, height: 15, width: 35)
  let secondView = UIView(frame: secondFrame)
  secondView.addBackgroundColor = UIColor.green
  firstView.addSubView(firstView)
 }

由于此行而出现错误:

firstView.addSubView(firstView)

您无法将自己添加到子视图中。我将代码行更改为:

firstView.addSubView(secondView)

错误消失了,我能够看到两个视图。只是认为这会对希望查看示例的人有所帮助。


我也尝试过这种方法,但是stacktrace会有所不同,并且实际上显示了导致崩溃的代码行。我相信源问题与问题有所不同。

1

在您的代码中搜索“ addSubview”。

在您调用此方法的地方之一中,您尝试使用此方法将视图添加到其自己的子视图数组中。

例如:

[self.view addSubview:self.view];

要么:

[self.myLabel addSubview:self.myLabel];

很高兴得知您发现了错误,现在我完全理解您为什么收到“无法将自身添加为子视图”的原因。在您的View2是导航控制器的根视图控制器的点上,您按下了View2,这导致了这一问题:[View2.view addSubview:View2.view]因此,将self添加为子视图。
Michal Shatz 2014年

1

我认为在任何时候用动画推送/弹出视图控制器都应该很好,并且SDK应该为我们处理呼叫队列。

因此,并非如此,所有解决方案都试图忽略后续的推送,因为最终的导航堆栈不是代码的意图,因此可以将其视为错误。

我改为实现了一个推送调用队列:

// SafeNavigationController.h

@interface SafeNavigationController : UINavigationController
@end

 

// SafeNavigationController.m

#define timeToWaitBetweenAnimations 0.5

@interface SafeNavigationController ()

@property (nonatomic, strong) NSMutableArray * controllersQueue;
@property (nonatomic)         BOOL animateLastQueuedController;
@property (nonatomic)         BOOL pushScheduled;
@property (nonatomic, strong) NSDate * lastAnimatedPushDate;

@end

@implementation SafeNavigationController

- (void)awakeFromNib
{
    [super awakeFromNib];

    self.controllersQueue = [NSMutableArray array];
}

- (void)pushViewController:(UIViewController *)viewController
                  animated:(BOOL)animated
{
    [self.controllersQueue addObject:viewController];
    self.animateLastQueuedController = animated;

    if (self.pushScheduled)
        return;

    // Wait for push animation to finish
    NSTimeInterval timeToWait = self.lastAnimatedPushDate ? timeToWaitBetweenAnimations + [self.lastAnimatedPushDate timeIntervalSinceNow] : 0.0;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((timeToWait > 0.0 ? timeToWait : 0.0) * NSEC_PER_SEC)),
                   dispatch_get_main_queue(), ^
                   {
                       [self pushQueuedControllers];

                       self.lastAnimatedPushDate = self.animateLastQueuedController ? [NSDate date] : nil;
                       self.pushScheduled = NO;
                   });
    self.pushScheduled = YES;
}

- (void)pushQueuedControllers
{
    for (NSInteger index = 0; index < (NSInteger)self.controllersQueue.count - 1; index++)
    {
        [super pushViewController:self.controllersQueue[index]
                         animated:NO];
    }
    [super pushViewController:self.controllersQueue.lastObject
                     animated:self.animateLastQueuedController];

    [self.controllersQueue removeAllObjects];
}

@end

它不能处理推送和弹出的混合队列,但是它是修复大多数崩溃的一个很好的起点。

要点:https : //gist.github.com/rivera-ernesto/0bc628be1e24ff5704ae


我一直在尝试您的解决方案,这看起来非常好,但是我遇到了问题。当一个接一个地推两个带有动画NO的视图控制器时,我非常简要地看到了第一个。以前没有发生过。知道我该如何解决吗?
1

我正在尝试构建一个可以持续导致此类崩溃的项目(我的真实项目会收到此类崩溃报告)。我做了一个简单的应用,其中包含导航控制器,根控制器和一个按钮,该按钮可立即将4个新的视图控制器推入导航堆栈,然后弹出最后一个。如果没有任何特殊的子类化或任何其他东西,它实际上似乎可以正常工作。苹果最近有解决此问题吗?
Cruinh 2015年

1

对不起,派对晚了。我最近遇到了一个问题,因为同时推送多个视图控制器,导航栏进入了损坏状态。发生这种情况是因为在第一个视图控制器仍处于动画状态时,另一个视图控制器已被推入。从不愉快的回答中得到提示,我想到了适用于我的情况的简单解决方案。您只需要UINavigationController继承并重写pushViewController方法,并检查以前的视图控制器动画是否已完成。您可以通过将类UINavigationControllerDelegate设为的委托并将委托设置为来收听动画的完成self

在这里上传了要点以使事情变得简单。

只需确保将新类设置为情节提要中的NavigationController。


到目前为止,它似乎已经解决了我正在处理的应用程序崩溃的问题……此外,解决方案非常简单明了:第一个viewcontroller动画尚未完成。有相同问题的人应该检查一下。
2015年

0

基于@RobP的很好的提示,我制作了UINavigationController子类以防止此类问题。它处理推入和/或弹出操作,您可以安全地执行:

[self.navigationController pushViewController:vc1 animated:YES];
[self.navigationController pushViewController:vc2 animated:YES];
[self.navigationController pushViewController:vc3 animated:YES];
[self.navigationController popViewControllerAnimated:YES];

如果'acceptConflictingCommands'标记为true(默认情况下),则用户将看到vc1,vc2,vc3的动画推送,然后看到vc3的动画弹出。如果'acceptConflictingCommands'为false,则所有推入/弹出请求将被丢弃,直到vc1被完全推入为止-因此将丢弃其他3个调用。


这些命令实际上有冲突吗?我只是集合了一个快速的新项目,以查看崩溃的发生,使用上面的代码(但在Swift中),并且实际上按顺序执行了每次推送和弹出操作。一个接一个地。没有崩溃。不使用任何子类。只是苹果的常规UINavigationController。
Cruinh 2015年

ObjC和iOS 7确实确实崩溃了。我无法确认它是否现在仍然发生。您确定要执行带有animated:trueflag 的命令吗?
hris.to

是的,我正在使用animation:true标志。
Cruinh



0

有时您错误地尝试将视图添加到其自己的视图中。

halfView.addSubview(halfView)

将此更改为您的子视图。

halfView.addSubview(favView)

0

我也遇到了这个问题。当我执行Firebase日志分析时,我发现仅在应用程序冷启动时才会出现此问题。因此,我写了一个可以重现此崩溃的演示

我还发现,显示窗口的根ViewController时,多次执行推送不会再次引起相同的问题。(您可以在AppDelegate.swift中注释testColdStartUp(rootNav),并在ViewController.swift中取消注释testColdStartUp()注释)

ps:我在应用程序中分析了崩溃的场景。当用户单击推送通知以冷启动该应用程序时,该应用程序仍在“启动”页面上,然后单击另一个推送以跳转。此时,该应用可能会出现崩溃。我当前的解决方案是缓存推入或通用链接冷启动以打开App跳转页面,等待rootviewcontroller显示,然后延迟执行。



-2

视图本身不能添加为子视图。

这些视图维护着父子层次结构,因此,如果您将视图本身添加为子视图,则会出现异常。

如果一个类是UIViewController,则使用self.view来获取其视图。

如果一个类是UIView Class,则使用self来获取其视图。


-3

如果它将成为UiViewController类,则不能将self添加为子视图。如果要成为UiView类,则可以将self添加为子视图。


-9

如果您想将子视图添加到视图中,则可以这样做。

UIView *mainview = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)]; //Creats the mainview
    UIView *subview = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)]; //Creates the subview, you can use any kind of Views (UIImageView, UIWebView, UIView…)

    [mainview addSubview:subview]; //Adds subview to mainview

做得好,这是一段不错的代码。现在,您能告诉我这与这个问题有什么关系,以及如何解决这个问题?
Popeye

@Popeye您有更好的主意吗?
DavidGölzhäuser13年

否,因为他们没有提供足够的信息/代码来复制问题。因此,这不可能得到解决,就像您告诉他们如何做与他们的问题无关的事情一样。
Popeye

2
我想这对他们解决这个问题大有帮助。得到它了!大卫G的+1表示实际上尝试帮助StackOverflow上的某人。希望我能为您的接近投票-1 !!!对于用户而言,这种情况仍在发生,就我们所知,这可能是iOS7中的错误。因此,仅仅因为某人无法发布有问题的代码并不意味着该问题无效,并且对于其他用户来说也很有价值。即使只是看到其他人看到相同的问题,却没有任何逻辑上的理由看到他们。-rrh
Richie Hyatt
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.