Category Archives: Links

Designing macOS Menu Bar Extras

A great article by Marc Edwards, essentially the “missing manual” for macOS menu bar extras:

Apple’s HIG is great, but it doesn‘t contain much information related to designing menu bar extras. This article aims to provide additional details and context needed to create icons for macOS menu bar extras.

There are a lot of subtleties to get right, and this will help you if you are unfamiliar with the conventions!

Casting Objective-C Message Sends

Mike Ash shares interesting news that the latest Xcode SDKs include a change to the function prototype of Objective-C’s msgSend family of functions. Where objc_msgSend was previously defined in terms of the couple of parameters it usually takes, and with the return type that it sometimes has, it is now declared as taking no parameters and returning no value:

OBJC_EXPORT void
objc_msgSend(void /* id self, SEL op, ... */ )

In practial terms, this will have an impact if you are still using direct objc_msgSend calls anywhere in your code. For example, imagine you have a “transformer” class that is capable of performing a variety of text manipulations on strings. You might have some code that derives a “SEL” programmatically and then messages the transformer to perform the action. Here’s a contrived example:

SEL tSEL = @selector(uppercaseString:);
NSString* upString = objc_msgSend(transformer, tSEL, lowString);

While that would have worked previously (apart from some ARC warnings), on the latest SDKs you’ll get a compile-time error on the objc_msgSend call:

Too many arguments to function call, expected 0, have 3

Obviously, you need to pass the arguments or the invocation will be useless, but how do you do it? Mike’s post has the advice:

Because it still has a function type, you can still cast it to a function pointer of the appropriate type and invoke it that way. This will work correctly as long as you get the types right.

As long as you get the types right … so, how does one do that? Mike includes an example of inline-casting objc_msgSend, but if you need to do this more than once in your code, I think a more elegant way of casting objc_msgSend is by declaring a global variable as a function pointer with the desired types:

#import "objc/message.h"

NSString* (*PerformWithStringReturningString)(id, SEL, NSString*) = (NSString* (*)(id, SEL, NSString*)) objc_msgSend;

Now when you want to invoke “objc_msgSend” on an object that you know accepts and returns a string type, you can do so like this:

NSString* upString = PerformWithStringReturningString(transformer, tSEL, lowString);

No compiler warnings, ARC knows just what to do with all the types, and you have a very clear understanding of what objc_msgSend is expected to do with this particular invocation.

Supporting Dark Mode: On the Web

I wrote several articles about Supporting Dark Mode on the Mac, including one about supporting Dark Mode for in-app web content.

Today, Craig Hockenberry of The Iconfactory writes about the challenge of adapting browser-based web content. That is to say, web page content that you view in an app like Safari. Dark Mode and CSS he talks about changes in the latest Safari Technology Preview:

Luckily the standards groups have been debating this issue for the past several months and have settled on a new media query called prefers-color-scheme. It’s not available in any shipping browser yet, but thanks to the WebKit team, it’s available in the new Safari Technology Preview.

Obviously Dark Mode has a long way to go before it becomes an expected standard around the web, but Apple supporting in on Mac and Safari is a good start. I bet we’ll hear more about Dark Mode on iOS soon, and I’m curious to see if non-Apple platforms also rise to the occasion.

Evergreen Images

Brent Simmons, the original developer of MarsEdit and NetNewsWire, is building a new feed reader app called Evergreen:

Evergreen is an open source, productivity-style feed reader for Macs.

It’s at a very early stage – we use it, but we don’t expect other people to use it yet.

I’ve never been one to shy away from early-stage software, so of course I ran to the GitHub project page, cloned the repository, and built it immediately on my own Mac.

Screenshot of Evergreen about box without a custom icon.

Ahh, the tell-tale sign of a young app: the generic about box. Personally, I like to give apps-in-progress an icon, even if only a placeholder image, as soon as possible. It occurred to me that Apple has done the favor of providing a pretty-darned-suitable image for “Evergreen” in the form of its Emoji glyph of the same name:

🌲

Since I have the source code right here, why don’t I render that tree at a large size in a graphics app, resize it to a million different resolutions, bundle it up and check it in to the Evergreen source base?

Because that’s not nearly as fun as doing it in code. I dove into the Evergreen application delegate class, adding the following function:

