[Make short and understandable things]
I wrote a custom indent.
-(void)perform { UIView *preV = ((UIViewController *)self.sourceViewController).view; UIView *newV = ((UIViewController *)self.destinationViewController).view; [preV.window insertSubview:newV aboveSubview:preV]; newV.center = CGPointMake(preV.center.x + preV.frame.size.width, newV.center.y); [UIView animateWithDuration:0.4 animations:^{ newV.center = CGPointMake(preV.center.x, newV.center.y); preV.center = CGPointMake(0- preV.center.x, newV.center.y);} completion:^(BOOL finished){ [preV removeFromSuperview]; }]; }
When running segue, an exception does not exist. However, release destinationViewController .
The application will crash when a button is pressed that starts another session in destinationViewController .
I tried to remove [preV removeFromSuperview] , but to no avail.
[Details]
I recently started working with Object-C, and I wrote a custom segue that mimics a push sega.
At the first start, everything works fine.
But after that, no matter what session is running, the application crashes, and I get an EXC_BAD_ACCESS error.
My first guess is that this is related to memory management. Something there needs to be released, but I have no idea what it is.
My second assumption is that this is due to the infrastructure provided by UIView and UIWindow . But then again, due to a lack of knowledge and experience, I cannot understand what the real problem is.
I know that I can actually make a simple approach and create a push sega using the rootviewcontroller and just hide the navigation bar, but I really want to know what is exactly wrong with my seemingly well-designed custom segue and study what happens under cloth codes.
[Update]
Thanks to Phillip Mills and Joachim Isaksson for the suggestions, having done some experiments and using the control points and the Zombie tool,
here is what i understand:
After the user segue has been launched by the button, the application will only crash when the next session is also launched by the button. Starting the next session with viewDidAppear will not crash.
The main cause of the accident:
An Objective-C message was sent to a freed object (zombies)
[#, event type, refCt, library, caller]
0 Malloc 1 UIKit -[UIClassSwapper initWithCoder:] 1 Retain 2 UIKit -[UIRuntimeConnection initWithCoder:] 2 Retain 3 UIKit -[UIRuntimeConnection initWithCoder:] 3 Retain 4 UIKit -[UIRuntimeConnection initWithCoder:] 4 Retain 5 UIKit -[UIRuntimeConnection initWithCoder:] 5 Retain 6 UIKit -[UIRuntimeConnection initWithCoder:] 6 Retain 7 UIKit -[UIRuntimeConnection initWithCoder:] 7 Retain 8 UIKit -[UIRuntimeConnection initWithCoder:] 8 Retain 9 UIKit UINibDecoderDecodeObjectForValue 9 Retain 10 UIKit UINibDecoderDecodeObjectForValue 10 Retain 11 UIKit -[UIStoryboardScene setSceneViewController:] 11 Retain 12 UIKit -[UINib instantiateWithOwner:options:] 12 Release 11 UIKit -[UINibDecoder finishDecoding] 13 Release 10 UIKit -[UINibDecoder finishDecoding] 14 Release 9 UIKit -[UIRuntimeConnection dealloc] 15 Release 8 UIKit -[UIRuntimeConnection dealloc] 16 Release 7 UIKit -[UIRuntimeConnection dealloc] 17 Release 6 UIKit -[UIRuntimeConnection dealloc] 18 Release 5 UIKit -[UINibDecoder finishDecoding] 19 Release 4 UIKit -[UIRuntimeConnection dealloc] 20 Release 3 UIKit -[UIRuntimeConnection dealloc] 21 Release 2 UIKit -[UIRuntimeConnection dealloc] 22 Retain 3 UIKit -[UIStoryboardSegue initWithIdentifier:source:destination:] 23 Retain 4 ProjectX -[pushlike perform] 24 Retain 5 UIKit -[UINib instantiateWithOwner:options:] 25 Retain 6 UIKit +[UIProxyObject addMappingFromIdentifier:toObject:forCoder:] 26 Retain 7 UIKit -[UIProxyObject initWithCoder:] 27 Retain 8 UIKit -[UIRuntimeConnection initWithCoder:] 28 Retain 9 UIKit UINibDecoderDecodeObjectForValue 29 Retain 10 UIKit UINibDecoderDecodeObjectForValue 30 Release 9 UIKit -[UINib instantiateWithOwner:options:] 31 Release 8 UIKit +[UIProxyObject removeMappingsForCoder:] 32 Release 7 UIKit -[UINibDecoder finishDecoding] 33 Release 6 UIKit -[UIRuntimeConnection dealloc] 34 Release 5 UIKit -[UINibDecoder finishDecoding] 35 Release 4 UIKit -[UINibDecoder finishDecoding] 36 Release 3 ProjectX -[pushlike perform] 37 Retain 4 libsystem_sim_blocks.dylib _Block_object_assign 38 Retain 5 UIKit -[UIApplication _addAfterCACommitBlockForViewController:] 39 Release 4 UIKit -[UIStoryboardSegue dealloc] 40 Release 3 UIKit _UIApplicationHandleEvent 41 Release 2 UIKit -[UIStoryboardScene dealloc] 42 Retain 3 UIKit _applyBlockToCFArrayCopiedToStack 43 Release 2 UIKit _applyBlockToCFArrayCopiedToStack 44 Release 1 UIKit __destroy_helper_block_739 45 Release 0 UIKit _applyBlockToCFArrayCopiedToStack 46 Zombie -1 UIKit -[UIApplication sendAction:to:from:forEvent:]
which means that (if I'm not mistaken)
the custom segue somehow called something that frees up the objects to which the Objective-C message will be sent after clicking the button (in destinationViewController ) that launches another segment.
More details
Not one prepareForSegue , since I don't need to pass data between views.
My sessions start the same way:
- (void)viewDidLoad { [super viewDidLoad]; CGRect buttonFrame = CGRectMake( 10, 40, 200, 50 ); UIButton *button = [[UIButton alloc] initWithFrame: buttonFrame]; [button setTitle: @"Go" forState: UIControlStateNormal]; [button addTarget:self action:@selector(nextView) forControlEvents:UIControlEventTouchUpInside]; [button setTitleColor: [UIColor blackColor] forState: UIControlStateNormal]; [self.view addSubview:button]; } - (void)nextView{ [self performSegueWithIdentifier:@"push" sender:self]; }
I have ARC enabled, so I really did not make any release.
[UPDATES 2]
The object that has been turned into a zombie is the destinationViewController user segment.
Do not call removeFromSuperview in custom segue does not stop the object from turning into a zombie.
As long as I use the usual series of models or the push sega (with rootViewController) instead of the usual one I made, there will be no zombies and everything will work fine.