Hardcoding Classes

May 15th, 2014 — 12:58pm

When referring to class object, you can refer to it directly by name. When creating an object, you can do:

[[Foo alloc] init]

There are cases though where you want it to be a bit more dynamic. Say you want a class method which creates an autoreleased instance. You might do something like:

+ (id)fooWithName:(NSString *)name
   return [[[Foo alloc] initWithName:name] autorelease];

The problem with this, of course, is that if you have a subclass, SubFoo, then +fooWithName: will return Foo objects, not SubFoo. To fix this, instead of hardcoding the class, refer to it dynamically:

+ (id)fooWithName:(NSString *)name
  return [[self alloc] initWithName:name] autorelease];

Since this is a class method, self refers to the class object. Now, no matter which subclass you are in, the proper type of instance will be created. And if you are calling class methods from other class methods in the same class:

+ (void)doBlah
  [self doBlech];

Hardcoding the class here would call that specific class’s version of the method, even in subclasses, which is usually undesirable.

If you are in an instance method, you can likewise do something like:

- (id)copyWithZone:(NSZone *)zone
    return [[[self class] alloc] initWithName:[self name]];

Now, this is all well and good. In general, it’s a good idea to to use [self class] instead of hardcoding the name. But let’s take this example:

bundle = [NSBundle bundleForClass:[self class]];

Seems ok. You want the bundle where this class comes from. Or do you? Suppose Foo is in a Framework and SubFoo is in an app using that framework. The above code will return a different bundle for SubFoo than it does for Foo. Depending on what you want to do with that bundle, that can be a bad thing. For instance, finding a nib. Unless it is expected that the subclasses provide their own nib, chances are, the nib you are looking for only exists in Foo’s bundle and the above will fail. The fix? Hardcode the class:

bundle = [NSBundle bundleForClass:[Foo class]]

Here’s an odd case that I ran into some time back. Suppose Foo implements a protocol that has an optional method -bingo. In SubFoo, you implement -bingo but you’re not sure if the superclass (Foo) implements -bingo itself as part of the protocol. If it does, we want to call super but if it doesn’t we can’t. The documentation is silent on the subject so we can’t rely on any particular behavior. How do we check it at run-time?

- (void)bingo
    if ([[[self class] superclass] instancesRespondToSelector:@selector(bingo)])
       [super bingo];

Besides the compiler warning that Foo may not implement -bingo, it looks like it works. If you are a SubFoo instance, it gets the Foo class and asks it if its instances can receive -bingo. Ah, but what happens when we have a subclass of SubFoo called ReallySubFoo. Let’s also say that Foo doesn’t implement -bingo. When the above code is called, from a ReallySubFoo instance, we get a SubFoo class which then gets asked if it responds to -bingo. It does because we implemented it in SubFoo. Problem is there is no super implementation of -bingo and we get a crash. Again, the fix is to hardcode the class:

- (void)bingo
   if ([Foo instancesRespondToSelector(bingo)])
       [super bingo];

In most cases, dynamically getting the class is the right thing to do but don’t do it indiscriminately. Take a moment to think about how it will play out in subclasses. You may be surprised.

Comment » | Cocoa, OS X, Programming

NSConference 6

March 26th, 2014 — 5:24pm

I should have posted about this before but since I already didn’t do that, I’m posting about it now after the fact. Last week I spoke at NSConference 6. I have to say it was an extremely well-run conference. Cheers to Scotty and his crew for putting together a great event. Being a speaker, I was more conscious of how things were run since there were more arrangements regarding travel and such but it was smooth sailing throughout. The staff at the venue were wonderfully attentive as well.

Had a great time. It was nice meeting people whom I might not see at conferences stateside. By the way, to those of you who followed me on Twitter after the conference: prepare to be disappointed as I hardly use it. But I do hope to see you all at future conferences.

