Unpopular

Social approval is like sweetness — a signal crucial for survival for the majority of humankind’s existence that in our modern era is so prevalent that it can be toxic.

Identifying sweet foodstuffs in our hunter-gatherer era indicated carbohydrate-dense foods. The school of hard evolutionary knocks hard-wired a craving for sweet foods and gives us pleasure when we ingest them. It got us through the winters.

Once beneficial, this trait is now unfortunately out of step with humankind’s newfound ability to manufacture and consume enough sweetness that it literally makes us sick.

Social approval is likewise crucial for survival. Can’t let your “approval rating” drop so low that you’ll be ousted from your tribe and left to forage alone and die childless.

So we do things that garner approval. That’s always been the case. It’s not all bad but it’s not all good.

What’s new is that Internet social networks allows us to crowdsource social approval. As with the large-scale manufacturing of sweetness, our newfound manufacturing of social approval impacts our arthritic social structures.

It’s never been easier to garner social approval from vast numbers of people. And it’s never meant less. But like chasing sweetness’s empty calories, our lizard brains keeps us on the social approval treadmill.

Like sweetness manufacturing, social approval manufacturing can also make us sick. While social approval has incredible upsides including evolutionary advantage, it also commonly leads to shallow groupthink and hindering of true progress.

Don’t misconstrue that I’m arguing that you shouldn’t care at all what others think and approve of. Tribes provide valuable insights and checks on your experiences and evaluations. But social approval is like salt — even if you ban it from your home chances are its pervasiveness in our society will be more than enough to meet your daily requirement.

Unpopular is my Chrome extension that helps dampen the social approval echo chamber. It hides indicators of social status on GitHub (followers, watchers, stars, forks) and Twitter (followers, retweets, favs).

I find Unpopular useful to focus on what I find interesting and important.

I hope you find it useful as well.

unpopular chrome crx Jun 28 2014

JRTranscriptView 1.0

JRTranscriptView is my new purpose-built text view for logging output.

It scrolls like you think it should.

Requires iOS 7+ and Xcode 5.1+.

jrtranscriptview Apr 14 2014

Apple Claims Mogenerator’s Methods

When generating class files to represent your data model’s entities, mogenerator writes a few convenience class methods for you:

+ (id)insertInManagedObjectContext:(NSManagedObjectContext*)moc_;
+ (NSString*)entityName;
+ (NSEntityDescription*)entityInManagedObjectContext:(NSManagedObjectContext*)moc_;

These handy class methods allow you to write something like this:

[MyEntity insertInManagedObjectContext:moc];

to create a new instance. Contrast with:

[NSEntityDescription insertNewObjectForEntityForName:@"MyEntity" inManagedObjectContext:moc];

The mogenerator way is more obvious, less code and not stringly typed.

So that’s the backgrounder.

The good news is Apple likes mogenerator so much that they used it to implement iOS’s PhotoLibraryServices.framework.

The bad news is that PhotoLibraryServices.framework is a private framework.

As a first line of defense against naughty developers submitting apps that use undocumented APIs, Apple sweeps up every selector (method name) defined in all private frameworks and puts them on a special list. The “non-public selectors” list.

Unfortunately this includes the convenience methods mentioned above.

If your App Store submission is found to be use non-public selectors Apple may do nothing, issue a warning or reject your submission altogether.

※ ※ ※

I’m not sure what to do about this.

I could not supply the convenience methods and use Core Data directly like an animal. No! I won’t go back. I can’t go back.

Prefixing the methods (perhaps with an mo_) would provide relief, but only temporarily. When Apple upgrades PhotoLibraryServices to the newer version of mogenerator the cycle would begin anew.

NS is designed for optional class namespacing, but its concepts could be applied to method names as well. Unfortunately at the method level it uglies up the code and confuses Xcode’s code navigator popup menu. Also it would probably require NS_NAMESPACE preprocessor symbol be defined at the target or project level.

Apple could explicitly whitelist mogenerator’s convenience methods but I’m not holding my breath.

The next version of mogenerator could be released under an “Anyone But Apple” license. The idea is to allow everyone but Apple to use mogenerator. I could prefix the methods and issue the mogenerator upgrade knowing Apple couldn’t upgrade and claim the new methods as their own again.

Sadly, this seems like the most promising option.

(Thanks to Tony Arnold for the wording for the title of this post.)

Update Apr 18: First off, a clarification: it appears Apple has never rejected an application using mogenerator’s methods — they’ve only issued warnings.

