iOS app error - Can't add self as subview

iOS app error - Can't add self as subview
已被困扰要疯了,求助如何解决

ios

4个回答

同一时间同时push多个controller在返回的时候会爆这样的错误,其本质的根源是push动画没有完成你就急着去push下一个controller。

解决的办法如下:

通过创建一个导航控制器的分类,将原有的push方法覆盖,再重写load方法,在里面exchange新的push和原始的push

iphone - iOS app error - Can't add self as subview - Stack Overflow

#import "UINavigationController+Consistent.h"

#import

/// This char is used to add storage for the

isPushingViewController property.

staticcharconst*constObjectTagKey="ObjectTag";

@interfaceUINavigationController()

@property(readwrite,getter = isViewTransitionInProgress) BOOL

viewTransitionInProgress;

@end
@implementationUINavigationController(Consistent)

-(void)setViewTransitionInProgress:(BOOL)property {

NSNumber *number = [NSNumbernumberWithBool:property];

objc_setAssociatedObject(self,ObjectTagKey, number , OBJC_ASSOCIATION_RETAIN);

}
-(BOOL)isViewTransitionInProgress {

NSNumber *number =objc_getAssociatedObject(self, ObjectTagKey);

return[number boolValue];

}
//注意上面是设置对象关联

#pragmamark -InterceptPop,Push,PopToRootVC

/// @name Intercept Pop, Push, PopToRootVC

  • (NSArray*)safePopToRootViewControllerAnimated:(BOOL)animated{

if(self.viewTransitionInProgress)returnnil;

if(animated){

self.viewTransitionInProgress =YES;

}
//-- This is not a recursion, due to method swizzling thecall below calls the originalmethod.

return[self

safePopToRootViewControllerAnimated:animated];

}

  • (NSArray*)safePopToViewController:(UIViewController*)viewController animated:(BOOL)animated {

if(self.viewTransitionInProgress)returnnil;

if(animated){

self.viewTransitionInProgress =YES;

}
//-- This is not a recursion, due to method swizzling thecall below calls the originalmethod.

return[selfsafePopToViewController:viewController animated:animated];

}

  • (UIViewController*)safePopViewControllerAnimated:(BOOL)animated{

if(self.viewTransitionInProgress)returnnil;

if(animated){

self.viewTransitionInProgress =YES;

}
return[selfsafePopViewControllerAnimated: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 thecall below calls the originalmethod.

[selfsafePushViewController: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.

[selfsafeDidShowViewController: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 tc =navigationController.topViewController.transitionCoordinator;

[tcnotifyWhenInteractionEndsUsingBlock:^(id context) {

self.viewTransitionInProgress =NO;

//--Reenable swipe back gesture.

self.interactivePopGestureRecognizer.delegate= (id)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.delegatenavigationController: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
//+ (void)load在类被加载的时候就会被执行,所以即使没有引入头文件或者主动调用他也会被执行。

同一时间同时push多个controller在返回的时候会爆这样的错误,其本质的根源是push动画没有完成你就急着去push下一个controller。

解决的办法如下:

通过创建一个导航控制器的分类,将原有的push方法覆盖,再重写load方法,在里面exchange新的push和原始的push

iphone - iOS app error - Can't add self as subview - Stack Overflow

#import "UINavigationController+Consistent.h"

#import

/// This char is used to add storage for the

isPushingViewController property.

staticcharconst*constObjectTagKey="ObjectTag";

@interfaceUINavigationController()

@property(readwrite,getter = isViewTransitionInProgress) BOOL

viewTransitionInProgress;

@end
@implementationUINavigationController(Consistent)

-(void)setViewTransitionInProgress:(BOOL)property {

NSNumber *number = [NSNumbernumberWithBool:property];

objc_setAssociatedObject(self,ObjectTagKey, number , OBJC_ASSOCIATION_RETAIN);

}
-(BOOL)isViewTransitionInProgress {

NSNumber *number =objc_getAssociatedObject(self, ObjectTagKey);

return[number boolValue];

}
//注意上面是设置对象关联

#pragmamark -InterceptPop,Push,PopToRootVC

/// @name Intercept Pop, Push, PopToRootVC

  • (NSArray*)safePopToRootViewControllerAnimated:(BOOL)animated{

if(self.viewTransitionInProgress)returnnil;

if(animated){

self.viewTransitionInProgress =YES;

}
//-- This is not a recursion, due to method swizzling thecall below calls the originalmethod.

return[self

safePopToRootViewControllerAnimated:animated];

}

  • (NSArray*)safePopToViewController:(UIViewController*)viewController animated:(BOOL)animated {

if(self.viewTransitionInProgress)returnnil;

if(animated){

self.viewTransitionInProgress =YES;

}
//-- This is not a recursion, due to method swizzling thecall below calls the originalmethod.

return[selfsafePopToViewController:viewController animated:animated];

}

  • (UIViewController*)safePopViewControllerAnimated:(BOOL)animated{

if(self.viewTransitionInProgress)returnnil;

if(animated){

self.viewTransitionInProgress =YES;

}
return[selfsafePopViewControllerAnimated: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 thecall below calls the originalmethod.

[selfsafePushViewController: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.

[selfsafeDidShowViewController: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 tc =navigationController.topViewController.transitionCoordinator;

[tcnotifyWhenInteractionEndsUsingBlock:^(id context) {

self.viewTransitionInProgress =NO;

//--Reenable swipe back gesture.

self.interactivePopGestureRecognizer.delegate= (id)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.delegatenavigationController: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
//+ (void)load在类被加载的时候就会被执行,所以即使没有引入头文件或者主动调用他也会被执行。

http://stackoverflow.com/questions/22421845/ios-app-crash-on-multiple-segue-at-the-same-time-going-to-other-segue-while-o/22928000#22928000

http://stackoverflow.com/questions/19560198/ios-app-err......
答案就在这里:iOS app error - Can't add self as subview
----------------------你好,人类,我是来自CSDN星球的问答机器人小C,以上是依据我对问题的理解给出的答案,如果解决了你的问题,望采纳。

同求答案图片说明

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问