This was my first time speaking at a conference. I think it went ok though I can think of a ton of things that didn’t go as planned but that’s mostly in my head (I think). I have to commend Scotty on making a bottle of scotch available on stage, which, as the audience observed, I was not shy about drinking. If there’s any interest, I may do a post on speaking at a conference for the first time.

The topic was “Life Outside the App Store” where I talked about my experiences with being solely outside the MAS. I tried to dispel any notions that apps are not viable outside it. After the talk, I was glad to hear from devs who were also doing their apps without the MAS. Much of the impetus of the talk was to get developers who were iffy about their app because of the MAS to actually realize their vision and know that their app can succeed, MAS or not. Hopefully there were a couple devs in the audience that took that lesson to heart.

In any case, for those that haven’t been, I highly recommend checking out NSConference next year. It’s definitely worth the trip across the pond for us Yanks. For you Europeans, well, you have no excuse since everything over there is like only a two hour drive away.

1 comment » | Conferences, NSConference

Hazel 3.2 with Mavericks tagging support

October 23rd, 2013 — 12:51pm

Apple just released Mavericks yesterday so I’ve released version 3.2 which specifically supports the new tagging feature. You can now create conditions based on a file’s tags and add/set tags via a new action. I’ve done a fairly faithful reproduction of Mavericks tagging UI so it should be a seamless experience.

Like Apple, I’m taking a more conservative approach to tag support as it’s still unclear how people are going to use the feature. One particular feature: the ability to create dynamic tags (i.e. not hardcoded into the rule) is definitely being considered. I’m sure many of you want this feature so here’s the deal: tell me how exactly you would use it. It’s not a question of “why” but of “how” so concrete examples will go a long way into determining how this feature will be fleshed out.

There are fixes in this release as well so even if you aren’t on Mavericks yet (though being free, what are you waiting for?), you should update. Many thanks to the people who beta tested. The beta version should update to the final release but if you run into any problems, contact me.


6 comments » | Hazel, Noodlesoft


July 10th, 2013 — 10:58am

In Hazel 3.1, I added the ability to upload files. Underneath the hood, I used ConnectionKit 2 to do the heavy lifting. It has an API similar to NSFileManager, making it very easy to add FTP, SFTP and WebDAV support without having to deal with the pesky details of those protocols. There were other factors on why I chose it, such as the fact that not only is it actively developed, but done so by people who use it in their own shipping commercial products. And it didn’t hurt that it’s maintained by my friends at Karelia.

If you have used this feature in Hazel, you would have encountered this interface:


It should look a bit familiar. It’s a homegrown, from scratch, implementation of NSOpenPanel made to work on top of ConnectionKit. I felt it important to provide a familiar interface instead of coming up with something new in this case. I did a bit of work to make sure it operated as closely to NSOpenPanel as was reasonable. It has multiple view types (icon, list, and column) and most of the controls you’d expect.

Of course, browsing a filesystem via various network protocols is a different beast so some things had to be done differently. The main thing is that the UI is asynchronous from the network stuff so no beachballing while waiting for responses from the server. The UI should be responsive at all times, even allowing you to cancel the panel at any point. In the upper right, there’s a reload button that changes to a progress indicator to indicate activity and you will see a loading message when trying to fetch the contents of directories that haven’t been loaded yet.

Visually, the biggest difference is the header up top noting which server is being browsed. Also, the sidebar is missing. There aren’t many standard locations that can be put there and I felt that favorite URLs should be managed elsewhere as it didn’t seem likely that users would want to hop from server to server by clicking different entries in the sidebar. The one common directory that I could think of was the home directory and so instead, I gave that its own button (note that not all servers/protocols have such a concept of a home directory and it also depends on what URL you use to connect to the server so YMMV).