Now for the good news: a little birdie has told me Apple has whitelisted mogenerator’s methods.

mogenerator appstore Apr 12 2014

Apps I Love: Acorn

I’m surprised I haven’t already written about Acorn under my Apps I Love tag.

Acorn long ago freed me from having to install Photoshop on my Mac. Thank goodness.

I’m not a graphics professional. Acorn does way more than I need it to do. But those “extra” abilities never get in my way. And when I do need to do something a little beyond my common tasks, Acorn has always delivered.

That’s how Mac apps should be.

appsilove acorn Apr 7 2014

AutoLayoutShorthand 1.0

AutoLayoutShorthand is my new(-ish) library for creating and adding Cocoa Auto Layout constraints.

Even with Visual Format Language (VFL), Auto Layout is verbose.

AutoLayoutShorthand strives to highlight the intent of your constraints with a simple literal dictionary-based syntax.

AutoLayoutShorthand also eliminates the need for stringly-typed code, you’ll get compile-time errors when you forget to update a view’s variable name. Xcode features like Edit All in Scope will also work.

AutoLayoutShorthand seamlessly simultaneously supports both iOS and OS X: the same constraint code works with both UIViews and NSViews.

autolayout als autolayoutshorthand Apr 6 2014

Using ownCloud for Contacts and Calendar Syncing (instead of iCloud)

OS X 10.9 removed the ability to sync your contacts and calendars between your Mac and iOS device via direct USB connection. (Though it’s rumored to reappear.)

The removal of this feature was sadly unadvertised. I only noticed when I updated my sister’s address on my Mac and it never showed up on my iPhone. I probably would have put off upgrading to 10.9 if I had known about its removal ahead of time.

Apple’s preferred contact and calendar syncing method is now via its iCloud service.

However, I don’t want to use iCloud since Apple has a poor track record with online services (in both longevity and correctness) and I’d prefer not to upload my private information.

Fortunately both OS X and iOS also support CardDAV for contact syncing and CalDAV for calendar syncing. I decided the time had come for me to make the jump and host these services myself, for myself.

OS X Server has built-in support for workgroup contact and calendar sharing, however I’ve learned through extensive painful experience to avoid it.

Apple open-sourced their Calendar and Contacts Server, and I investigated using it as my personal server. Unfortunately the dependencies were steep (PostgreSQL and Memcached required), Linux support nonexistent and basic instructions about how things work were lacking. I have a sad sordid history of dealing with unsupported Apple software, and I decided against adding CalendarServer to the heap.

Fortunately I read about Alex Payne’s Sovereign project when he announced it and I remember it had contacts and calendar support. I looked into it a bit more, and discovered those services were provided via ownCloud.

So I spun up a new Ubuntu Server 12.04.3 LTS VM on VMWare Fusion on my Mac mini sitting at Mac Mini Vault and installed ownCloud 6:

$ sudo apt-get update
$ sudo apt-get upgrade
$ sudo apt-get dist-upgrade
$ sudo reboot
$ sudo su -
$ wget http://download.opensuse.org/repositories/isv:ownCloud:community/xUbuntu_12.04/Release.key
$ apt-key add - < Release.key
$ echo 'deb http://download.opensuse.org/repositories/isv:ownCloud:community/xUbuntu_12.04/ /' >> /etc/apt/sources.list.d/owncloud.list
$ apt-get update
$ apt-get install owncloud
$ sudo a2enmod headers
# s/AllowOverride None/AllowOverride All/:
$ sudo nano /etc/apache2/sites-available/default
$ sudo service apache2 restart

I think that’s enough to get ownCloud 6 running on Ubuntu Server using its SQLite backend. You can add MySQL to the mix if you think you need it (10+ users, speed, scale).

Then I created a self-signed SSL cert:

$ openssl genrsa -des3 -out myssl.key 1024
$ openssl req -new -key myssl.key -out myssl.csr
$ cp myssl.key myssl.key.org
$ openssl rsa -in myssl.key.org -out myssl.key
$ openssl x509 -req -days 365 -in myssl.csr -signkey myssl.key -out myssl.crt

I installed my self-signed cert on my Mac and iPhone (via Dropbox’s Public URL sharing) and rebooted.

I ended up entering the following URL into Contacts.app:

https://example.com/owncloud/remote.php/carddav/principals/wolf/

And into Calendar.app:

https://example.com/owncloud/remote.php/caldav/principals/wolf/

