Times have changed
Saturday, November 1, 2014
I know this has been said by many of you before, but last night this really hit home for me. The social status of computer geeks has really changed in my lifetime, especially for the younger generation.
For Halloween, my family decided to be superheroes of our own invention. I was the Caped Computer Crusader. My costume included a cape covered in computer parts, a keyboard belt, and an iPad in my chest. The iPad was running a short app I wrote that typed out its own source code in green text on black, including playing typing sounds.
Last night, the costume was a huge hit. When answering the door for trick-or-treaters, I was inevitably told I had the best costume they’d seen. Several kids sat wide-mouthed staring at my chest (not a phrase I figured I’d ever say). Kids loved it. Some adults thought it was awesome as well, while others clearly though I was odd.
I did not expect this reaction. Subconsciously, I was even slightly embarrassed to wear it when the time came. As a kid, I learned that flaunting how big of a geek I was would not lead to social acceptance and that is still somewhat ingrained in me. But the reality that I grew up with is not the reality of today. High school, middle school, and elementary school kids all seem to think that a guy with a Objective-C code printing on his chest is cool.
I know lots of others have written about this before. I understood the concept cognitively, but had not really internalized it until last night.
VoiceOver support for custom text editors
Friday, November 16, 2012
When I originally released Pear Note for iPad a little over a year ago, it did not include VoiceOver support. I had hoped to include it in 1.0, but ended up pushing it off. Soon after release, thanks to some emails from users, I started looking into providing VoiceOver support.
iOS makes it easy to add VoiceOver support for most controls. A button simply needs a label that the system can read. Some different kinds of views are much more complicated, and the most complicated of them all is the text editor. If you use the built-in UITextView class, it handles all of this complication for you. Users can scrub around the text, advance by different granularities using the rotor, and edit the text without needing to see anything.
Pear Note, however, has a custom text editor to provide many capabilities beyond UITextView. It draws text to the screen using Core Text and captures input by complying with the UITextInput protocol. I wanted to have my custom text editor emulate the VoiceOver behavior of UITextView. I searched for protocols to conform to and hacks I could implement to accomplish this, but I came up with nothing. Finally I filed a support incident with Apple, and was told that indeed there was no way for a custom text editor to support VoiceOver. So, I filed a rdar (which was soon closed as a dup) and accepted that I could not do this.
When iOS 6 was in beta, I scoured the API changes to see if they had added support for this. Alas, I found nothing. So, I gave up for another year, hoping iOS 7 might hold a possibility of this. Then, a few weeks after iOS 6 shipped, I was going through my bugs on bugreport.apple.com and noticed something odd. My bug was still closed as a dup, but the bug that it was a dup of was also now closed. I again searched the documentation to find anything new in this area, but found nothing.
So, I submitted another support incident to Apple asking what was going on. It turns out that they had indeed added support for VoiceOver in custom text editors in iOS 6, but they had done so without any changes to the published API. They simply made VoiceOver work with the existing UITextInput protocol that editors must conform to. So, they had added this functionality under the hood and not updated any documentation to tell us about it.
I quickly tested Pear Note and found that while it was completely broken since I'd never tested it, VoiceOver was indeed trying to work. I spent a few days fixing bugs and improving my string tokenizer, and then I had working VoiceOver support in Pear Note.
So, if you're looking to provide VoiceOver support for a custom text editor, it is now possible in iOS 6 despite not being documented anywhere. Just conform to UITextInput and make sure your tokenizer is fully functioning.
Monday, November 12, 2012
A couple years ago, I cataloged my growing photo kit. Since that time, I've expanded a bit and certainly learned a ton about photography. I thought it was about time to catalog my current kit again. So, here goes.
From left to right: Panasonic GH1 body, Panasonic 20mm f/1.7, Olympus 45mm f/1.8, Rokinon 7.5mm f/3.5 Fisheye, Canon FDn 50mm f/1.4, Canon FDn 100mm f/2.0, Panasonic 14-140mm f/4.0-f/5.8, Panasonic 45-200mm f/4.0-f/5.6, Canon FDn 200mm f/2.8 IF, Canon FDn 300mm f/5.6, Olympus E-P1
My main body is a Panasonic GH1. It's a couple years old, but it's still a great body. I've hacked it to increase the video bitrate to around 40Mbps, which means it is a phenomenal video camera. I'm tempted by some of the newer bodies (e.g. the Olympus E-M5) to get faster autofocus and slightly better high ISO performance, but the GH1 is so good in both stills and video that I can't bring myself to change.
I also have an Olympus E-P1, though it rarely gets used. I bought it cheap off eBay. Jen was complaining that she sometimes wanted a camera when I had the GH1 with me elsewhere. I looked at getting her a compact, but the used E-P1 body was just as cheap and takes much better pictures. That said, its screen is awful and its focus is really slow, so Jen does not really use it. I use it occasionally to shoot stills when the GH1 is busy shooting video, though.
These are listed in order of how often I use them. Some of them are native, meaning made for Micro Four Thirds cameras. Others are legacy lenses, meaning made for older camera systems (all my legacy lenses are made for Canon FD). Legacy lenses require a cheap adapter to work, which is not a big deal. The bigger issue is that you have to manually set aperture and focus these lenses. Lacking autofocus can be a big deal, but there are lots of great old lenses out there that fill gaps in the current lens line-up or can be had for less money than their native counterparts.
- Olympus 45mm f/1.8 - This lens is fantastic. It is very sharp and a great focal length for portraits or just things a bit farther away. It also focuses quite quickly, making it a great video lens when the light is dim or you want shallower depth of field.
- Panasonic 20mm f/1.7 - This lens is also fantastic. It is the sharpest of my bunch and a great normal focal length. Its one drawback is that it is pretty slow to focus, so it's not the best for fast action or video.
- Rokinon 7.5mm f/3.5 Fisheye - This is my newest lens, and I'm surprised how much I use it. It's fun to have something so extremely wide. I sometimes use it for fun fisheye pictures, but I also use it as a standard ultra-wide. I combine it with Fisheye-Hemi to straighten things out a bit when I don't want the curvy fisheye effect. It is also great for getting a shot of my daughters when they're sitting right next to me. Note that while this lens is native on Micro Four Thirds, it is also manual like a legacy lens. That said, manually focusing it is easy as the depth of field is huge given its wide focal length.
- Panasonic 14-140mm f/4.0-f/5.8 - I'm more of a prime shooter than a zoom shooter, but I still use this lens a bunch. It's aperture leaves a lot to be desired, but the rest of it is quite good. I find it to be pretty sharp for a superzoom (though not in the same league as the 20 or 45 above). It also focuses extremely fast and quietly, making it a good lens for action and video. Of course, the range of focal lengths it covers is so large that it's quite versatile as well, which can be handy when I'm in a situation that I don't know what I'll be shooting.
- Canon FDn 100mm f/2.0 - As I've filled out my collection, this has become the legacy lens that I still use most commonly. There isn't anything native that is this long and this fast. It's a great lens for capturing something from afar and provides excellent subject isolation.
- Canon FDn 200mm f/2.8 IF - This is a giant lens and I would not dare use it without a monopod or tripod. It takes the attributes of the 100mm (close up from afar and extreme subject isolation) and takes them to the next level. I don't use it much due to its heft, but it is fun to pull out occasionally.
- Panasonic 45-200mm f/4.0-f/5.6 - I got this lens before I had the superzoom and used it a bunch then. These days, I really hardly use it. The superzoom has so much more range on the near side that if I want a bunch of options I use it. If I want something more specific, then I'll use one of the primes. So, this lens gets very little use these days. It's not a bad telephoto zoom, but I find I don't have too much interest in a telephoto zoom.
- Canon FDn 50mm f/1.4 - Before I got the 45, I used this lens a lot. It is a great legacy portrait lens and can be had for very little money. That said, the 45 has autofocus, is sharper, and is better in almost every way. I still put this lens on occasionally, as it can take a great picture, but not very often.
- Canon FDn 300mm f/5.6 - I have only used to shoot the moon. It's not a great lens, but it was very cheap and incredibly long.
You may notice a few lenses from my previous write-up that are missing from this list. I do still have them, but I don't use them. I would sell them if they were worth anything, but they're not.
So, that's what I use from a camera and lens standpoint. I've obviously got a bunch of other gear as well, but that will have to wait for another time. I hope to write up some specific things regarding photography in the coming months, but I wanted to get an overview of what I use out first so you could all see where I'm coming from. If you have any questions about any of this, please don't hesitate to ask.
Does this count?
Sunday, September 23, 2012
I've complained that sandboxing was not ready to be mandated for all Mac App Store apps before, and pointed out that Apple seemed to know this as they had not sandboxed any of their own apps. Well, the recent updates to iPhoto and Aperture are actually sandboxed. At first glance, this seems like evidence that sandboxing has passed a huge milestone. Now sandboxing is capable of handling very complete applications such as these. Sadly, that's not exactly the case.
Michael Tsai dug into the entitlements Aperture is using, and found some alarming things. I'll group these into 3 categories.
The most obvious of these is this one:
Yes, that says that it can read and write all files on the system. This is obviously a large access, but I actually have very little problem with them requesting this. I don't mind it because any 3rd party developer could do the same. Of course, they'd have to make their case to the app reviewer as to why they need this access, but it's a publicly available entitlement that anyone could use. They should work to remove this access, but as a temporary stop-gap until system functionality is fixed it's fine by me.
There are three entitlements listed that are not public. These are:
com.apple.security.library-repair.extensions com.apple.security.library-repair.ostype com.apple.security.temporary-exception.sbpl
It doesn't surprise me that Apple is using private entitlements for their own stuff. I'm not sure what the first two do, but they seem to be specifically created to handle their own apps controlling their internal databases. The third is very different, which I'll discuss next.
The sbpl exception, which Daniel Jalkut wrote about, allows them to drop down to the underlying sandbox policy language and allow whatever they like. This is equivalent to inline assembly, and is a way of Apple admitting that the entitlements mechanism is not complete enough to handle this app. In this particular instance, they grant themselves three abilities beyond what is available via normal entitlements:
(allow file-search) (allow ipc-posix-sem) (allow system-fsctl)
The first of these seems odd, as it seems unnecessary given the broad filesystem access they've already granted themselves via temporary entitlements. The second shows one of the many interprocess communication mechanisms that doesn't work fully with sandboxing entitlements - POSIX semaphores. I'm not sure what the third is for, as fsctl can be a catchall for filesystem controls.
Regardless, the point here is that even with incredibly broad entitlements and private entitlements, they still couldn't sandbox Aperture. They had to use this escape hatch to grant additional capabilities outside of entitlements. 3rd party developers can't use this escape hatch.
A bright spot
None of the above is surprising. Many developers have known how much was missing from the available entitlements, so we all knew Apple wouldn't be able to sandbox their apps without cheating. However, there is one surprising and awesome thing in the entitlements. It's this:
<key>com.apple.security.temporary-exception.mach-lookup.global-name:before:10.8</key> <array> <string>com.apple.AOSNotification-FMM</string> </array>
The cool part is at the end of the entitlement. It ends with a suffix indicating this entitlement should only be applied before Mac OS X 10.8. It looks like Apple has heard our cries and added a mechanism for continuing to use temporary entitlements in older OS versions while removing them in newer ones. This is very important for evolving beyond excessive temporary entitlements. It means an app can claim an excessive entitlement (such as the one for all files at the top of this post) only on the older OS versions that contain bugs requiring such excessive access.
This is not yet public, but I really hope it becomes public. Pear Note requires some excessive sandboxing entitlements on Lion, but I don't want to claim those excessive entitlements forever. This mechanism looks like the perfect solution.
Baltimore Cocoa comeback
Wednesday, July 18, 2012
To Baltimore-area Cocoa developers:
I've missed Baltimore Cocoa (or at least having some sort of Cocoa developer group). So, I've talked to Zach Waugh, Ed Schmalzle, and Chris Ashworth about reviving/reinventing the group. Chris has generously offered for us to meet in the Figure 53 office (@HeyArea53), which will hopefully work a bit better and not result in people getting locked out of get-togethers.
The biggest unknown to me is what format to take. The previous format involved monthly meetings, each with a speaker (e.g. https://vimeo.com/13513818, https://vimeo.com/14316719, https://vimeo.com/14875584). This is similar to the model followed by CocoaHeads groups all over the globe, I believe. This was tough to maintain, as there were only a few of us volunteering to put talks together and we all got busy.
Alternatively, we could just get together and code, helping each other as it is requested, as is done in weekly NSCoder Nights. No formality, no preparation, just show up. Certainly easier to pull off, but possibly less worthwhile.
Or, we could do a hybrid. Or, something else.
The other big unknown is when to meet. We could do the traditional week night. Or, we could do something in the morning or afternoon, as many of us have flexibility in our work day.
My questions to you are:
- Are you interested in being involved in a Baltimore Cocoa group?
- What sort of format would you like to see?
- When would you like to get together?
Please email me directly with your response. Once I get an idea of who's interested, I'll start a conversation among that group to hash things out further. I can do that via email or Glassboard, so let me know which you'd prefer.
Lastly, please spread the word to other Baltimore Cocoa developers you know, and get them to email me to if they're interested.
Wednesday, July 11, 2012
As I wrote last week, I attended and spoke at CocoaConf DC. CocoaConf is a Mac and iOS developer conference that’s held in different locations throughout the year (the next one will be in Columbus, Ohio August 9-11). It was an excellent conference, and I’d encourage any other developers to attend one if you get the chance.
I’m not generally excited about going to conferences as I’m an introverted guy and the idea of spending a few days constantly socializing is off-putting. Combine that with a high dollar and time cost, being away from home, and the usual focus on drinking heavily, and I rarely even consider attending a conference. CocoaConf, however, is a very different sort of conference.
I’m not sure what the actual number was, but I’d guess CocoaConf DC had less than 100 people attending. That’s far smaller than most other conferences, which makes getting to know the other attendees and speakers much easier. Don’t let the small size fool you into thinking there weren’t interesting people there, though. The conference was packed with folks with very impressive backgrounds and technical skills. I’m not sure how they got so many great speakers and attendees for such a small conference, but I’m not complaining.
A common trend in conferences these days is to decrease the technical content and increase the socialization. I get why people would want to do this, but I’m not a fan of this trend. I go to a conference to meet people, but the context of that relationship is technical. I’d much rather chat with someone in the 15 minutes between sessions about HTTP Live Streaming or Core Text than go to a party and make idle chit-chat. CocoaConf did this really well. The first day went from 9:00am to 8:00pm, and was packed with technical content and short breaks between each session for chatting. They even provided all meals so that we didn’t have to waste time looking for food.
The technical content was very good as well. I increased my breadth of knowledge significantly over the course of the two days and look forward to putting my new knowledge to good use. The speakers took their subjects seriously, as did the attendees. There were no speakers apologizing for taking up time when the attendees could be at the bar. They understood that this conference was not just an excuse to have a party, but that we were there to learn and share ideas.
I’m very glad I went to CocoaConf and I plan to return next year. I met several new developer friends (some even in the local area!) and learned about a number of technologies I previously knew nothing about. If you’re a Mac or iOS developer, watch for it to come to your area. I think you’ll find it’s worth your while.
The Wonderful World of Text
Sunday, July 1, 2012
I just got back yesterday from CocoaConf DC, which was a fantastic conference (and that’s coming from a guy who doesn’t generally like conferences). I even got to speak. I’ll post more about the conference soon, but for now I wanted to post my slides and example code for everyone who wanted them.
For those that didn’t make it to the talk, it was about dealing with text in Mac and iOS apps. I started by giving some basic text concepts (e.g. plain vs. rich), covered the two main model classes in Cocoa (NSString and NSAttributedString), talked at a high level about a bunch of the text rendering technologies on the Mac and iOS, and then delved deeper into two of those rendering technologies - the Cocoa Text System on the Mac and Core Text. I was afraid that it wasn’t going well due to how tired some of the attendees looked, but I got a lot of positive feedback afterward so I guess it went well after all. I think people were just tired since it was the last session of the conference.
History repeats itself
Friday, June 1, 2012
Today I find myself remembering the day Fedora Core 2 launched. As you may remember, I used to be an SELinux developer. Today, as sandboxing becomes mandatory on the Mac App Store, I think we may be repeating the mistakes of the past.
Fedora Core 2 was the first major release of a Linux distribution to include SELinux support, though the user had to choose to turn it on during install. It enforced a security policy that was later called the strict policy which confined everything on the system. It was a disaster. Applications broke everywhere. Trying to take a preexisting general-purpose OS and confine all the apps in one action was a bad idea.
Red Hat quickly realized this and changed courses. They created a new security policy they called the targeted policy. For this policy, they left most of the system unconfined and only confined a few (~13) high-payoff apps (apache, mysql, etc.). For Fedora Core 3, they removed the strict policy and replaced it with the targeted policy. Over the course of future releases, they expanded which applications were confined significantly while improving the underlying system to handle those new apps better at the same time.
Today, Apple seems to be taking a similar approach to Fedora Core 2. They're forcing an initial implementation of a security mechanism onto all apps that come from the largest source of apps on the platform. Rather than allowing for organic growth in the wild the way Red Hat did with Fedora Core 3 onward, Apple is choosing to start with everything.
Interestingly, the pain will be felt differently than the pain of SELinux in Fedora Core 2. Apple has chosen to grandfather in any app in the store before today, but no updates (except for minor bug fixes) will be allowed. So, instead of everything breaking on user systems the way they did on Fedora Core 2, things will keep working. They'll just either stagnate due to lack of updates or lose features in future updates in order to work within the incomplete sandboxing technology that currently exists.
I do realize that it probably would not have worked for Apple to force certain Mac App Store apps to sandbox early, and allow others to wait till later the way Red Hat developed the targeted policy. They need consistent rules for all Mac App Store developers. That said, I believe that Apple should have at least led the way by sandboxing all of their own apps sold through the Mac App Store (I believe they have not sandboxed a single one of their 17). This would have showed them a lot of the deficiencies in the current sandboxing mechanism and given them the chance to improve it before forcing it on all of the rest of us.
Oh, and in case you were wondering about Pear Note in specific, I'm still waiting on Apple to get their own frameworks working under sandboxing.
OS X is not ready for sandboxing
Thursday, February 16, 2012
In my previous post, I talked a bit about the high-level approach Apple was taking to sandboxing and the problems therein. Sadly, Apple has not changed their position on this at all yet. So, for now, it appears we have to live with it. I've expected this, so I've been targeting Pear Note for Mac 3 (which just came out in beta) to work in a sandboxed environment. This means I've gotten familiar with dealing with sandboxing, which has led me to the conclusion that OS X is not ready for apps to be sandboxed.
To me as a developer, an operating system is primarily a set of frameworks, of APIs, of functionality provided to applications to let them work. OS X has a long history of providing some great frameworks, from Cocoa to QuickTime and more. These have primarily been developed before the days of sandboxing. So, it's no surprise that many of these made assumptions that cause them to malfunction in a properly sandboxed environment.
The good news is that Apple has a work-around. They call them temporary entitlements, and they allow you to grant your application broad access. So, I figured I would develop Pear Note 3 with a design that could work in a properly sandboxed environment. Then, when I encountered bugs in Apple's own frameworks, I would file those bugs with Apple and in the end grant myself broad temporary entitlements to get Pear Note to work while waiting for Apple to fix their bugs.
And that's what I did. Not surprisingly, I found several bugs. What surprised me was that when I gave myself the broad temporary entitlements, Pear Note still didn't work. One method from QTKit (-[QTMovie writeToFile:] in case you were wondering) fails even with full filesystem access granted. Worse, it does not generate a denial in the system log to give a clue as to why it isn't working. As you can probably guess, writing out audio/video is a pretty important thing for Pear Note, so this wasn't something I could just live without.
So, for now, Pear Note 3 is not sandboxed. If Apple doesn't fix bugs quickly or extend the March 1 deadline out, I'm not sure what I'm going to do. I've already done all the work to make Pear Note ready for sandboxing and would just have to throw a switch to turn it on, but I can't do that until Apple fixes at least this bug.
My point here is not that there's one bug preventing me from sandboxing my app, but that there are lots of bugs preventing developers from sandboxing their apps. Putting aside the debate about whether Apple should be mandating sandboxing and what classes of apps can't be run inside a sandbox, you're left with a bunch of apps that sandboxing was designed for that still can't use it yet because the OS frameworks aren't ready. Pear Note is not unique here, which is why you can look on your system today and see that almost no apps are sandboxed.
It reminds me a lot of when Apple added garbage collection to Objective-C in Leopard. I actually used garbage collection in the first version of Pear Note, but it quickly became apparent that some of Apple's own frameworks (notably QTKit) didn't behave well when used with garbage collection. Thankfully nothing prevented me from throwing out garbage collection until it was ready (which actually never happened). Apple's mandate will prevent us from waiting to use sandboxing until it is ready.
I hope Apple extends the deadline on sandboxing. More than that, I hope that Apple fixes the problems with older frameworks not working with sandboxing. QTKit/QuickTime haven't gotten much love lately, which makes me fearful that their sandboxing bugs may never be fixed.
Crash after opening an NSDocument subclass
Tuesday, January 3, 2012
I've been dancing with this bug for the past day and a half. Now that I found the problem, I thought I'd detail it here for anyone else having the issue to find in the future.
The problem I've found is that, on Lion, after opening a document represented by a NSDocument subclass, the app would crash. This did not occur for any NSDocument subclass, just one in particular. It would report an uncaught exception to me with the following stack trace:
2012-01-02 16:04:03.405 Pear Note[5933:507] An uncaught exception was raised 2012-01-02 16:04:03.406 Pear Note[5933:507] *** -[__NSArrayM insertObject:atIndex:]: object cannot be nil 2012-01-02 16:04:03.409 Pear Note[5933:507] ( 0 CoreFoundation 0x00007fff94eb1286 __exceptionPreprocess + 198 1 libobjc.A.dylib 0x00007fff8dd6bd5e objc_exception_throw + 43 2 CoreFoundation 0x00007fff94e58108 -[__NSArrayM insertObject:atIndex:] + 296 3 AppKit 0x00007fff970e475d __-[NSApplication(NSAppleEventHandling) _handleAEOpenDocumentsForURLs:]_block_invoke_2 + 1089 4 AppKit 0x00007fff971e9ca7 __-[NSDocumentController _openDocumentsWithContentsOfURLs:presentErrors:completionHandler:]_block_invoke_2 + 50 5 Foundation 0x00007fff8f835b95 -[NSBlockOperation main] + 116 6 Foundation 0x00007fff8f7fc788 -[__NSOperationInternal start] + 705 7 Foundation 0x00007fff8f80f9e6 ____NSOQSchedule_block_invoke_2 + 124 8 libdispatch.dylib 0x00007fff961f78ba _dispatch_call_block_and_release + 18 9 libdispatch.dylib 0x00007fff961f972a _dispatch_main_queue_callback_4CF + 308 10 CoreFoundation 0x00007fff94e464dc __CFRunLoopRun + 1724 11 CoreFoundation 0x00007fff94e45ae6 CFRunLoopRunSpecific + 230 12 HIToolbox 0x00007fff918793d3 RunCurrentEventLoopInMode + 277 13 HIToolbox 0x00007fff9188063d ReceiveNextEventCommon + 355 14 HIToolbox 0x00007fff918804ca BlockUntilNextEventMatchingListInMode + 62 15 AppKit 0x00007fff96e273f1 _DPSNextEvent + 659 16 AppKit 0x00007fff96e26cf5 -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 135 17 AppKit 0x00007fff96e2362d -[NSApplication run] + 470 18 AppKit 0x00007fff970a280c NSApplicationMain + 867 19 Pear Note 0x000000010001a172 main + 34 20 Pear Note 0x00000001000021b4 start + 52 )
This is a fun stack trace, as it contains none of my code. But, it at least gave the clue that something was nil that Cocoa couldn't handle. So, I began searching for what this missing object might be.
First I looked for methods I had overridden that might be giving back nil when they shouldn't. That yielded nothing. Then I tried overriding other methods in NSDocument just to see if any of them were returning nil. Nope. Then I moved on to NSDocumentController. Nothing. I couldn't find anything in my code that could be causing the problem.
Finally, I discovered the problem. It wasn't in my code at all, but rather in the xib file for the document. I had not connected (or more likely had disconnected) the window outlet for my NSDocument from the window. This NSDocument subclass often didn't even need a window (as it was used as a temporary object for importing other data types into a proper Pear Note document). So, the simple solution was to connect this outlet to a window. Problem solved.
Of course, this is technically Apple's bug. They shouldn't be crashing because of this, or at least should be checking input to provide a useful error message before crashing. So, being a good citizen I've submitted a bug to Apple. If you'd like to dup it, it's rdar://10638416.