2013-04-25

Viewing NSException reason when "All Exceptions" breakpoint set in Xcode.

I have not memorized this yet. HumbleBee blog is the first to explain it to me accurately.

In short:

  1. Click on objc_execption_throw frame.
  2. po $eax on simulator.
  3. po $r0 on device.

2013-04-11

Reminder to self: use Objective-C literals, dummy.

I love how Objective-C is becoming more Perlish. See docs.

NSDictionary *fruits2colors = @{
                                @"apple"  : @"red",
                                @"banana" : @"yellow",
                                @"pear"   : @"green"
                                };

Although I am too scared to put a trailing comma after the last element, which is perfectly safe in Perl.

2013-03-06

Auto Layout support for UIScrollView.

Note to self: do not forget about this in iOS 6.0 Release Notes. Just search the page for "translatesAutoresizingMaskIntoConstraints".

2013-01-03

Size of UIViews throughout startup.

Looking again at this iPad container-VC-plus-two-content-VCs storyboard setup:

In the Storyboard, the size of ZetaView is 768 × 669 and MuView is 768 × 338. Suppose you need to perform calculations on these numbers at some point while your app is starting up. Those views are not always those dimensions at every phase of start up. These logs show you.

2013-01-03 11:23:07.588 Sandbox[11233:11303] -[SBAppDelegate application:didFinishLaunchingWithOptions:] [Line 16] Entered here.
2013-01-03 11:23:07.593 Sandbox[11233:11303] -[SBContainerViewController prepareForSegue:sender:] [Line 76] childViewController count = 0
2013-01-03 11:23:07.596 Sandbox[11233:11303] -[SBContainerViewController prepareForSegue:sender:] [Line 78] Fired segue = ZetaSegue
2013-01-03 11:23:07.626 Sandbox[11233:11303] -[SBZetaViewController viewDidLoad] [Line 37] self.view.frame.size.width = 768.000000
2013-01-03 11:23:07.627 Sandbox[11233:11303] -[SBZetaViewController viewDidLoad] [Line 38] self.view.frame.size.height = 1004.000000
2013-01-03 11:23:07.628 Sandbox[11233:11303] -[SBContainerViewController prepareForSegue:sender:] [Line 76] childViewController count = 1
2013-01-03 11:23:07.628 Sandbox[11233:11303] -[SBContainerViewController prepareForSegue:sender:] [Line 78] Fired segue = MuSegue
2013-01-03 11:23:07.630 Sandbox[11233:11303] -[SBMuViewController viewDidLoad] [Line 37] self.view.frame.size.width = 768.000000
2013-01-03 11:23:07.630 Sandbox[11233:11303] -[SBMuViewController viewDidLoad] [Line 38] self.view.frame.size.height = 1004.000000
2013-01-03 11:23:07.631 Sandbox[11233:11303] -[SBContainerViewController viewDidLoad] [Line 37] self.view.frame.size.width = 768.000000
2013-01-03 11:23:07.738 Sandbox[11233:11303] -[SBContainerViewController viewDidLoad] [Line 38] self.view.frame.size.height = 1004.000000
2013-01-03 11:23:07.739 Sandbox[11233:11303] -[SBContainerViewController viewWillAppear:] [Line 46] self.view.frame.size.width = 768.000000
2013-01-03 11:23:07.740 Sandbox[11233:11303] -[SBContainerViewController viewWillAppear:] [Line 47] self.view.frame.size.height = 1004.000000
2013-01-03 11:23:07.741 Sandbox[11233:11303] -[SBZetaViewController viewWillAppear:] [Line 46] self.view.frame.size.width = 0.000000
2013-01-03 11:23:07.741 Sandbox[11233:11303] -[SBZetaViewController viewWillAppear:] [Line 47] self.view.frame.size.height = 0.000000
2013-01-03 11:23:07.742 Sandbox[11233:11303] -[SBMuViewController viewWillAppear:] [Line 46] self.view.frame.size.width = 0.000000
2013-01-03 11:23:07.742 Sandbox[11233:11303] -[SBMuViewController viewWillAppear:] [Line 47] self.view.frame.size.height = 0.000000
2013-01-03 11:23:07.748 Sandbox[11233:11303] -[SBContainerViewController viewWillLayoutSubviews] [Line 62] self.view.frame.size.width = 768.000000
2013-01-03 11:23:07.749 Sandbox[11233:11303] -[SBContainerViewController viewWillLayoutSubviews] [Line 63] self.view.frame.size.height = 1004.000000
2013-01-03 11:23:07.750 Sandbox[11233:11303] -[SBContainerViewController viewDidLayoutSubviews] [Line 69] self.view.frame.size.width = 768.000000
2013-01-03 11:23:07.751 Sandbox[11233:11303] -[SBContainerViewController viewDidLayoutSubviews] [Line 70] self.view.frame.size.height = 1004.000000
2013-01-03 11:23:07.752 Sandbox[11233:11303] -[SBMuViewController viewWillLayoutSubviews] [Line 62] self.view.frame.size.width = 768.000000
2013-01-03 11:23:07.753 Sandbox[11233:11303] -[SBMuViewController viewWillLayoutSubviews] [Line 63] self.view.frame.size.height = 338.000000
2013-01-03 11:23:07.754 Sandbox[11233:11303] -[SBMuViewController viewDidLayoutSubviews] [Line 69] self.view.frame.size.width = 768.000000
2013-01-03 11:23:07.755 Sandbox[11233:11303] -[SBMuViewController viewDidLayoutSubviews] [Line 70] self.view.frame.size.height = 338.000000
2013-01-03 11:23:07.756 Sandbox[11233:11303] -[SBZetaViewController viewWillLayoutSubviews] [Line 62] self.view.frame.size.width = 768.000000
2013-01-03 11:23:07.757 Sandbox[11233:11303] -[SBZetaViewController viewWillLayoutSubviews] [Line 63] self.view.frame.size.height = 669.000000
2013-01-03 11:23:07.758 Sandbox[11233:11303] -[SBZetaViewController viewDidLayoutSubviews] [Line 69] self.view.frame.size.width = 768.000000
2013-01-03 11:23:07.759 Sandbox[11233:11303] -[SBZetaViewController viewDidLayoutSubviews] [Line 70] self.view.frame.size.height = 669.000000
2013-01-03 11:23:07.760 Sandbox[11233:11303] -[SBMuViewController viewWillLayoutSubviews] [Line 62] self.view.frame.size.width = 768.000000
2013-01-03 11:23:07.761 Sandbox[11233:11303] -[SBMuViewController viewWillLayoutSubviews] [Line 63] self.view.frame.size.height = 338.000000
2013-01-03 11:23:07.761 Sandbox[11233:11303] -[SBMuViewController viewDidLayoutSubviews] [Line 69] self.view.frame.size.width = 768.000000
2013-01-03 11:23:07.762 Sandbox[11233:11303] -[SBMuViewController viewDidLayoutSubviews] [Line 70] self.view.frame.size.height = 338.000000
2013-01-03 11:23:07.763 Sandbox[11233:11303] -[SBZetaViewController viewWillLayoutSubviews] [Line 62] self.view.frame.size.width = 768.000000
2013-01-03 11:23:07.764 Sandbox[11233:11303] -[SBZetaViewController viewWillLayoutSubviews] [Line 63] self.view.frame.size.height = 669.000000
2013-01-03 11:23:07.765 Sandbox[11233:11303] -[SBZetaViewController viewDidLayoutSubviews] [Line 69] self.view.frame.size.width = 768.000000
2013-01-03 11:23:07.765 Sandbox[11233:11303] -[SBZetaViewController viewDidLayoutSubviews] [Line 70] self.view.frame.size.height = 669.000000
2013-01-03 11:23:07.768 Sandbox[11233:11303] -[SBAppDelegate application:didFinishLaunchingWithOptions:] [Line 20] Done here.
2013-01-03 11:23:07.772 Sandbox[11233:11303] -[SBContainerViewController viewDidAppear:] [Line 55] self.view.frame.size.width = 768.000000
2013-01-03 11:23:07.773 Sandbox[11233:11303] -[SBContainerViewController viewDidAppear:] [Line 56] self.view.frame.size.height = 1004.000000
2013-01-03 11:23:07.774 Sandbox[11233:11303] -[SBZetaViewController viewDidAppear:] [Line 55] self.view.frame.size.width = 768.000000
2013-01-03 11:23:07.775 Sandbox[11233:11303] -[SBZetaViewController viewDidAppear:] [Line 56] self.view.frame.size.height = 669.000000
2013-01-03 11:23:07.776 Sandbox[11233:11303] -[SBMuViewController viewDidAppear:] [Line 55] self.view.frame.size.width = 768.000000
2013-01-03 11:23:07.777 Sandbox[11233:11303] -[SBMuViewController viewDidAppear:] [Line 56] self.view.frame.size.height = 338.000000