I was worried what would happen when added these URLs to my iPhone. Would I wind up with a mess of duplicate records? Should I first tediously delete all my existing records, one by one? Fortunately, upon addition of these new data sources, my iPhone offered to delete all existing Calendar and Contact entries. I took the leap of faith and it worked out. Phew.

A final snag is that apparently iOS CardDAV implementation apparently attempts to HTTP GET https://example.com/.well-known/carddav before allowing addition of the CardDAV source to ensure a working service, I guess. ownCloud knows nothing about this, but it’s easy to support what iOS is looking for adding a URL rewrite to your web server config. Here’s my nginx rule:

rewrite ^/.well-known/carddav /owncloud/remote.php/carddav/ redirect;

I’ve been using ownCloud for about four months now and have been happy with it. I’m happy to be able to use cloud syncing without being beholden to a questionable cloud provider.

owncloud sysadmin icloud carddav caldav Mar 28 2014

JREnum 1.1

What’s New:

  • [NEW] Add support for hex constants. (Alex Gray)
  • [NEW] Add support for very simple bit-shifting constants. (rentzsch)

Previously.

jrenum Mar 25 2014

Apple Close-Sources IOUSBFamily

Landon Fuller / @landonfuller:

My IOUSBFamily radar: “The issue is not going to be addressed … We discourage developers to do anything in kernel”: pic.twitter.com/NrifEvOKMn

If this Radar response is accurate, it appears Apple will no longer publish OS X’s IOUSBFamily source code.

apple kext Mar 24 2014

man’s Special Xcode Support

The backstory: I use ManOpen to view Unix man pages on OS X. (schwa has a modernized fork on GitHub.)

It stopped working. Perhaps with 10.9 Mavericks or 10.8 Mountain Lion. I was too busy to track it down.

Today I was trying to look up memcmp's page and it was still broken. I figured Apple just moved where man pages live and I needed to add the new search path to ManOpen's prefs.

However, I couldn’t figure out the right path. I knew man memcmp somehow worked, and I used sudo find / -name 'memcmp.3' to locate where man was finding its page:

/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.9.sdk/usr/share/man/man3/memcmp.3

I added that path to ManOpen and it worked, but I was troubled that 1) it seemed way too specific and 2) I didn’t know how man was finding the page in the first place.

I took a look at /etc/man.conf and /etc/manpaths and /etc/manpaths.d to no avail. They pointed me towards /usr/share/man (which is a ghost town on my system) and /usr/local/share/man (which was also incomplete (it didn’t have memcmp.3)).

So I tweeted:

rentzsch / @rentzsch:

what’s the deal with man pages on OS X 10.9? man memcmp works even though /usr/share/man is a ghost town and /u/l/s/man doesn’t have it

rentzsch / @rentzsch:

looks like it’s coming from /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform /Developer/SDKs/MacOSX10.9.sdk/usr/share/man

rentzsch / @rentzsch:

but I don’t understand how

rentzsch / @rentzsch:

manpaths does list that Xcode SDK path, but I there’s no entry for it in /etc/man*

Kyle Sluder figured it out in short order:

Kyle S. / @optshiftk:

Ah, here’s the magic: opensource.apple.com/source/man/man…

That’s just the patch, man's full code is here (thanks to Tom Harrington).

So Apple’s man calls xcselect_get_manpaths() to dynamically add Xcode-specific paths to man's search paths. Sneaky.

Dave DeLong also informed me about libxcselect.dylib:

Dave DeLong / @davedelong:

my guess: /usr/lib/man links libxcselect.dylib (otool -L) and it’s using that to find your Xcode SDK to look for more man pages

(typo corrected)

libxcselect.dylib is key to Apple’s technique of providing stubs binaries at standard locations that do little else but look up the actual tool locations inside /Applications/Xcode.app and execute them.

For example, let’s look at cc. /usr/bin/cc is just a symlink to /usr/bin/clang, which makes sense in modern terms. Let’s see what it links to:

otool -L /usr/bin/cc
/usr/bin/cc:
    /usr/lib/libxcselect.dylib (compatibility version 1.0.0, current version 1.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1197.1.1)

Your suspicions should be raised by our friend libxcselect.dylib. Also, /usr/bin/clang's size:

$ ls -l /usr/bin/clang
-rwxr-xr-x  1 root  wheel  14224 Oct 24 08:41 /usr/bin/clang

clang is cool but I doubt Apple’s fitting an entire C/C++/Obj-C/Obj-C++ compiler into 14K. Let’s take a look at what it actually does:

