KJGridLayout

Xcode's Interface Builder is a pretty good user-interface layout tool, especially for simple situations. However, it is not the best tool for every job. Sometimes you have to write code to dynamically create user interface elements or to move them around as the view is resized.

When you do this, you find that iOS doesn't help you much beyond some rudimentary autoresizing options. While iOS 5 does provide some autolayout features, they are limited, and they don't help at all if you need to support earlier versions of iOS.

I had a need to do a grid-based layout in an iOS app. I hoped to find a grid-layout component like one would find in Android or WPF, but there is no such thing built into iOS.

I also couldn't find any third-party implementations. I found a few posts and samples for making a grid-like UITableView, but I wanted a way to lay out things in a grid in a plain-old UIView.

So I decided to write my own grid-layout thingees for iOS.

The results are the KJGridLayout class and the KJGridLayoutView class, which you can find on GitHub. Check out the README and feel free to use them yourself. I hope someone finds this stuff useful.

MacBooks and Caps Lock and Control

I learned to touch-type over 30 years ago, on an IBM Selectric typewriter. I'm a fast and accurate typist, compared to most programmers. I've always considered typing to be a basic skill that all programmers should take seriously. What goes on in your head is more important than how fast you can type, but the more efficient you are in getting your thoughts into the computer, the better you are going to be at your job.

I've been dismayed at one "feature" of my MacBook: to prevent accidental triggering of the Caps Lock key by incompetent typists, Apple makes it necessary to hold down the Caps Lock key for an extra fraction of a second. If you just tap it quickly, it does nothing. See http://support.apple.com/kb/HT1192 for Apple's explanation. They have also baked this behavior into some of their keyboards: see http://support.apple.com/kb/TS1578.

While I'm sure that many people welcome this feature, I do not. I type quickly and confidently, and my fingers hit the Caps Lock key at the appropriate times without me consciously thinking about it. I hit and release it so quickly that my MacBook ignores it. So when I type "UNIX is awesome!", "Party in the USA!" or "New York, NY", I see "unix is awesome!", "Party in the usa!" or "New York, ny" on the screen.

There is no easy way to disable this feature. When I complain, most people respond "Big deal. We hardly ever use Caps Lock." Well, I do. I've been using it for 30 years, and it has always worked fine. Until Apple decided It Should Just Not Work.

So, I looked into what I could do.

My Python Cheatsheet

Here's another programming-language cheatsheet. It's been a couple of years since I've done any Python programming, and now I'm taking the online CS373: Programming a Robotic Car course, which uses Python for quizzes and homework assignments, so I have to get back up to speed.

As always, this is the information I've found useful in reacquainting myself with a programming language. It may not help you at all.

My Android Development Cheatsheet

If I had my druthers, I'd spend all my time developing mobile apps. I've always been fascinated with pocket-sized computers, and have owned many through the years. Unfortunately, for most of my life such devices have been little more than toys, and so I've had to focus my expertise on writing code for "real computers".

This is true even now, during the explosion of smartphone and tablet usage. I'm one of those dinosaurs who knows how to use C, C++, MFC, ATL, CORBA, UNIX, and other ancient magic, so there are sometimes a few months of old-school development between mobile-development gigs. I write iOS stuff for fun, so I keep those skills sharp, but Android is something I touch only when I'm being paid to do so. Thus, I have to find a way to quickly get back up to speed when the Android work does come.

This is my little refresher for when I arrive back in Android-land. It may not help you at all.

Measuring Elapsed Time in C# Methods

When determining why some damned thing in my .NET programs is taking so damned long, it is useful to be able to look at the elapsed time for various sections of code. The straightforward way to do this is to create an instance of System.Diagnostics.Stopwatch, start it, do the thing, then stop the Stopwatch and print out the elapsed time.

But it gets tedious to keep adding those var stopwatch = new Stopwatch(); stopwatch.Start(); and stopwatch.Stop(); Print(stopwatch.ElapsedMilliseconds); lines all over the place, and it also makes the code less readable, so I made a little class to simplify things.

45

It's another one of those "5" years. I'm now halfway to 90. 90 sounds old, but once upon a time, 45 sounded old too.

The year has not been easy. We lost my maternal grandmother, Ann Woods, in August. I have many good memories of time spent with her up in North Dakota.

My brother announced that he and his wife were getting a divorce. Again, not happy news, but we have to accept it. The end-of-year family get-togethers have seemed incomplete without my sister-in-law.

