Animation problem in iOS 4 - cocoa-touch

Am having trouble setting up an animation in iOS 4. Here is the code in the ViewDidLoad method:
//---animate the two views flipping---
[UIView beginAnimations:#"flipping view"
context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight:tempImageView
cache:YES];
[tempImageView setHidden:YES];
[UIView commitAnimations];
[UIView beginAnimations:#"flipping view"
context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationCurve:UIViewAnimationCurveEaseInOut];
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight:tempImageView
cache:YES];
[UIImageView setHidden:NO];
[UIView commitAnimations];
While the code compiles, I get a message which reads Method ' + setAnimationTransition::cache:' not found (return type defaults to 'id')
When I hit the page control, the app crashed. Here is what the console said:
2011-06-18 14:06:48.249 UsingViews[2093:207] +[UIView setAnimationTransition::cache:]: unrecognized selector sent to class 0x58f3b4
2011-06-18 14:06:48.255 UsingViews[2093:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[UIView setAnimationTransition::cache:]: unrecognized selector sent to class 0x58f3b4'
*** Call stack at first throw:
(
0 CoreFoundation 0x00dc25a9 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x00f16313 objc_exception_throw + 44
2 CoreFoundation 0x00dc417b +[NSObject(NSObject) doesNotRecognizeSelector:] + 187
3 CoreFoundation 0x00d33966 ___forwarding___ + 966
4 CoreFoundation 0x00d33522 _CF_forwarding_prep_0 + 50
5 UsingViews 0x00002d97 -[UsingViewsViewController pageTurning:] + 935
6 UIKit 0x000144fd -[UIApplication sendAction:to:from:forEvent:] + 119
7 UIKit 0x000a4799 -[UIControl sendAction:to:forEvent:] + 67
8 UIKit 0x000a6c2b -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 527
9 UIKit 0x001cdfaa -[UIPageControl endTrackingWithTouch:withEvent:] + 386
10 UIKit 0x000a578b -[UIControl touchesEnded:withEvent:] + 381
11 UIKit 0x00038ded -[UIWindow _sendTouchesForEvent:] + 567
12 UIKit 0x00019c37 -[UIApplication sendEvent:] + 447
13 UIKit 0x0001ef2e _UIApplicationHandleEvent + 7576
14 GraphicsServices 0x00ffb992 PurpleEventCallback + 1550
15 CoreFoundation 0x00da3944 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
16 CoreFoundation 0x00d03cf7 __CFRunLoopDoSource1 + 215
17 CoreFoundation 0x00d00f83 __CFRunLoopRun + 979
18 CoreFoundation 0x00d00840 CFRunLoopRunSpecific + 208
19 CoreFoundation 0x00d00761 CFRunLoopRunInMode + 97
20 GraphicsServices 0x00ffa1c4 GSEventRunModal + 217
21 GraphicsServices 0x00ffa289 GSEventRun + 115
22 UIKit 0x00022c93 UIApplicationMain + 1160
23 UsingViews 0x000023b9 main + 121
24 UsingViews 0x00002335 start + 53
)
terminate called after throwing an instance of 'NSException'
(gdb)
Can you tell me what's wrong? Thanks in advance!

The method name is setAnimationTransition:forView:cache: not setAnimationTransition::cache:
Change
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight:tempImageView cache:YES];
to
[UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:tempImageView cache:YES];

Related

Crashing [self.collectionView performBatchUpdates:]

