Category Archives: Cocoa

Brent Is Doing It Wrong So You Don’t Have To

My friend Brent Simmons has long been writing at inessential.com. Recently he’s been writing more often, sometimes many times a day, about his experience adding synchronization to my preferred note taking app of choice, Vesper.

Brent writes well. I’ve not asked him but it seems as if this is part of his process. Write the code. Consider the problems. Write them down. Do so publicly so they carry weight.

If you write software then I suggest you keep up with Inessential. It’s a rare treat to have such a plainly expressed narrative of the process behind writing these complex systems.

Objective: Copland 2010

As is our way, like all nerds before us and all the nerds to follow, it is that time where we take a look at the future of our toolset and gnash our teeth.

Ash Furrow kicks us off this time with, “We Need To Replace Objective-C”. Steve Streza follows up and expands in his piece, “Replacing Objective-C and Cocoa”. Brent Simmons then weighed in “On Replacing Objective-C” with his thoughts.

The root of this discussion is best crystallized by John Siracusa’s Avoiding Copland 2010 from back in 2005 (just 35 years after the start of the Unix Epoch). Back in 2011, Siracusa rekindled his argument on an episode of his podcast, Hypercritical. I wrote a follow on piece to Siracua’s episode: Regarding Objective-C & Copland 2010. Personally, I think this entire debate should just be called, “Copland 2010″ because it puts it all in perspective. Here’s a photograph of Siracusa and myself from 2005 soon after he’d posted his original article.

My issue isn’t with the basic premise that if our toolchain stagnates then so does our chosen platform. My issue isn’t with many of the specific suggestions as to what needs improvement. And my issue isn’t with the timeline of doom, the perils of prognostication and it’s certainly not with the authors.

My issue is that I increasingly feel as if we’re being an incredibly poor client approaching a design agency.

We come to the table demanding certain fonts, colours and shapes but we’ve not identified what the actual problem to be solved is. We’ve come with a set of solutions. Each solution fits our notion of what’s wrong and how it can, should and, indeed — must — be implemented, immediately, or we face irrelevancy.

What we want to do is to describe our fantasy gown to wear to the ball, not how the stitching must be applied. Let’s try to communicate what we need at a higher level so we can actually understand the problem space rather than working backwards from the proposed solution space.

In the future our software will need to concisely express operations that may take seconds to complete, if ever, and must do so within strict security boundaries while exploiting the full compute power of the host device.

That’s what our software needs to do. That one sentence captures much of the Copland 2010 argument. Pretty much anything else is venturing off into the weeds. What does concisely mean? What do strict security boundaries entail? Express operations – functionally? (but, still expressed as imperative?) Compiled but concurrent and functional? What if recompiling on the device can use some sort of other computational asset?

My issue is that listing fashionable solutions is small and myopic yet wrapped in the grandeur of a call to revolution.

Define the problem space and attack it.

That’s what design is. You don’t get to pick, “I’m BLUE!” and then make it work. The problem finds you, and then you fix it. All the noise is a string tied between a doorknob and a bad tooth.

Ok, we could automate that. But can we do better by better understanding the problem?

Shadows Around Document Views Under Elastic Scrolling On Lion

To break a trend, here’s something technical.

If you run Safari on Lion and pull down past the top of the page you’ll see a blue linen background and a shadow atop the content view. This is because of the new elastic scrolling that Lion has inherited from iOS. By default NSScrollView does not provide this behaviour for you. Moreover it’s not obvious how to implement it.

Creating a custom NSScrollView will fail — NSScrollView doesn’t report a different frame when a document view is offset by an elastic scroll. Neither does it report a different frame for it’s scroll view under those circumstances. This means that we can’t subclass NSScrollView or NSClipView and implement a -drawRect method that will achieve the shadowed content view we’re after.

Here’s how you do it.

Override the -drawRect method of your ScrollViews’ DocumentView. Save the graphics state. Create a new clip path based on outsetting the view’s bounds intersected by the bounds of the superview. Set the new clip path then draw the shadow in the affected regions. Finally, restore the graphics state.

Here’s a simple example:

-(void) drawRect:(NSRect)dirtyRect; { [NSGraphicsContext saveGraphicsState];

NSBezierPath *newClipPath = [NSBezierPath bezierPathWithRect: NSIntersectionRect( NSInsetRect( [self bounds], -5, -5 ), [[self superview] bounds] )];
[newClipPath setClip];

NSBezierPath *outerPath = [NSBezierPath bezierPathWithRect: [self bounds]];

NSShadow *shadow = [[NSShadow alloc] init];
[shadow setShadowColor: [NSColor blackColor]];
[shadow setShadowBlurRadius: 5];
[shadow set];

[outerPath stroke];
[shadow release];

[NSGraphicsContext restoreGraphicsState];

}

The trick is knowing how things work — the NSClipView that is the super view of your DocumentView has set up a clipping region inside the renderer. It has assumed you’ll not draw outside your bounds. If you want to draw shadows around your DocumentView to look nice during elastic scrolling you’ll need to draw outside your bounds. That’s how you do it.

As a caveat — do not use -setClip unless you know what you’re doing. Use -addClip to decrease the rendering space which is almost always what you want to do. If you find yourself calling -setClip and you’re not 100% sure you know what you’re doing you’ll find that you’ve ended up drawing all over the toolbar and any other UI you’ve got surrounding the view you’ve decided to get cute with.