'Can't add self as subview' crash log details

Source: Internet
Author: User

Problem description: this problem is very common. We usually create a button (we assume this page is rootvc) and add an event to the button, when you click this event, a new Controller A will be pushed out. When we are continuously fast (the interval is within seconds, that is, before the push animation of the previous event is completed) when you click this button twice, it will cause the button to respond to two events consecutively, and two controllers A1 and A2 are introduced at the same time (both controllers are of the type ), when we click A1 (A2) again to return, the first return will be a black screen. When we click A2 (A1) again to return, the following crash will be reported.
* ** Terminating app due to uncaught exception 'nsinvalidargumentexception ', reason: 'Can't add self as subview'

Problem reproduction: In order to reproduce this problem, we use the following method to push the A1 controller 0.3 seconds after it is pushed:

[Self. navigationcontroller pushviewcontroller: controller animated: Yes]; // launch the first controller A1. (refer to the relevant materials. The push animation lasts for about 0.5 s, to ensure that the second page is pushed before the push animation ends, we use 0.3 seconds to push the second controller)

Dispatch_after (dispatch_time (dispatch_time_now, (int64_t) (. 3 * nsec_per_sec), dispatch_get_main_queue (), ^ {
[Self. navigationcontroller pushviewcontroller: [[mycontroller alloc] initwithnibname: @ "mycontroller" Bundle: Nil] animated: Yes]; // push the A2 controller After 0.3 seconds
});
After entering the new page, we press the return button to bring the View Controller A1/a2pop out. According to the Problem description above, when we click the first return, we can see that the navigation bar of the team is black, when we press the second response, we will capture a crash message like 'can't add self as subview.

Solution:
In the past, when we encountered a similar problem, we usually asked the button to accept an event and set the Enable attribute of the button to no rather than enable, then, after one second, set the Enable attribute of the button to yes, in this way, through continuous and fast click control, the two objects A1/a2of the same controller type will not be introduced at the same time by the same controller rootvc. Obviously, this is unknown.

Now we write a category (uinavigationcontroller + gonavigationcontroller. H ") to uinavigationcontroller to implement the following four methods:

-(Void) pushviewcontroller :( uiviewcontroller *) viewcontroller animated :( bool) animated navigationlock :( ID) lock;
{
If (! Lock | self. topviewcontroller = Lock)
{
[Self pushviewcontroller: viewcontroller animated: animated];
}
}
-(ID) navigationlock
{
Return self. topviewcontroller;
}
-(Nsarray *) poptoviewcontroller :( uiviewcontroller *) viewcontroller animated :( bool) animated navigationlock :( ID) Lock ;\
{
If (! Lock | self. topviewcontroller = Lock)
{
[Self poptoviewcontroller: viewcontroller animated: animated];
}
Return @ [];
}
-(Nsarray *) poptorootviewcontrolleranimated :( bool) animated navigationlock :( ID) Lock
{
If (! Lock | self. topviewcontroller = Lock)
{
[Self poptorootviewcontrolleranimated: animated];
}
Return @ [];
}


When calling, we write as follows:
Id lock = [self. navigationcontroller navigationlock];
[Self. navigationcontroller pushviewcontroller: controller animated: Yes navigationlock: Lock];
Analyze the code: At this time, lock is our rootvc. Once we call this method, lock is consistent with self. topviewcontroller is equal, so if the branch is established, rootvc will normally launch A1 (that is, Controller). Once A1, self. topviewcontroller becomes the A1 controller just launched,
At this time, we will follow the problem reproduction method to write the following code:
Dispatch_after (dispatch_time (dispatch_time_now, (int64_t) (. 3 * nsec_per_sec), dispatch_get_main_queue (), ^ {
Mycontroller * controler2 = [[mycontroller alloc] initwithnibname: @ "mycontroller" Bundle: Nil];
[Self. navigationcontroller pushviewcontroller: controler2 animated: Yes navigationlock: Lock];
});
Here, when we call push again, self. the topviewcontroller is already A1, and the input parameter lock is still rootvc. If the branch is not established, another object A2 (that is, controler2) of the same type will be automatically released)

The same is true for POP methods.

'Can't add self as subview' crash log details

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.