The application is crashing below I don't know it seems like apple bug.. if any one faced the same problem please update me
[self.collectionView performBatchUpdates: —>// crashing here
^{
if (indexToInsertAt == count)
{
// Add cell at end of list
[self.restaurantList addObject:cellData];
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:indexToInsertAt
inSection:0];
[self.collectionView insertItemsAtIndexPaths:#[indexPath]];
}
else
{
// Insert cell
[self.restaurantList insertObject:cellData
atIndex:indexToInsertAt];
NSIndexPath *indexPath = [NSIndexPath indexPathForItem:indexToInsertAt
inSection:0];
[self.collectionView insertItemsAtIndexPaths:#[indexPath]];
}
}
completion:^(BOOL finished)
{
// Do nothing
}];
crash log are here:
Crashed: com.apple.main-thread
SIGABRT ABORT at 0x3baff1f0
raw
0
libsystem_kernel.dylib
__pthread_kill + 8
10
Foundation
-[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 90
11
UIKit
__45-[UICollectionViewData validateLayoutInRect:]_block_invoke + 1206
12
UIKit
-[UICollectionViewData validateLayoutInRect:] + 938
13
UIKit
-[UICollectionView layoutSubviews] + 156
14
UIKit
-[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 380
15
QuartzCore
-[CALayer layoutSublayers] + 142
16
QuartzCore
CA::Layer::layout_if_needed(CA::Transaction*) + 350
17
UIKit
-[UIView(Hierarchy) layoutBelowIfNeeded] + 550
18
UIKit
-[UICollectionView performBatchUpdates:completion:] + 170
crash is happening rearly please help me out
thanks in advance....

NSView Frame Reverting After Being Set Programmatically

So I have a view that I set in IB and I need to change the frame programmatically. For some reason, the frame keeps reverting back to its IB location after I've set it. I subclassed NSView and logged the frame in the -setFrame:(NSRect)frameRect method and it looks like -setFrame: is getting called twice -- once when I set it (where it logs the new values) and once when it reverts (where it logs the IB values). I can't seem to distill the root of the problem because in some situations (such as if I have an NSButton dedicated to setting it or have a timer setting the frame) it works perfectly, but if I have the -setFrame: call in-line with my other code, it always reverts.
Edit:
This is a simple example that shows the problem (the original frame in the IB is {{20, 118}, {48, 48}}):
AppDelegate.m:
#import "AppDelegate.h"
#implementation AppDelegate
- (void)awakeFromNib{
[self.button setFrame:NSMakeRect(50, 10, 100, 100)];
}
#end
Log:
2014-02-18 18:01:40.206 WHS-ChangingFrameTest[15210:303] Frame: {{50, 10}, {100, 100}}
2014-02-18 18:01:41.223 WHS-ChangingFrameTest[15210:303] Frame: {{20, 118}, {48, 48}}
Edit #2:
Call Stack from when I edit the frame (from original app):
0 MyApp 0x000000010000203c -[FrameLogProgressIndicator setFrame:] + 284
1 MyApp 0x000000010001c994 -[SubjectViewController updateTableViewHeight] + 1284
2 MyApp 0x000000010001c468 -[SubjectViewController updateUI] + 4664
3 MyApp 0x0000000100012f2f -[TabMenuViewController updateDisplayingBlock:] + 975
4 MyApp 0x0000000100010c59 -[TabMenuViewController switchBlockFromDaySchedulePopover:] + 873
5 AppKit 0x00007fff82eea959 -[NSApplication sendAction:to:from:] + 342
6 AppKit 0x00007fff82eea7b7 -[NSControl sendAction:to:] + 85
7 AppKit 0x00007fff82eea6eb -[NSCell _sendActionFrom:] + 138
8 AppKit 0x00007fff82ee8bd3 -[NSCell trackMouse:inRect:ofView:untilMouseUp:] + 1855
9 AppKit 0x00007fff82ee8421 -[NSButtonCell trackMouse:inRect:ofView:untilMouseUp:] + 504
10 AppKit 0x00007fff82ee7b9c -[NSControl mouseDown:] + 820
11 AppKit 0x00007fff82edf50e -[NSWindow sendEvent:] + 6853
12 AppKit 0x00007fff82edb644 -[NSApplication sendEvent:] + 5761
13 AppKit 0x00007fff82df121a -[NSApplication run] + 636
14 AppKit 0x00007fff82d95bd6 NSApplicationMain + 869
15 MyApp 0x00000001000020a2 main + 34
16 libdyld.dylib 0x00007fff8152a7e1 start + 0
17 ??? 0x0000000000000003 0x0 + 3
)
Call Stack from when frame is reverting back:
0 MyApp 0x000000010000203c -[FrameLogProgressIndicator setFrame:] + 284
1 AppKit 0x00007fff82e21e77 -[NSView resizeWithOldSuperviewSize:] + 659
2 AppKit 0x00007fff82e21307 -[NSView resizeSubviewsWithOldSize:] + 318
3 AppKit 0x00007fff82f08399 NSViewLevelLayout + 44
4 AppKit 0x00007fff82f07e65 -[NSView _layoutSubtreeHeedingRecursionGuard:] + 112
5 CoreFoundation 0x00007fff84b524a6 __NSArrayEnumerate + 582
6 AppKit 0x00007fff82f07fc6 -[NSView _layoutSubtreeHeedingRecursionGuard:] + 465
7 CoreFoundation 0x00007fff84b524a6 __NSArrayEnumerate + 582
8 AppKit 0x00007fff82f07fc6 -[NSView _layoutSubtreeHeedingRecursionGuard:] + 465
9 CoreFoundation 0x00007fff84b524a6 __NSArrayEnumerate + 582
10 AppKit 0x00007fff82f07fc6 -[NSView _layoutSubtreeHeedingRecursionGuard:] + 465
11 CoreFoundation 0x00007fff84b524a6 __NSArrayEnumerate + 582
12 AppKit 0x00007fff82f07fc6 -[NSView _layoutSubtreeHeedingRecursionGuard:] + 465
13 AppKit 0x00007fff82f07cfe -[NSView layoutSubtreeIfNeeded] + 615
14 AppKit 0x00007fff82f034ac -[NSWindow(NSConstraintBasedLayout) layoutIfNeeded] + 201
15 AppKit 0x00007fff82dfd0a8 _handleWindowNeedsDisplayOrLayoutOrUpdateConstraints + 446
16 AppKit 0x00007fff833c8901 __83-[NSWindow _postWindowNeedsDisplayOrLayoutOrUpdateConstraintsUnlessPostingDisabled]_block_invoke_01208 + 46
17 CoreFoundation 0x00007fff84b20417 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
18 CoreFoundation 0x00007fff84b20381 __CFRunLoopDoObservers + 369
19 CoreFoundation 0x00007fff84afb7b8 __CFRunLoopRun + 728
20 CoreFoundation 0x00007fff84afb0e2 CFRunLoopRunSpecific + 290
21 HIToolbox 0x00007fff8231aeb4 RunCurrentEventLoopInMode + 209
22 HIToolbox 0x00007fff8231ab94 ReceiveNextEventCommon + 166
23 HIToolbox 0x00007fff8231aae3 BlockUntilNextEventMatchingListInMode + 62
24 AppKit 0x00007fff82dfa533 _DPSNextEvent + 685
25 AppKit 0x00007fff82df9df2 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 128
26 AppKit 0x00007fff82df11a3 -[NSApplication run] + 517
27 AppKit 0x00007fff82d95bd6 NSApplicationMain + 869
28 MyApp 0x00000001000020a2 main + 34
29 libdyld.dylib 0x00007fff8152a7e1 start + 0
30 ??? 0x0000000000000003 0x0 + 3
)
Let me know if I need to post the code from the methods used in the stack for this to be useful. (sorry, I've never really dealt with this stuff before)
An alternative to replacing the content of resizeWithOldSuperviewSize: is to inform the auto layout system that you don't want your NSView to be resized. This will have the effect of keeping your NSView at the origin that you specified programmatically thereby keeping your override of the interface builder intact. You do this by:
[<id> setAutoresizingMask:NSViewNotSizable];
[<id> setTranslatesAutoresizingMaskIntoConstraints:YES];
where <id> would be the instance of your NSView, i.e. self.button. The first line states that the view is not sizable, while the second states that the mask should be considered a constraint by the auto layout system. Your revised AppDelegate.m would then be:
#import "AppDelegate.h"
#implementation AppDelegate
- (void)awakeFromNib{
[self.button setAutoresizingMask:NSViewNotSizable];
[self.button setTranslatesAutoresizingMaskIntoConstraints:YES];
[self.button setFrame:NSMakeRect(50, 10, 100, 100)];
}
#end
Update:
If you use this method with an NSView that you plan to set hidden, the auto layout system will still take the frame of the hidden NSView into account when the frame's superview/window is resized. This means that if the hidden NSView would be outside the visible area of the superview after resize, the auto layout system will prevent the superview from resizing properly and instead will force the superview frame to enclose the hidden NSView.
One naïve solution to this problem is to set the width and height of the NSView to zero after setting hidden:YES and restoring the width and height before setting hidden:NO. For example, at some point in your code using your NSView self.button:
...
[self.button setHidden:YES];
[self.button setFrameSize:NSZeroSize];
...
and later:
...
[self.button setFrameSize:NSMakeSize(160, 90)];
[self.button setHidden:NO];
...
However, if you have width/height auto layout constraints set on the NSView (either programmatically or through Interface Builder), these changes may throw warnings like:
Unable to simultaneously satisfy constraints:
(
"<NSLayoutConstraint:0x608000082990 H:[NSButton:0x6080001200a0(100)]>",
"<NSAutoresizingMaskLayoutConstraint:0x60800008bae0 h=--& v=--& H:[NSButton:0x6080001200a0(0)]>"
)
Will attempt to recover by breaking constraint
<NSLayoutConstraint:0x608000082990 H:[NSButton:0x6080001200a0(100)]>
You can either ignore these warnings, reduce the constraints priority to a low number, change the constraint from = to ≤, or alternately you can simply setTranslatesAutoresizingMaskIntoConstraints:NO before hiding the NSView, and setting it to YES prior to unhiding the NSView:
...
[self.button setTranslatesAutoresizingMaskIntoConstraints:NO];
[self.button setHidden:YES];
...
And when we unhide the NSView:
...
[self.button setTranslatesAutoresizingMaskIntoConstraints:YES];
[self.button setHidden:NO];
...
You can also automate this by subclassing the NSView and overriding setHidden: (note the !):
- (void)setHidden:(BOOL)hidden {
[self setTranslatesAutoresizingMaskIntoConstraints:!hidden];
[super setHidden:hidden];
}
You can then simply call [self.button setHidden:YES]; or [self.button setHidden:NO]; and the overridden method will take care of everything.
From awakeFromNib description:
Because the order in which objects are instantiated from an archive is not guaranteed, your initialization methods should not send messages to other objects in the hierarchy. Messages to other objects can be sent safely from within an awakeFromNib method.
Typically, you implement awakeFromNib for objects that require additional set up that cannot be done at design time. For example, you might use this method to customize the default configuration of any controls to match user preferences or the values in other controls. You might also use it to restore individual controls to some previous state of your application.
I am not 100% sure but I am strongly suggest to move
[self.button setFrame:NSMakeRect(50, 10, 100, 100)];
to
- (void)viewDidLoad
method. Also you should not forget to call super's methods - in some cases it could be critical. So your final code should look like this:
#implementation AppDelegate
- (void)awakeFromNib{
[super awakeFromNib];
... non GUI initialization
}
- (void)viewDidLoad
{
[super viewDidLoad];
[self.button setFrame:NSMakeRect(50, 10, 100, 100)];
}
#end
UPDATE:
Thanks for call stuck. It seems that your view is autoresized. You should check autoresizingMask and auto-layout constraints
So I managed to stop the resizing of the views by subclassing them and overriding -resizeWithOldSuperviewSize: to just do nothing, like this:
- (void)resizeWithOldSuperviewSize:(NSSize)oldSize {};

iOS7 - UITabBarController seletedIndex crash

I am working on a TabBar based application. At some point I am doing:
if([[[appDelegate.tabBarController viewControllers] objectAtIndex:1] isKindOfClass:[UINavigationController class]]) {
UINavigationController *navController = [[appDelegate.tabBarController viewControllers] objectAtIndex:1];
[navController popToRootViewControllerAnimated:NO];
}
appDelegate.tabBarController.selectedIndex = 1; // CRASH HERE
On iOS6 it is working fine but when I build the application with XCode5 / iOS7 then the application crash here randomly. Please help me guys.
Thank you!
Crash Logs:
* thread #1: tid = 0x4b606, 0x0557f811 CoreFoundation`___forwarding___ + 769, queue = 'com.apple.main-thread, stop reason = EXC_BREAKPOINT (code=EXC_I386_BPT, subcode=0x0)
frame #0: 0x0557f811 CoreFoundation`___forwarding___ + 769
frame #1: 0x0557f4ee CoreFoundation`_CF_forwarding_prep_0 + 14
frame #2: 0x01128d6a UIKit`-[UISearchBar _didMoveFromWindow:toWindow:] + 168
frame #3: 0x00eca847 UIKit`-[UIView(Internal) _didMoveFromWindow:toWindow:] + 761
frame #4: 0x00eca847 UIKit`-[UIView(Internal) _didMoveFromWindow:toWindow:] + 761
frame #5: 0x00eca847 UIKit`-[UIView(Internal) _didMoveFromWindow:toWindow:] + 761
frame #6: 0x00ec2070 UIKit`__45-[UIView(Hierarchy) _postMovedFromSuperview:]_block_invoke + 162
frame #7: 0x00ec1ef8 UIKit`-[UIView(Hierarchy) _postMovedFromSuperview:] + 260
frame #8: 0x00ecd031 UIKit`-[UIView(Internal) _addSubview:positioned:relativeTo:] + 1847
frame #9: 0x00ec0521 UIKit`-[UIView(Hierarchy) addSubview:] + 56
frame #10: 0x00f5b1f8 UIKit`-[UITransitionView transition:fromView:toView:removeFromView:] + 1205
frame #11: 0x00f5ad3b UIKit`-[UITransitionView transition:fromView:toView:] + 62
frame #12: 0x00f5aadb UIKit`-[UITransitionView transition:toView:] + 123
frame #13: 0x00fafe45 UIKit`-[UITabBarController transitionFromViewController:toViewController:transition:shouldSetSelected:] + 1438
frame #14: 0x00faf262 UIKit`-[UITabBarController transitionFromViewController:toViewController:] + 63
frame #15: 0x00fab64b UIKit`-[UITabBarController _setSelectedViewController:] + 279
frame #16: 0x00fab470 UIKit`-[UITabBarController setSelectedIndex:] + 261
frame #17: 0x00014e6d TestApp`-[HomeViewController btn_TopRatedClicked:](self=0x0d813830, _cmd=0x0023559b, sender=0x0dbceb80) + 1533 at HomeViewController.m:707
frame #18: 0x02311874 libobjc.A.dylib`-[NSObject performSelector:withObject:withObject:] + 77
frame #19: 0x00e66c8c UIKit`-[UIApplication sendAction:to:from:forEvent:] + 108
frame #20: 0x00e66c18 UIKit`-[UIApplication sendAction:toTarget:fromSender:forEvent:] + 61
frame #21: 0x00f5e6d9 UIKit`-[UIControl sendAction:to:forEvent:] + 66
frame #22: 0x00f5ea9c UIKit`-[UIControl _sendActionsForEvents:withEvent:] + 577
frame #23: 0x00f5dd4b UIKit`-[UIControl touchesEnded:withEvent:] + 641
frame #24: 0x00ea40cd UIKit`-[UIWindow _sendTouchesForEvent:] + 852
frame #25: 0x00ea4d34 UIKit`-[UIWindow sendEvent:] + 1232
frame #26: 0x00e78a36 UIKit`-[UIApplication sendEvent:] + 242
frame #27: 0x00e62d9f UIKit`_UIApplicationHandleEventQueue + 11421
frame #28: 0x055188af CoreFoundation`__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__ + 15
frame #29: 0x0551823b CoreFoundation`__CFRunLoopDoSources0 + 235
frame #30: 0x0553530e CoreFoundation`__CFRunLoopRun + 910
frame #31: 0x05534b33 CoreFoundation`CFRunLoopRunSpecific + 467
frame #32: 0x0553494b CoreFoundation`CFRunLoopRunInMode + 123
frame #33: 0x02b739d7 GraphicsServices`GSEventRunModal + 192
frame #34: 0x02b737fe GraphicsServices`GSEventRun + 104
frame #35: 0x00e6594b UIKit`UIApplicationMain + 1225
frame #36: 0x0000213d TestApp`main(argc=1, argv=0xbfffed08) + 141 at main.m:16
At HomeViewController.m:707 I have found following statement:
appDelegate.tabBarController.selectedIndex = 1; // CRASH HERE
You have solved the problem. The reason is that the view controller is released but the searchbar.delegate is not setting nil. So you can set searchBar.delegate = nil in dealloc of the view controller.
In iOS7, the navigation controller stack is crashed so I have done following:
NSMutableArray *allControllersArray = [[appDelegate.tabBarController viewControllers] mutableCopy];
SearchViewController *viewController2 = [[SearchViewController alloc] initWithNibName:#"SearchViewController" bundle:nil];
UINavigationController *search=[[UINavigationController alloc] initWithRootViewController:viewController2];
[allControllersArray replaceObjectAtIndex:1 withObject:search];
appDelegate.tabBarController.viewControllers = allControllersArray;
And after that:
appDelegate.tabBarController.selectedIndex = 1;

UIViewController purgeMemoryForReason: Crashing on iOS 5

So I've been seeing this crash pretty frequently in Crashlytics, both on iPad and iPad 2, running iOS 5. It looks like it's caused by a memory warning, but the stack trace doesn't reference any of my application code, just iOS frameworks:
0 libobjc.A.dylib objc_msgSend + 15
1 UIKit -[UIViewController purgeMemoryForReason:] + 64
2 Foundation __57-[NSNotificationCenter addObserver: selector: name: object:]_block_invoke_0 + 18
3 CoreFoundation ___CFXNotificationPost_block_invoke_0 + 70
4 CoreFoundation _CFXNotificationPost + 1406
5 Foundation -[NSNotificationCenter postNotificationName: object: userInfo:] + 66
6 Foundation -[NSNotificationCenter postNotificationName: object:] + 30
7 UIKit -[UIApplication _performMemoryWarning] + 80
8 UIKit -[UIApplication _receivedMemoryNotification] + 174
9 libdispatch.dylib _dispatch_source_invoke + 516
10 libdispatch.dylib _dispatch_queue_invoke + 50
11 libdispatch.dylib _dispatch_main_queue_callback_4CF + 156
12 CoreFoundation __CFRunLoopRun + 1268
13 CoreFoundation CFRunLoopRunSpecific + 300
14 CoreFoundation CFRunLoopRunInMode + 104
15 GraphicsServices GSEventRunModal + 156
16 UIKit UIApplicationMain + 1090
17 500px iOS main.m line 12
I've googled high and low but can't find any solutions to this. It looks like this is caused by over-releasing a UIViewController instance, but I'm using ARC, so I don't see how that could be the case.
I'm at a loss of how to even approach this. I can't even tell which UIViewController subclass is causing the issue. I've tried reproducing the problem in the simulator and on the device, but I can't find what causes it. Has anyone seen anything like this or have suggestions on how to approach reproducing the issue?
I think I've solved the issue. I was thinking about it, and the problem isn't the unloading of the UIViewController view, it's the posting of the actual low memory warning notification. There are several instances in my code where I call [[NSNotificationCenter defaultCenter] removeObserver:self]. This is fine in the dealloc method, but there were two instances of this in viewDidUnload methods.
I noticed this when my breakpoint in didReceiveMemory of one of the UIViewController's wasn't getting hit. The code in viewDidUnload was also unregistering self from other, system notifications as well, as detailed here.
I'm not going to mark this as an accepted answer until I verify that the crashes stop with the new update.
UPDATE: I've verified with Crashlytics that the problem has been fixed!
I noticed the exact same stack trace in crashes reported by HockeyApp for devices running on iOS 5.
I never called [[NSNotificationCenter defaultCenter] removeObserver:self] except inside dealloc, so this could not be the cause of the crash.
Here is how I was able reproduce the crash: from MasterViewController I push DetailViewController, then pop it by tapping the back button. Finally, I trigger a memory warning and the crash happens (on iOS 5 only).
It turns out that the DetailViewController instance is not released after being popped because of a retain cycle when using SVPullToRefresh:
#implementation DetailViewController
- (void) viewDidLoad
{
[super viewDidLoad];
[self.scrollView addPullToRefreshWithActionHandler:^{
[self refresh];
}];
}
#end
Since the DetailViewController is not released it’s still registered for memory warning notifications and this is what happens:
frame #0: 0x0004d61b MyApp`-[DetailViewController dealloc](self=0x089a5150, _cmd=0x024d2738) + 27 at DetailViewController.m:103
frame #1: 0x0227ae3d libobjc.A.dylib`_objc_rootRelease + 47
frame #2: 0x0227ae00 libobjc.A.dylib`objc_release + 48
frame #3: 0x0227c047 libobjc.A.dylib`objc_storeStrong + 39
frame #4: 0x0004e44c MyApp`__destroy_helper_block_ + 44 at DetailViewController.m:157
frame #5: 0x029b555d libsystem_sim_blocks.dylib`_Block_release + 166
frame #6: 0x0227ae00 libobjc.A.dylib`objc_release + 48
frame #7: 0x0227c047 libobjc.A.dylib`objc_storeStrong + 39
frame #8: 0x00084c8d MyApp`-[SVPullToRefreshView .cxx_destruct](self=0x08bf3af0, _cmd=0x00000001) + 525 at UIScrollView+SVPullToRefresh.m:121
frame #9: 0x0226630d libobjc.A.dylib`object_cxxDestructFromClass + 104
frame #10: 0x02270fde libobjc.A.dylib`objc_destructInstance + 38
frame #11: 0x02271015 libobjc.A.dylib`object_dispose + 20
frame #12: 0x0247a9a1 CoreFoundation`-[NSObject dealloc] + 97
frame #13: 0x00a8cdc7 UIKit`-[UIView dealloc] + 748
frame #14: 0x0227ae3d libobjc.A.dylib`_objc_rootRelease + 47
frame #15: 0x00a90b73 UIKit`-[UIView(Hierarchy) removeFromSuperview] + 194
frame #16: 0x00a8cc10 UIKit`-[UIView dealloc] + 309
frame #17: 0x00a9d6ff UIKit`-[UIScrollView dealloc] + 405
frame #18: 0x013ab36c Foundation`NSKVODeallocate + 105
frame #19: 0x0227ae3d libobjc.A.dylib`_objc_rootRelease + 47
frame #20: 0x00b21c12 UIKit`-[UIViewController setView:] + 447
frame #21: 0x00b21885 UIKit`-[UIViewController unloadViewForced:] + 117
frame #22: 0x00b2180b UIKit`-[UIViewController unloadViewIfReloadable] + 41
frame #23: 0x00b256ff UIKit`-[UIViewController purgeMemoryForReason:] + 75
frame #24: 0x00b2563b UIKit`-[UIViewController didReceiveMemoryWarning] + 41
frame #25: 0x00b2560d UIKit`-[UIViewController _didReceiveMemoryWarning:] + 33
frame #26: 0x0141ca29 Foundation`__57-[NSNotificationCenter addObserver:selector:name:object:]_block_invoke_0 + 40
frame #27: 0x02443855 CoreFoundation`___CFXNotificationPost_block_invoke_0 + 85
frame #28: 0x02443778 CoreFoundation`_CFXNotificationPost + 1976
frame #29: 0x0136119a Foundation`-[NSNotificationCenter postNotificationName:object:userInfo:] + 98
frame #30: 0x0136db03 Foundation`-[NSNotificationCenter postNotificationName:object:] + 55
frame #31: 0x00a64cf4 UIKit`-[UIApplication _performMemoryWarning] + 91
frame #32: 0x00a64e00 UIKit`-[UIApplication _receivedMemoryNotification] + 180
frame #33: 0x00a64f98 UIKit`__block_global_0 + 36
frame #34: 0x029f1450 libdispatch.dylib`_dispatch_source_invoke + 719
frame #35: 0x029edcc4 libdispatch.dylib`_dispatch_queue_invoke + 66
frame #36: 0x029ee4cf libdispatch.dylib`_dispatch_main_queue_callback_4CF + 295
frame #37: 0x023af803 CoreFoundation`__CFRunLoopRun + 2003
frame #38: 0x023aed84 CoreFoundation`CFRunLoopRunSpecific + 212
frame #39: 0x023aec9b CoreFoundation`CFRunLoopRunInMode + 123
frame #40: 0x038d07d8 GraphicsServices`GSEventRunModal + 190
frame #41: 0x038d088a GraphicsServices`GSEventRun + 103
frame #42: 0x00a5a626 UIKit`UIApplicationMain + 1163
frame #43: 0x00002b82 MyApp`main(argc=1, argv=0xbffff318) + 178 at main.m:15
Or in english: the SVPullToRefreshView instance is released as a result of the view being unloaded. Since the SVPullToRefreshView instance is the last object to hold a reference to the DetailViewController, it is released, then deallocated. But purgeMemoryForReason: was still doing things (i.e. accessing instance variables) with the just deallocated view controller, hence the crash.
Once diagnosed the solution was very simple: just avoid the retain cycle in the first place.
#implementation DetailViewController
- (void) viewDidLoad
{
[super viewDidLoad];
__typeof__(self) __weak weakSelf = self;
[self.scrollView addPullToRefreshWithActionHandler:^{
[weakSelf refresh];
}];
}
#end

Error switching views in AppDelegate

I am making a iPhone app with a login feature. After they login, I have it write to a database. When the user opens the app, I want it to check whether or not to go to the app or show a UIView for them to login. I have some code, but it crashes. Here it is:
- (void)applicationDidFinishLaunching:(UIApplication *)application {
sleep(5);
// Configure and show the window
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
//[application setStatusBarStyle:UIStatusBarStyleBlackOpaque];
int checkLoginCount = 0;
NSArray *checkLoginInfo = [database executeQuery:#"SELECT * FROM login WHERE id != '' or email != '' or password != ''"];
for (NSDictionary *checkLoginRow in checkLoginInfo) {
checkLoginCount++;
}
NSLog(#"alsdfjaldfksjalsdfjkas %d", checkLoginCount);
if (checkLoginCount == 0) {
SplashPageViewController *screentwo = [[SplashPageViewController alloc] initWithNibName:#"splashPage" bundle:nil];
//NSLog(#"aldjksflasdfjadksaldfjsaldksfj %#", screentwo);
screentwo.modalTransitionStyle = UIModalTransitionStyleCoverVertical;
[self presentModalViewController:screentwo animated:NO];
[screentwo release];
} else {
splashView = [[UIImageView alloc] initWithFrame:CGRectMake(0,0, 320, 480)];
splashView.image = [UIImage imageNamed:#"Default.png"];
[window addSubview:splashView];
[window bringSubviewToFront:splashView];
[UIView beginAnimations:nil context:nil];
[UIView setAnimationDuration:0.5];
[UIView setAnimationTransition:UIViewAnimationTransitionNone forView:window cache:YES];
[UIView setAnimationDelegate:self];
[UIView setAnimationDidStopSelector:#selector(startupAnimationDone:finished:context:)];
splashView.alpha = 0.0;
//splashView.frame = CGRectMake(-60, -60, 440, 600);
[UIView commitAnimations];
}
}
And here's the error:
-[TableViewAppDelegate presentModalViewController:animated:]: unrecognized selector sent to instance 0x4e3e860
TableView[15309:207] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[TableViewAppDelegate presentModalViewController:animated:]: unrecognized selector sent to instance 0x4e3e860'
*** Call stack at first throw:
(
0 CoreFoundation 0x00fccbe9 __exceptionPreprocess + 185
1 libobjc.A.dylib 0x011215c2 objc_exception_throw + 47
2 CoreFoundation 0x00fce6fb -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
3 CoreFoundation 0x00f3e366 ___forwarding___ + 966
4 CoreFoundation 0x00f3df22 _CF_forwarding_prep_0 + 50
5 TableView 0x00002b02 -[TableViewAppDelegate applicationDidFinishLaunching:] + 473
6 UIKit 0x002e6253 -[UIApplication _callInitializationDelegatesForURL:payload:suspended:] + 1252
7 UIKit 0x002e855e -[UIApplication _runWithURL:payload:launchOrientation:statusBarStyle:statusBarHidden:] + 439
8 UIKit 0x002f2db2 -[UIApplication handleEvent:withNewEvent:] + 1533
9 UIKit 0x002eb202 -[UIApplication sendEvent:] + 71
10 UIKit 0x002f0732 _UIApplicationHandleEvent + 7576
11 GraphicsServices 0x0186fa36 PurpleEventCallback + 1550
12 CoreFoundation 0x00fae064 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 52
13 CoreFoundation 0x00f0e6f7 __CFRunLoopDoSource1 + 215
14 CoreFoundation 0x00f0b983 __CFRunLoopRun + 979
15 CoreFoundation 0x00f0b240 CFRunLoopRunSpecific + 208
16 CoreFoundation 0x00f0b161 CFRunLoopRunInMode + 97
17 UIKit 0x002e7fa8 -[UIApplication _run] + 636
18 UIKit 0x002f442e UIApplicationMain + 1160
19 TableView 0x000027f6 main + 84
20 TableView 0x00002799 start + 53
21 ??? 0x00000001 0x0 + 1
)
terminate called after throwing an instance of 'NSException'
database isn't nil
Maybe I can't do that action in that method. Who knows. Any help is appreciated! Coulton!
First of all sleep(5); is a bad idea, you should avoid using sleep on the main thread (and better don't use it anywhere).
Seems that you have all your code in one file (main app delegate) and it also is a tableview delegate? Thats why you have so messy code, try to divide logic in two groups.
For example, you can show your modal views with the help of navigation controller:
[[self navigationController] presentModalViewController:modalViewController animated:YES];
and dismiss it using
[self.navigationController dismissModalViewControllerAnimated:YES];
In iOS, you can display views modally by presenting the controller for the modal view from your current view controller. So you have get any view controller loaded before.