Another omission is the search field. Since there’s no notion of Spotlight in any of these protocols, doing an exhaustive search of the remote filesystem would be resource intensive and not very friendly to the servers involved. While I may consider adding it back in to search the current directory, you can get much of the same effect by just typing out the name of the file. Just as in NSOpenPanel, it will end up selecting the entry starting with those characters. I also dropped the Arrange button and the Coverflow view, mainly because I didn’t think people actually used those things. Especially for Coverflow, it wouldn’t be particularly useful since we can’t get file previews without downloading the whole files themselves.

But besides all of that, I think you’ll find it to be a pretty decent facsimile of NSOpenPanel. You might be surprised by how much of NSOpenPanel’s behavior is replicated here, including some features many people don’t know that NSOpenPanel has.

And the resemblance is more than skin deep. CK2OpenPanel (the name of the NSOpenPanel implementation) has a nearly identical API to that of NSOpenPanel. It’s a mostly drop-in replacement for NSOpenPanel so programming to its API should be just as familiar. Why would you care? Well, you should care because I’ve contributed the code for CK2OpenPanel to be included in ConnectionKit. You can see all the code, warts and all. Play around with it. Use it in your own projects. Print it out and wallpaper your home with it. I felt it was the least I could do for all the work that’s been done on the backend. Also, I thought it would be nice if people adopted it so that there was a standard UI for this type of thing.

You can find everything on the ConnectionKit GitHub page. In particular, you want to check out the v2.x-beta branch. Note that there are separate targets/frameworks in the project for the back end (ConnectionKit) and front end (ConnectionKitUI), with the latter dependent on the former. Make sure to check out the README as it should answer a lot of your questions. And if you are interested in contributing to ConnectionKit, please do as there are a bunch of things that need work. S3 support would be nice, for instance.

Last but not least, a big thanks to Mike Abdullah at Karelia for working with me to provide the backend support for this. Rest assured that he will be receiving beers from me at the next conference we both attend.


Comment » | Cocoa, Downloads, Hazel, OS X, Programming, Software, User Interface

Hazel 3.1 is here

June 19th, 2013 — 3:40pm

Fresh from the Noodlesoft Danger Labs is Hazel 3.1 with a bunch of spiffy new things. The two main features this time around are file uploading and matching against file contents. If you don’t use Hazel, maybe these sound a bit abstract to you but for people that use it, it fills a couple big holes in their workflows.

But instead of elaborating on these myself, I’ve been fortunate to have a couple users do the work for me. Demonstrating use of the new file upload facility, Sid O’Neill shows his workflow for resizing and uploading images to his server

Next up is David Sparks (MacSparky and MacPowerUsers Podcast) showing how to match and extract dates out of your files and use them for renaming. Includes a great video so definitely check it out.

Of course, there are a bunch of other things in this release. You can find the full list here.

The response from customers have been great. I’ve gotten a lot of wonderful emails from people so far which has solidified my dedication to the product even more. As mentioned in my last post, I will be looking into Mavericks support, with a particular interest in its tagging feature, in a future release.

Also, in regards to the new upload feature, watch this space in the coming weeks as I’ll have something for you developers.


2 comments » | Business, Downloads, Hazel, Noodlesoft, Software

Things to know about Hazel 3.1

June 11th, 2013 — 12:33pm

If you don’t follow the Twitter feed or forums, then you may not know that Hazel 3.1 is currently in beta and will be released soon(ish). Normally, I’d just announce it when released but this time around there are a few things you should know in preparation.

It will require OS X 10.7 (Lion)

I announced this in the forums last fall. It was a hard decision to make but given the data, it made sense to drop 10.6 support. Note that Hazel 3.0.18 will still continue to run on 10.6.

It will be a free upgrade

Being a non-major release, this update will be free to version 3 license holders.

When 3.1 is released, Hazel’s price will go up

Final price has yet to be determined. If you are considering buying Hazel, you should do so before 3.1 ships as you’ll get it at the lower price now with a free upgrade to 3.1 later.

And about Mavericks…

