End editing in an NSTextField

December 17, 2006

A few weeks ago I read a blog post by Daniel Jalkut on how to commit editing in an NSTextField. The basic idea is when you want to end editing (or just validate the current value), you call [window makeFirstResponder:nil]. This validates the text field’s value, commits the changes, and resigns the text field as the first responder.

I’ve known this for a while, but what I didn’t know was how to restore the first responder afterwards. Although you can get the current first responder by calling [window firstResponder], trying to make this object first responder afterwards does not seem to do anything. What Daniel realized was that this object is not the NSTextField we’re dealing with, but the window’s field editor. You can get a reference to the actual text field you want through the field editor’s delegate.

I rewrote this slightly for my own use, and packaged it up into an NSWindow category. See Daniel’s post for a code snippet with a few more comments.


@implementation NSWindow (NSWindowAdditions)

- (bool)endEditing;
{
	bool success;
	id responder = [self firstResponder];

	// If we're dealing with the field editor, the real first responder is
	// its delegate.

	if ( (responder != nil) && [responder isKindOfClass:[NSTextView class]] && [(NSTextView*)responder isFieldEditor] )
		responder = ( [[responder delegate] isKindOfClass:[NSResponder class]] ) ? [responder delegate] : nil;

	success = [self makeFirstResponder:nil];

	// Return first responder status.

	if ( success && responder != nil )
		[self makeFirstResponder:responder];

	return success;
}

- (void)forceEndEditing;
{
	[self endEditingFor:nil];
}

@end

Again, thanks to Daniel Jalkut for this.

MacHeist software bundle

December 11, 2006

MacHeist is finally wrapping up, and the final bundle is now available. Anyone can purchase the bundle, regardless of whether you’ve participated in MacHeist or not. The cost is $49, and it includes some great apps such as Delicious Library and TextMate. On top of that, 25% of your purchase goes to a charity of your choice. Have a look sometime this week.

Cocoa Blogs community website

December 11, 2006

Scott Stevenson, a well known member of the Cocoa development community, unveiled Cocoa Blogs today. The site is a round-up of some of the best OSX development blogs on the web, highlighting some of the more useful tutorials and posts. I’m looking forward to adding it to my daily reading.

Runner’s Log Beta 1 Available!

December 09, 2006

Runner’s Log, my latest OSX application, is finally available for download. Get more information here, or go directly to the download.

One of my goals from the start was not to spend a lot of time adding extra features, but to get something out to the public where I can see what other people want from it. In other words, I’m really hoping for some good feedback during the beta testing period. Feel free to get in touch with me if you have any comments!

Runner’s Log Screenshot

December 05, 2006

Runner's Log Beta 1 Screenshot

Stay tuned for the first beta. Moving into a new apartment has delayed things a bit, but it’s on its way.

Tara Hunt on Community Involvement

November 27, 2006

Tara Hunt posted a great article on Vitamin today about the role of community in software development. Although written for the web 2.0 app crowd, the same philosophy applies to any platform.

Principle #2. Design to delight There are plenty of great articles on Vitamin that help you with this, but a really good rule of thumb to stick with is that details should not be overlooked. In fact, scaling back on the features (especially upon first launch) and concentrating on making each step of the process delightful (i.e. the language on the error pages, the ease of the signup process, and so on) is essential. There is a great deal of competition in the online application space right now. We certainly can’t compete on price (since most everything is free), so we need to compete on experience. Take a look at every application that you can’t live without and go through each step. What you will most likely discover is that the designers have sacrificed features for detail.

Exactly.

Nike Amp+?

November 27, 2006

It looks like a new Nike iPod product is due to be released soon, according to tuaw.com:

The Nike Amp+ is a wrist band which communicates with your iPod (with Bluetooth, I assume) so that you can start, stop, and browse your tunes. That's not all! It also talks to the Nike+iPod Sport Kit, so you can access information about your run without having to take out your iPod.