$ otool -tV /usr/bin/clang
/usr/bin/clang:
(__TEXT,__text) section
_main:
0000000100000f5e    pushq   %rbp
0000000100000f5f    movq    %rsp, %rbp
0000000100000f62    movq    %rsi, %rax
0000000100000f65    leal    0xffffffffffffffff(%rdi), %esi
0000000100000f68    leaq    0x8(%rax), %rdx
0000000100000f6c    leaq    0x27(%rip), %rdi ## literal pool for: clang
0000000100000f73    xorl    %ecx, %ecx
0000000100000f75    callq   0x100000f7a ## symbol stub for: _xcselect_invoke_xcrun

It’s entire implementation is pretty much just

return xcselect_invoke_xcrun("clang");

FWIW I found the real clang binary in

/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang

It’s 28MB.

Anyways, I’m sticking with just adding that Xcode SDK path to ManOpen for now, but perhaps someone will enhance ManOpen to call automatically manpath instead of having to explicitly specify such paths. ManOpen is open source (hint hint).

Update: Chris Cieslak has immediately stepped into the breach and added a quick and dirty fix to ManOpen. Thanks, Chris.

xcode man manpath Feb 4 2014

ARC’s Fast Autorelease

ARC has a trick that keeps returned objects out of autorelease pools if both the caller and callee are ARC.

But how does that work? One of the features of ARC is that old compiled-before-ARC code (MRC code) can call ARC code and vice-versa. But if ARC code doesn’t put a returned object in an autorelease pool that MRC code is expecting, then the object would just leak.

So ARC-ified clang code emits this function call when returning an object: objc_autoreleaseReturnValue(id).

If you look at objc_autoreleaseReturnValue's implementation, it calls callerAcceptsFastAutorelease(). Even if you don’t read x86_64 or ARM assembly, the code’s comment is straight-forward:

/*
  Fast handling of returned autoreleased values.
  The caller and callee cooperate to keep the returned object 
  out of the autorelease pool.

  Caller:
    ret = callee();
    objc_retainAutoreleasedReturnValue(ret);
    // use ret here

  Callee:
    // compute ret
    [ret retain];
    return objc_autoreleaseReturnValue(ret);

  objc_autoreleaseReturnValue() examines the caller's instructions following
  the return. If the caller's instructions immediately call
  objc_autoreleaseReturnValue, then the callee omits the -autorelease and saves
  the result in thread-local storage. If the caller does not look like it
  cooperates, then the callee calls -autorelease as usual.

  objc_autoreleaseReturnValue checks if the returned value is the same as the
  one in thread-local storage. If it is, the value is used directly. If not,
  the value is assumed to be truly autoreleased and is retained again.  In
  either case, the caller now has a retained reference to the value.

  Tagged pointer objects do participate in the fast autorelease scheme, 
  because it saves message sends. They are not entered in the autorelease 
  pool in the slow case.
*/

To summarize, callerAcceptsFastAutorelease() inspects the caller’s instructions and uses it to determine at runtime whether it needs to actually put the returned object in the autorelease pool or if it’s on the same ARC-team and it can be skipped (speeding things up).

Clever girl.

※ ※ ※

Follows is the tweet-stream that led this posting, much thanks to David Smith for the education.

rentzsch / @rentzsch:

part of me still wants to write [NSMutableArray array] instead of [NSMutableArray new] since maayybbeee this code will be MRC one day again

David Smith / @Catfish_Man:

@rentzsch should be just as efficient under arc, so go for it :)

rentzsch / @rentzsch:

@Catfish_Man I think +array still hits the autorelease pool under ARC

David Smith / @Catfish_Man:

@rentzsch I’ll try to remember to check today and file a bug if it does

rentzsch / @rentzsch:

@Catfish_Man I love it but messaging sending is a serious conceptual barrier toward optimization

David Smith / @Catfish_Man:

@rentzsch aye. I got [NSDate date] fixed to not hit the ar pool though :)

rentzsch / @rentzsch:

@Catfish_Man very interesting! I’m not sure how that’s possible unless you’re playing some sort of cacheing magic

David Smith / @Catfish_Man:

@rentzsch ah didn’t realize you weren’t familiar with the general mechanism here. ARC can elide most autoreleased returns. Lemme find a link

David Smith / @Catfish_Man:

@rentzsch grep for callerAcceptsFastAutorelease here: opensource.apple.com/source/objc4/o…

mrc arc autorelease Jan 30 2014