Apple just announced and seeded it to developers so, Hazel 3.1 won’t have specific support for it. As with every other OS release, I will be adding support for Mavericks in a future release. I usually don’t try and do compatibility fixes this early on since many of the issues end up being on Apple’s end so I like to wait until the seeds stabilize a bit before hunkering down.

And as for that tagging thing, I’m just as excited about it as you are so, trust me, I’m looking into it.

Comment » | Hazel, Noodlesoft, OS X

New Look

February 5th, 2013 — 5:22pm

In the midst of updating software on my server, I decided to update the WordPress theme for my blog. I’ll wait a moment while the excitement wears off…


Still here? I guess I should post some sort of news then since I haven’t posted in a while.

In short, Hazel 3 has been a wonderful success, the result of which is that I’ve been quite busy keeping up. Luckily, I’ve stabilized the 3.0.x series and have started work on version 3.1. There is one big feature which I hope you’ll like plus a bunch of improvements. No timetable as of yet but I suggest checking the forums or Twitter for news on this front. At some point, I will be doing a beta test, so if you’re the gambling type, check those spots in a month or so.

Oh, and it you notice anything wrong with the blog, post a comment to let me know as there might have been things broken in the update.

Comment » | Hazel, Noodlesoft

[self note]

October 4th, 2012 — 11:20am

While working on the most recent patch to Hazel, I stumbled across some code that made me scratch my head. It seemed the code was unnecessary and was causing the bug I was trying to fix. I ended up removing that code while doing the fix thinking I must have been drunk/high/had a gun to my head when I wrote that code originally. Initial tests seemed to confirm it as things were working at first. A couple days later I discovered an older bug had resurfaced. Sure enough, I began to realize why I wrote that odd piece of code back when. I ended up backing out my recent changes and making the fix with the original code intact. I also made another change which was to comment the code explaining why the hell I wrote it that way in the first place.

[self now] != [self future]

One of the nice things about being a solo developer is that you don’t have to deal with the overhead involved when working on a team. You don’t have issues with miscommunication that you would when working with others. Or do you? Like it or not, you are still a team. Sure, you probably don’t need to communicate things with someone else about a current issue, but you, yourself, now, is not the same person as yourself a year from now. You’ll find many times that intentions are lost through the annals of time so documenting things as if there are other programmers on your team is a worthy exercise. Comment your code. Write descriptive commit messages. Edit your wiki. Your future self will thank you for it.

8 comments » | Debugging, Programming

Modus Operandi

June 1st, 2012 — 9:18pm

Apple devs have had a lot to talk about in the past couple years. The App Store has changed the landscape in significant ways. As devs, we’re constantly concerned with issues of pricing, conformance to Apple’s rules, marketing, advertising… I may post about those issues sometime in the future but not now. There’s been a bit of soul searching amongst devs lately and I think it’s important for me to step back and talk about where I’m coming from and what motivates me. What I’m finding in a lot of these discussions is that some people seem to think that the raison d’etre for doing anything commerce related is to make as much money as you can with everything else being peripheral to that. There seems to be a disconnect when talking to people about my business. Where they are talking about profits and growth, I’m thinking in terms of cool things I can add to my product.

Sure, one of my goals is to make money as I want to make a decent living but beyond a certain point, the money doesn’t interest me so much. I find the most important things in my life aren’t bought. Yes, I’m fortunate enough that I make enough now to live comfortably and I understand that that is a luxury but when I look back on my life, I fondly remember what I’ve done and the people I’ve met, not how much money I’ve made.

For me, it’s about the product. I wrote Hazel because I needed it and when I realized other people did as well, I seized the opportunity. Many of the jobs I’ve had in life were working on products that I didn’t use myself. Sure, there were interesting technical challenges and many of the jobs paid well. While at times I was passionate about the work, I was rarely passionate about the product itself. Now that I’m creating something that I do use, it’s a world of difference. Some companies have a policy where employees can work on what they want for a small percentage of their time and what a difference it makes. Now imagine if they could do that 100% of the time.