However, even with those events, this year has been a pretty good one for me.

Professionally, things have been better than usual. I developed Real Professional mobile apps for iPhone/iPad and Android. These apps have over 30,000 users, and they have been well received. Most applications I've developed during my career had only a few dozen users, so this larger reach gives me a sense that I can have some sort of effect on the world.

I've wanted to make iPhone and iPad software since I was 12 years old. Unfortunately, iPhones and iPads didn't exist back then. I'm glad that the devices are finally here, and that they pay me to work with them.

One resolution I've made for the coming year is to spend at least one hour per day working on personal programming projects. I gave up programming "for fun" a few years ago when work was burning me out, but now my interest has been rekindled.

I started meditating almost-daily about 12 months ago. For this, I credit 5by5's Dan Benjamin, who mentioned his meditation practice on several podcasts. I'm no zen master, but I do feel less stress and it's easier to ignore all the little problems in my life. I only have a mental breakdown two or three times a day now.

The optometrist prescribed progressive lenses for me this year. I don't like having old-people glasses, but I'm glad that my corrected eyesight is better. I wish I'd gotten these years ago.

Life with my wife and stepson keeps getting better. Bailey has matured and calmed down a lot over the past year—we actually see him smile once in a while! Pebble hasn't had to spend any time in the hospital this year, which makes us both feel a lot better. Our five dogs are all healthy and happy. Our little cabin in the foothills is still the nicest place I've ever been.

I don't like getting older, but as long as the years keep getting better, I won't complain about it.

Creating .NET Remoting IPC Channels

Yet another C# code snippet. I'm developing a service and an accompanying UI that always run on the same physical box, and it was suggested that I implement the communication between them using .NET Remoting and the IPC channel type, which is a supposedly-easy way to get processes on the same machine to talk to one another.

Of course, it wasn't easy, because if you simply create and register an IpcChannel with default parameters, you get security-related exceptions when you try to do anything with it. You have to delve through documentation and online forums to figure out what underdocumented magic is required to get the stuff to actually work.

There were two obstacles I had to overcome:

  • By default, user-defined types will not be deserialized, to prevent deserialization-based attacks by malicious clients. To disable this "feature", one must set the TypeFilterLevel to Full.
  • My service runs as the LocalSystem user, whereas the client application runs in the logged-in user's security context. By default, the user's account would not be able open the IPC port that the service creates. The fix to this is to set the channel's authorizedGroup to the name of a user group that is allowed to open the port.

So, as usual, the resulting code looks simple, but it took a couple of hours to figure out what had to be written.

Configuring WebDAV and Digest Authentication for Ubuntu

I'm looking at using WPKG as a mechanism for distributing software updates to client workstations. WPKG appears to be a pretty nice system, but it has one big downside: one has to set up a WebDAV-enabled server if the updates are to be pulled from the Internet instead of from a local shared directory. So I've spent a few hours learning the intricacies of setting up WebDAV on my Ubuntu-based Internet server and accessing it from Windows machines. Here's what I learned.

Deserializing Objects from XML in C#

Here's another C# code snippet that takes me way too much time to recreate by just reading the documentation.

This is a simple example of a class that can be serialized to/from XML. In this case the "ServerConfig" XML string can contain a list of servers, looking like this:

<ServerConfig loggingEnabled="1">
  <Servers>
    <Server host="test1.example.com" port="9999" />
    <Server host="test2.example.com" port="8888" />
  </Servers>
</ServerConfig>

The client code can just do "var serverConfig = ServerConfig.FromXmlString(s);" to deserialize it into a ServerConfig object.

(The method that would serialize a ServerConfig to an XML string is left as an exercise for the reader. I rarely need to do that.)

Pretty-formatting XML in C#

I had a need to convert an XML string to a nice, indented format. It was a little more complicated than I expected, so I'm posting this snippet here where I can find it again when I need it.

using System;
using System.Text;
using System.Xml;
using System.Xml.Linq;

static string PrettyXml(string xml)
{
    var stringBuilder = new StringBuilder();

    var element = XElement.Parse(xml);

    var settings = new XmlWriterSettings();
    settings.OmitXmlDeclaration = true;
    settings.Indent = true;
    settings.NewLineOnAttributes = true;

    using (var xmlWriter = XmlWriter.Create(stringBuilder, settings))
    {
        element.Save(xmlWriter);
    }

    return stringBuilder.ToString();
}

Note that this method can throw exceptions for a variety of reasons.

Syndicate content