Debugging Autolayout

If you need to debug the constraints that produced any view layout, just hit LLVM, and type:

[cc lang=”objc”]
po [[UIWindow keyWindow] _autolayoutTrace]
[/cc]

This will help you get the Autolayout Trace. Pick up the troublesome view, find its memory address, and then try:

[cc lang=”objc”]
po [0x12341234 constraintsAffectingLayoutForAxis:1]
[/cc]

Note that you should replace 0x12341234 with the memory address of the view you’d like to debug. AxisX = 0, while AxisY = 1.

Props to this extremely useful post.

iOS 8 Autosizing Cells

The latest iOS release (8.0 at the time this was written!) added a new cool feature: autosizing cells. Meaning that we don’t really need to implement tableView:heightForRowAtIndexPath: anymore.

How can we enable this?. Super simple, just add the following snippet:

[cc lang=”objc”]
self.tableView.estimatedRowHeight = SomeConstant;
self.tableView.rowHeight = UITableViewAutomaticDimension;
[/cc]

Now, here’s the deal. iOS 7 still requires tableView:heightForRowAtIndexPath: to be implemented. And if you do implement it, iOS 8 will disregard the Automatic Dimension settings.

Solution?.. import objc/runtime.h, and place this hack in your UITableView’s delegate:

[cc lang=”objc”]
– (BOOL)respondsToSelector:(SEL)aSelector {
if (sel_isEqual(aSelector, @selector(tableView:estimatedHeightForRowAtIndexPath:)) ||
sel_isEqual(aSelector, @selector(tableView:heightForRowAtIndexPath:))) {
return false;
}
return [super respondsToSelector:aSelector];
}
[/cc]

YES. It’s a hack =)

Fixing: StatusBar covering your UIViewController’s view

Ever since iOS 7, if you’re not using a UINavigationController instance, you’ll need to perform a very simple step, in order to prevent iOS’s StatusBar from covering your view:

1. Press Control, click over the “Top Layout Guide”, and drag it upon the troublesome view.
2. You’ll get a small popup. Please, click on “Vertical Spacing”.
3. Edit the new constraint, and update the Constant value, as needed.

Reference here!

CoreData HeavyWeight Migration Issues

We recently hit a pretty severe bug. In one of our apps, users began experiencing token issues after an upgrade.

Bottomline?… the last upgrade had a Heavyweight migration. So far so good, but what happened?. Turns out that the URIRepresentation that can be used to map a NSManagedObjectID, is and is not reliable. Everything is okay, until you perform a heavyweight migration!.

Heavyweight migrations might swizzle your NSManagedObjectID’s. Fix?, create your own primaryKeys. NSUUID helper class is the easiest way to accomplish that.

Reference here!

TextKit + iOS Clipping Bug

I’ve just spent several hours hunting an iOS 8 specific bug. After inserting several new lines into a UITextView (with custom TextKit stack), the newly-added text would not appear.

This is the way our NSTextContainer instance was being initialized

[cc lang=”objc”]
@implementation MyTextView
– (instancetype)init {
SPInteractiveTextStorage *textStorage = [[MyInteractiveTextStorage alloc] init];
NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init];

NSTextContainer *container = [[NSTextContainer alloc] initWithSize:CGSizeMake(0, CGFLOAT_MAX)];
container.widthTracksTextView = YES;
container.heightTracksTextView = YES;

[layoutManager addTextContainer:container];
[textStorage addLayoutManager:layoutManager];

self = [super initWithFrame:CGRectZero textContainer:container];
// …
[/cc]

Now, the interesting part is, specifically, heightTracksTextView = YES.

After several debugging hours, i figured out that iOS 7 was setting, by default heightTracksTextView to NO, after setting the UITextView’s scrollEnabled property.

Guess what? that’s different in iOS 8. Calling setScrollEnabled is not backfiring anymore. For some reason, if you just disable heightTracksTextView, and initialize your UITextView instance with that custom NSTextContainer, any call to the caretRectForPosition method will fail.

By that, i mean, caretRectForPosition will return an invalid position. Workaround? manually disabling heightTracksTextView, right after calling the super initialized.

By the way, for future reference, this post and this one helped me understand i wasn’t alone in Mordor.