As far as I know the Nike+iPod kit has been extremely successful since its release last summer, so it makes sense that Nike would continue to cash in on its success with new products, as well as address some of its shortcomings. ((The official Nike armband for the Nike+iPod kit completely covers your iPod’s screen, making it impossible to do anything other than skip or pause songs without taking it out of the case. Although the iPod Nano’s screen is small enough that you can’t really use it while running anyway.)) I still haven’t really used my Nike+iPod, apart from taking it out for a few laps to see how it works. When you’re running a set course where you already know the distance, the standard iPod stopwatch seems to do a good job on its own. I can see myself using it more and more once products like the Amp+ come out though, I love seeing technology integrated into something “low tech” like running.

Software Pricing & Sales

November 22, 2006

John Gruber talked about software pricing a few times this week, which is a subject I’ve been thinking of lately as well. Finding the “sweet spot” is always a tricky issue, and pricing your application too low can hurt just as much as pricing it too high. The assumption is that if your application costs less than the competition, potential customers might just assume your application is of lower quality, and that extra $10 spent on the competitor’s product is buying them a better application. I’ve actually heard one developer say he wouldn’t even consider purchasing an application under $10; if the seller doesn’t think it’s worth that much, he just assumed the software itself was useless or buggy. You can apply this line of thinking to sales as well; putting your application on MacZot for 60% off may or may not get you a few more sales, but what message is it sending in the long run? This has become more and more of an issue in the past few months, with websites like MacHeist and others giving away free applications by the dozen ((The catch here is that most of these free apps are a one time only deal, and if you want future upgrades and bug fixes, you’ll have to shell out for a real license. It’s more “unlimited shareware” than a real free license.)).

Speaking purely as a greedy consumer, I love free software and I love getting deals. If I think there’s a chance I can get a free application or a 50% discount, I’m probably not going to purchase it right away. Instead, I’ll wait until a sale comes up, decide I can’t live without it, or (more likely) the “new” factor wears off and I stop using that application altogether. Naturally you want to avoid giving your customers this impression, but does that mean you should avoid sales and discounts altogether?

Personally, I believe sales can be effective if done right, and I’ve heard similar opinions on mailing lists and blogs. Here are two ideas that come to mind.

First, instead of a “40% off” sale once every six months, offer an incentive to buy that isn’t really worth waiting for if you like the software. For example, a bundle discount when purchased with another product, or a “buy one get one free” license that the buyer can give away to a friend. If you customer waits until the sale is over to make his purchase, it’s not a big deal; they’re still paying the same amount in the end.

Second, if you are going to offer a price break make it part of your regular pricing. I have a great example of this. When I first tried Menuet, it showed me a little nag screen that included a $3 or $4 discount because I was using Synergy, a competing product. I liked Menuet, and I figured with the discount there was no better time to buy it, so I purchased a license. Since then I’ve seen a similar discount on banner ads at Phill Ryu’s blog and a few other places. If for some reason I did miss out on the original discount, it wouldn’t really discourage me from purchasing Menuet in the future. Every time I see an advertisement or a reminder of Menuet, I see the same enticement. There’s very little sense that I “missed” my chance to get a deal.

Have any experience on the subject? Post your thoughts in the comments.

Windows PowerShell

November 21, 2006

Microsoft released Windows PowerShell 1.0 a week or two ago, and I’ve heard a lot of positive things about it so far. The easiest way to describe PowerShell is to imagine a Unix command line shell, but with all kinds of design hints and functionality from the .NET programming language and Windows administration tools.

I was skeptical at first; I don’t use the command line much at work, and when I do I always have a *nix terminal nearby. The PowerShell “cmdlets” have different names than their DOS or Unix counterparts, so there’s a bit of a learning curve, even though PowerShell uses a pretty standardized naming scheme ((You can, and will probably want to, create aliases for common commands. This is why “ls” works by default.)). Spending some time with it changed my opinion though. The fact that you can run WMI queries right from the command line (normally you would write a .NET or vbscript application to run them) is enough to make me want to learn more. The scripting support seems nice as well, since it supports C# language concepts like foreach and doesn’t rely on text formatting tools to pipe data from one command to another (data is piped in the form of .NET style objects).

The only question now is if PowerShell will be the de-facto shell in future releases of Windows, or if it’ll silently gather dust until it’s forgotten altogether. If you read the PowerShell blog the development team seems pretty excited about integration with all the Microsoft server technologies like IIS and Active Directory, but I really think it could go either way, especially since it was one of the early features cut from Windows Vista.