private func evergreenImage() -> NSImage? {
	var image: NSImage? = nil
	let imageWidth = 1024
	let imageHeight = 1024
	let imageSize = NSMakeSize(CGFloat(imageWidth), CGFloat(imageHeight))

	if let drawingContext = CGContext(data: nil, width: imageWidth, height: imageHeight, bitsPerComponent: 8, bytesPerRow: 0, space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: CGImageAlphaInfo.premultipliedFirst.rawValue) {

		let graphicsContext = NSGraphicsContext(cgContext: drawingContext, flipped: false)
		NSGraphicsContext.saveGraphicsState()
		NSGraphicsContext.setCurrent(graphicsContext)

		let targetRect = NSRect(origin: NSZeroPoint, size: imageSize)
		NSString(string: "🌲").draw(in: targetRect, withAttributes: [NSFontAttributeName: NSFont.systemFont(ofSize: 1000)])

		NSGraphicsContext.restoreGraphicsState()

		if let coreImage = drawingContext.makeImage() {
			image = NSImage(cgImage: coreImage, size: imageSize)
		}
	}

	return image
}

In summary this code: creates a CoreGraphics drawing context, renders a huge evergreen Emoji glyph into it, and creates an NSImage out of it.

Then from the “applicationDidFinishLaunching()” function:

if let appIconImage = evergreenImage() {
	appIconImage.setName("NSApplicationIcon")
	NSApplication.shared().applicationIconImage = appIconImage
}

Give the newly created image the canonical name, used by AppKit, for looking up the application icon, and immediately change the application’s icon image to reflect the new value. It worked a treat:

EvergreenEmoji

In programming there is usually a hard way, an easy way, and a fun way. Be sure to take the third option as often as possible.

Brent’s Swift Tension

Brent Simmons has been writing new code exclusively in Swift for a while now, and he recognizes omissions from the language that he still anticipates will be hard to overcome as Apple presumably moves toward incorporating Swift into its developer-facing frameworks. The Tension of Swift:

The Objective-C runtime allows AppKit and UIKit to provide some powerful features that I’d hate to do without: the Responder Chain, xib and storyboard loading, KVC, and the undo manager.

A key point he gets at is that however great Swift is, it’s only possible to use it to develop functional iOS and Mac apps because of the Objective C runtime still operating behind the scenes. Both AppKit and UIKit not only lean on the functionality of the runtime, but are designed with the runtime in mind.

Some major design priorities of the Swift language, namely type safety and compile time dependency binding, are at odds with the design priorities of 20 years of evolution in Apple’s frameworks. How and if that disparity will be reckoned by Apple remains to be seen.

I’m optimistic, because the Swift team has already made many concessions to make the language more compatible with the Objective C runtime. It strikes me as possibly non-optimal that a language that strikes the right compromise between Swift’s priorities and Objective C’s would start at the opposite extreme and work its way backwards, but that is what Apple seems to be doing.

Let’s hope they continue in that direction, and surprise us all with how well it all works out in the end.

A Eulogy For Objective-C

I missed Aaron Hillegass’s talk at AltConf earlier this year, but was nudged to take a look at the transcript by Caro’s tweet today linking to the talk’s video page on Realm.

Although I’m 100% sure, based on experience, that Aaron’s talk is a pure delight to watch, I also appreciate that I could jump right in and read a transcript of the talk until I get a chance to watch it. Aaron gives a thought-provoking “eulogy” for Objective-C, in which he celebrates its parentage and its life thus far.

When a guy like Aaron Hillegass gives a history of Objective-C, and speaks to its strengths and weaknesses, you should hang on every word. He covers many of the features that distinguish the language, provides a context for when they were added, and gives examples of key technologies that are enabled by them. He is also aware of the tradeoffs some of these features demand:

Loose typing made a lot of things that were difficult in other languages much easier, or possible. It also made bugs that didn’t exist in other languages possible as well. And you embrace that as an Objective-C programmer. You’re like, “This is a language for smart, pedantic, uptight people, I’m going to be very careful and do the right thing when I’m typing in names.“

I love his hypothetical quote, and think it condenses the feeling a lot of us long-time Objective-C programmers have about the language. We welcome Swift in many respects, but it’s hard to let go of a language whose idiosyncrasies we’ve grown to love, hate, and ultimately make peace with.