Take a look at the journey MuView goes through. It starts off full screen in viewDidLoad. Then it becomes 0 × 0 in viewWillAppear.  The first time it has the correct size is in viewWillLayoutSubviews.

But again, keep in mind that viewWillLayoutSubviews can get called frequently during a running app.

Custom container UIViewController from UIStoryboard order of operations.

Here is an iPad container view controller with two content view controllers setup in a storyboard:

I added logging to every relevant overridable UIViewController method to show the order that these methods get called upon app startup.

2013-01-03 10:13:38.960 Sandbox[11029:11303] -[SBAppDelegate application:didFinishLaunchingWithOptions:] [Line 16] Entered here.
2013-01-03 10:13:38.968 Sandbox[11029:11303] -[SBContainerViewController prepareForSegue:sender:] [Line 59] childViewController count = 0
2013-01-03 10:13:38.969 Sandbox[11029:11303] -[SBContainerViewController prepareForSegue:sender:] [Line 61] Fired segue = ZetaSegue
2013-01-03 10:13:38.970 Sandbox[11029:11303] -[SBZetaViewController viewDidLoad] [Line 30] Entered here.
2013-01-03 10:13:38.972 Sandbox[11029:11303] -[SBContainerViewController prepareForSegue:sender:] [Line 59] childViewController count = 1
2013-01-03 10:13:38.973 Sandbox[11029:11303] -[SBContainerViewController prepareForSegue:sender:] [Line 61] Fired segue = MuSegue
2013-01-03 10:13:38.974 Sandbox[11029:11303] -[SBMuViewController viewDidLoad] [Line 30] Entered here.
2013-01-03 10:13:38.975 Sandbox[11029:11303] -[SBContainerViewController viewDidLoad] [Line 27] Entered here.
2013-01-03 10:13:38.976 Sandbox[11029:11303] -[SBContainerViewController viewWillAppear:] [Line 34] Entered here.
2013-01-03 10:13:38.977 Sandbox[11029:11303] -[SBZetaViewController viewWillAppear:] [Line 38] Entered here.
2013-01-03 10:13:38.978 Sandbox[11029:11303] -[SBMuViewController viewWillAppear:] [Line 38] Entered here.
2013-01-03 10:13:39.283 Sandbox[11029:11303] -[SBContainerViewController viewWillLayoutSubviews] [Line 48] Entered here.
2013-01-03 10:13:39.284 Sandbox[11029:11303] -[SBContainerViewController viewDidLayoutSubviews] [Line 53] Entered here.
2013-01-03 10:13:39.286 Sandbox[11029:11303] -[SBMuViewController viewWillLayoutSubviews] [Line 52] Entered here.
2013-01-03 10:13:39.287 Sandbox[11029:11303] -[SBMuViewController viewDidLayoutSubviews] [Line 57] Entered here.
2013-01-03 10:13:39.288 Sandbox[11029:11303] -[SBZetaViewController viewWillLayoutSubviews] [Line 52] Entered here.
2013-01-03 10:13:39.289 Sandbox[11029:11303] -[SBZetaViewController viewDidLayoutSubviews] [Line 57] Entered here.
2013-01-03 10:13:39.290 Sandbox[11029:11303] -[SBMuViewController viewWillLayoutSubviews] [Line 52] Entered here.
2013-01-03 10:13:39.291 Sandbox[11029:11303] -[SBMuViewController viewDidLayoutSubviews] [Line 57] Entered here.
2013-01-03 10:13:39.292 Sandbox[11029:11303] -[SBZetaViewController viewWillLayoutSubviews] [Line 52] Entered here.
2013-01-03 10:13:39.294 Sandbox[11029:11303] -[SBZetaViewController viewDidLayoutSubviews] [Line 57] Entered here.
2013-01-03 10:13:39.328 Sandbox[11029:11303] -[SBAppDelegate application:didFinishLaunchingWithOptions:] [Line 20] Done here.
2013-01-03 10:13:39.394 Sandbox[11029:11303] -[SBContainerViewController viewDidAppear:] [Line 41] Entered here.
2013-01-03 10:13:39.395 Sandbox[11029:11303] -[SBZetaViewController viewDidAppear:] [Line 45] Entered here.
2013-01-03 10:13:39.396 Sandbox[11029:11303] -[SBMuViewController viewDidAppear:] [Line 45] Entered here.