Leopard Technology Series for Developers Pt. II

November 16, 2006

A new installment of the Leopard Technology Series for Developers was posted today, showcasing Xcode and the rest of the developer tools. Xcode seems to have taken a few hints from Visual Studio for its next release, and the improvements to the code editor and debugger look nice. Perhaps more importantly, speed and code completion are improved (at least they claim) as well. I’ve heard a few complaints in the past about Xcode’s speed from developers working on large projects.

Memory leaks in the .NET 2.0 Ping class

November 14, 2006

As an IT developer, the .NET 2.0 System.Net.NetworkInformation.Ping class is extremely useful. Many times I’ll need to see if a server is reachable, or whether something exists at an IP address before sending another network request (say, a WMI query) with a long timeout delay. Although the Ping class works great (and is much easier than writing your own ping networking code, as in .NET 1.1), it can easily lead to a memory leak in your application. I remember when I first started with C#, there was the feeling that “everything is garbage collected, so that means I don’t have to worry about memory management.” I soon learned that wasn’t true at all, especially with Ping.

Let me post some sample code, illustrating the correct way to send an asynchronous ping. I’ll explain it further below.


private void Refresh( Object sender, EventArgs args )
{
    Ping ping = null;

    try
    {
        ping = new Ping();
        ping.PingCompleted += PingComplete;
        ping.SendAsync( defaultHost, null );
    }
    catch ( Exception )
    {
        ( (IDisposable)ping ).Dispose();
        this.isAlive = false;
    }
}

private void PingComplete( Object sender, PingCompletedEventArgs args )
{
    this.isAlive = ( args.Error == null && args.Reply.Status == IPStatus.Success );
    ( (IDisposable)sender ).Dispose();
}

You can see the Ping class implements the IDisposable interface. IDisposable, if you’re new to .NET, simply means you must call Dispose() before your object can be garbage collected. What makes the Ping class difficult compared to other IDisposable classes is that calling Ping.Dispose() doesn’t actually do anything. It might not be apparent at first, but if you’re working on a monitoring application that sends a new ping every minute (or less), you’ll notice your application’s memory usage creeping up to the hundred of megabytes before long.

The reason behind this is due to some tricky issues with inheritance and interfaces. You see, Ping inherits from System.ComponentModel.Component, which also implements Dispose(). Instead of overriding the inherited Dispose() method to actually dispose of the object, the Ping class explicitly implements the IDisposable Dispose() method. This means you must explicitly call IDisposable.Dispose(), or you’ll end up with the inherited Dispose() method which doesn’t do anything useful at all in this case. You can do this by casting the Ping object to IDisposable, hence the ( (IDisposable)ping ).Dispose() in the example above.

If this seems like a strange design decision, you’re not alone. I’d love to know why Ping implements IDisposable in this way, so feel free to post a comment if you know the answer.

.NET 3.0 and C# 3.0

November 10, 2006

.NET 3.0 was released earlier this week, to very little fanfare. I haven’t done much to prepare for it, and from what I’ve read so far there’s not much reason to unless you’re already building applications for Vista. The Windows Presentation Framework looks neat, but not something I’d use at work, where I do nearly all of my .NET development.

What really caught my eye as I was reading was LINQ, one of the upcoming features in C# 3.0 (which is not included in WinFX 3.0 .NET 3.0, and won’t be released for a while; confused yet?). Here’s a little code sample from the website which illustrates what it’s all about.


using System;
using System.Query;
using System.Collections.Generic;

class app {
  static void Main() {
    string[] names = { "Burke", "Connor", "Frank",
                       "Everett", "Albert", "George",
                       "Harris", "David" };

    IEnumerable expr = from s in names
                               where s.Length == 5
                               orderby s
                               select s.ToUpper();

    foreach (string item in expr)
      Console.WriteLine(item);
  }
}
</code></pre>
This is just a simple data query, but what's exciting is that it's built into the language itself, and you can use it on any object which implements the IEnumerable interface. Here it's an array, but it could just have easily been an MS SQL database or an XML file. Data handling has always been one of .NET's strengths compared to other languages and platforms, and with stuff like LINQ in the works I don't think that's going to change any time soon.