As a result, my company is just a vehicle for selling the product. I could care less about growing the company into some major concern. If I had to make the choice, I’d fold my company in a heartbeat if it meant my product would live on.

Apparently this will sound strange to a certain segment of people, but I’m also not interested in having a huge number of customers, in and of itself. I don’t really get satisfaction from people who buy the product in a promo or based on hype and don’t use it. I’m not hit-driven. I want users buying my product, not consumers. What really motivates me is when I hear about people that have been using it for years and it’s one the first things they install whenever they get a new machine. It’s when people get excited as I am about new features. It’s when users comes up with unique ways of using the product that I wouldn’t have come up with myself.

And Hazel’s not just some thing that I put out there only to move on to the next thing. I think I’ve shown that Hazel is a long term commitment for me (nearing 6 years). I intend to keep working on it until it doesn’t make sense anymore or external forces somehow shut it down. I haven’t put out any other apps besides Hazel so far, but when I do, I’ll try and make sure they are things I would use myself. I feel that  scratching your own itch can’t be replaced by stock options in terms of the commitment one has to the product. And if it does come down to having to move on, I’ll try my hardest to make sure that the product can live on in some form or another.

I consider myself very lucky. Going indie has been the best career decision I’ve made and I’ve been fortunate that it has panned out for me. And I intend to stay indie. I don’t have an exit strategy and I’m not looking for a big payout. I’m doing what I want and doing it on my own terms. This is it for me and it’s how I want it to be.

2 comments » | Business, Noodlesoft

Syntax Coloring For Fun And Profit

May 29th, 2012 — 9:32am

At the last NYC Cocoaheads meeting, I did a presentation entitled “Let’s Build a Text Editor: A Practical Introduction to the Cocoa Text System.” In it, I basically go through building a code editor from scratch, pointing out how to use the Cocoa text system along the way. I’m not going to reprise the whole thing here. The first part was an introduction to the basics of creating a document-based app and fitting the text system into that and the second part dealt with adding line numbering, which, if you’ve been paying attention at home, I covered here a while back. Instead, I’m going to focus on the third part, which is implementing syntax coloring.

One major aspect of syntax coloring is actually parsing the text. And guess what? I’m not going to cover that here either. There are books you should read on the topic. Like many people during their college years, I learned from the Dragon book though there are probably books more specific to parsing that you can find out there. Keep in mind, though, that you may not have to write as sophisticated a parser as you think. Sometimes, a lexical scanner is all that you need. Just parse the different elements you want to highlight (comments, strings, keywords, etc.) and ignore the syntactic structure. In some cases, this may be enough.

The focus of this article will be getting the Cocoa text system to do the coloring based on what your parser parses. Before we start, you should download the example project as this article refers to it throughout. I’ve created various snapshots at key points to show the progression. If you want, you can go through the various snapshots to see how the app was built up but for the purposes of this article, start at the snapshot called “Version 4”.

The Basic Approach

At the core of Cocoa text system is the NSTextStorage object. It stores the actual text as well as any formatting attributes. Being a subclass of NSMutableAttributedString, NSTextStorage allows you to apply different attributes to ranges of characters. For syntax highlighting, all we care about is the NSForegroundColorAttributeName attribute, which is the attribute that affects the font color.

If you look at the –parse: method in NoodleSyntaxHighlighter, you’ll see that it scans for C-style comments (/*...*/) and string literals ("..."). When it finds the range of a particular entity, it calls -addAttributes:range: on the NSTextStorage to annotate the characters with the appropriate color based on which entity we found. Note that this is how you modify any attributed string; it’s not specific to NSTextStorage. To make sure we keep up with the changes, we implement NSTextStorageDelegate protocol’s -textStorageDidProcessEditing: method. There’s an equivalent NSTextStorageDidProcessEditingNotification though I believe modifying the text storage is only allowed via the delegate method.