Note: the methods view(Did|Will)LayoutSubviews gets called over and over again during regular application execution. Be careful what initialization code you put in there.

2013-01-02

I think I just experienced a bracing/indent style shift within my mind.

And may the sweet Lord have mercy on me.

So I'm swapping back and forth between demonstration code and my own analogous code trying to figure out a bug on my side. As I swapped back and forth I thought to myself, "Clean looking example code always gets crowded and less readable once converted to actual-use code." Then I realized the particular code paragraph on my side that triggered this thought was just a cut-n-paste of the demo code. Uh oh.

So I swapped back and forth a few more times and realized the problem. I use K&R style and the example code uses Allman style. Oh, boy. Maybe, I'm tired or getting too old, but that initial brace all by itself sure looks cleaner to me right now.

I didn't mean to sin. I mean no disrespect to the zealots of my order, but I think I may have just been converted.

2012-12-26

Managed object context in iOS should get passed around not kept in a global object.

I'm baffled why this information is under Core Data Snippets instead of Core Data Programming Guide, but anyway:
When you create a view controller, you pass it the context it should use.... A view controller typically shouldn’t retrieve the context from a global object such as the application delegate....
Thanks to this Stackoverflow question/answer (in a comment on a bad answer).

If you're skilled enough to ignore dogmatic directives of this nature, then good for you, but I'm not (at the time of this writing). I'm logging this entry because I'm sick of over thinking this topic and then researching it repeatedly.

I would like to add that if I have a class that is passed an NSManagedObject, I do not need to also pass in an NSManagedObjectContext because managedObjectContext is a property of every NSManagedObject. In these cases, I simply extract the MOC from the managed object somewhere within the class.