If you compile and run at this point, you’ll see that it pretty much works as advertised. We’re done, right? Not exactly. Try loading in a large-ish document. Around a couple thousand lines or so. Start typing really fast. It might depend on your machine, but you’ll find that the typing lags a bit. It seems that modifying the NSTextStorage is not quite as efficient as we’d like. Luckily, there’s a better way to do this.

Using Temporary Attributes

NSLayoutManager has a thing called temporary attributes. These are attributes just like attributes you use on an attributed string, except that they’re, well, temporary. They are more lightweight and designed specifically for cases like this, where the attributes are only used for display and aren’t something intrinsic to the document itself. It’s used for features like spellchecking and other places where you need to make temporary annotations to the text.

Imagine writing a rich text editor. You don’t want to make display-only changes to the NSTextStorage since those changes could end up being saved with the document. Sure, the code editor in this example doesn’t allow rich text but you can see where semantic division lies. The NSTextStorage is your “model” and you don’t want something like syntax highlighting, a “view” feature, to change the model.

In the example project, restore snapshot “Version 5”. This code isn’t much different. It’s adding attributes as before but instead of adding them to the NSTextStorage, they are added via the NSLayoutManager. Now, compile and run it and, if it wasn’t automatically restored from before, load up the large document you used earlier. You should find that it keeps up with your typing this time around.

Now you could stop here but I’d like to take it a step further. You have this nice parser and all. Surely, the ability to pick out different entities in the document is useful for more than just syntax coloring. Maybe you want to add more smarts to your editor. Maybe triple clicks will select the whole comment or string literal instead of just a paragraph/line. Maybe you want to know where code blocks begin and end for code folding. Or maybe you want special tool tips when hovering over different entities.

You can ask the layout manager for the temporary attributes at any character position. Just check for the color that’s set there and deduce which entity (comment or string) it is. Suppose, though, that the user can change the colors in the preferences. If entities are set to be the same color, this method won’t work.

Creating Your Own Custom Attributes

There’s nothing saying that you can’t create and add your own attributes to an attributed string. Sure, only ones defined by Cocoa will be used by the system for display but let’s decide for the moment to annotate our text semantically. Instead of setting the NSForegroundColorAttributeName, we set our own custom attribute to indicate the type of element we’ve found.

Restore snapshot “Version 6” in the example project. At the top of the NoodleSyntaxHighlighter implementation you’ll see that I’ve defined our own attribute (“noodleElementType”) and the two possible values (“comment” and “string”). The -parse: method is the same as before except instead of setting colors, we set our own custom attribute, marking regions of text as comments or strings.

That’s great but how do we get our colors? If you look at the NSLayoutManagerDelegate protocol, you’ll see a method called -layoutManager:shouldUseTemporaryAttributes:forDrawingToScreen:atCharacterIndex: effectiveRange:. What this method does is allow you to substitute different attributes for the ones that are there already. In our implementation, we check what element type we set during the parse phase, look up its color and return it as the NSForegroundColor. So, our NSTextStorage has semantic markup but when displayed, we can substitute in the proper display attributes to get it to color properly.

• • •

Now, there’s one thing I glossed over which is an obvious optimization. Notice how we re-parse the whole document on every change. When you get the text storage notification, you can query it for the range of characters that was changed via its -editedRange method. You can use this information to limit the range of the document you have to re-parse. What you can do is look at what element is there already (from your annotations from the last parse pass) and start parsing from the beginning of that element. You can even tighten it up further by limiting how far it has to parse. I leave implementing this as an exercise for the reader.

As you can see, doing the coloring part isn’t so bad though there are some slightly subtle details to keep in mind. The hard part is the parsing which I’ve conveniently (for myself) left for you to figure out on your own. Enjoy.

And in case you missed the link to the example project above: NoodleEdit.zip

2 comments » | Cocoa, OS X, Programming, User Interface

Back to top