140 km/h

As I write this, I’m traveling at 140kmh (80mph) through the Danish countryside on a train to Nordjylland — specifically the island of Mors. It’s spring, my first since moving to Denmark seven months ago, and the slow rolling hills of Jylland are getting greener. It’s 20:30 (8:30pm) and there is plenty of daylight left.

I was speaking with a colleague of mine earlier in the day, and I’m not sure how we made it to the topic of blogging, but she inspired me to come back here and write a just a bit. Since I first stepped onto foreign soil over a year and a half ago, I’ve had this intense itch to explore new places, and I believe that it’s time I started sharing a bit about where I’ve been as well as where I’m going.

When I moved to Copenhagen, I had only been around the States and Denmark. Since then, I’ve made two short trips — one business, one pleasure — to the United Kingdom and Sweden, and I’ve made a long weekend out of a trip to Berlin. In fact, at Ani‘s behest, I intend to follow this post up with a little about my Berlin trip and all of the wonderfully historically-relevant things I chose to pay the most attention to.

So there it is — a new theme for my blog. Some travels. My travels. Whether it’s the girlfriend or “the guys” that I’m with, I’m hoping I’ll have plenty of things to share while I do my best to be a bonafide globe trotter.

OnATrain

Moments after this post was written! For lack of a better picture!

Reincarnation

I’ve decided to take the blog portion of my site and remove it from immediate focus. This site serves as a small stop on the internet to publish my resume and some choice information about myself. I find myself far too busy with other things to sit down and write what I consider to be proper blog posts about things that run through my head. Generally because when I have what appears to be a good idea for an article, it feels less so when it comes time to write it. That’s how I know if something isn’t worth writing. (I wonder if journalists who crank out truly awful content on command have just learned how to suppress this feeling — or if I’m just horrible at focusing long enough to write something worthwhile.)

So, the focus of this blog has shifted from mostly technical articles to being about whatever I decide to write about. I have ideas for things I’d like to experiment and work on in the coming year. We will see if they ever make it here.

Oh, and I’ve pruned the contents of the blog prior to this post to include only the articles I feel were worth keeping. Anything else was really just rubbish.

TestFlight and Being Busy

So, things have gotten pretty busy here lately. I’ve done a little work on the Beer app, but most of my time has been spent selling off all my stuff and getting things in order for the move.

Speaking of the currently unnamed and unfinished Beer app, I think one of the best decisions I’ve made with it had nothing to do with actually coding it. I’ve been using TestFlight to distribute new test builds to my friends, and I must say I’ve been rather pleased with it. Uploading a build is simple (proper provisioning is still my responsibility) and distributing a build to my team is just as easy. I can even see if they’ve installed or not. The only real problem I’ve had is the same problem anyone has when getting friends to take a small extra step to do something — getting my “testers” signed up and set up. Obviously that’s no fault of TestFlight.

The system we used before involved me making the build and uploading it to a webserver with a link to download OTA. What’s actually happening now with us and TestFlight isn’t much different except it keeps track of my testers and notifies them via email when I’ve put a new build up (along with download link and release notes!). This was previously done manually by me on Facebook chat. How painful. Sure, I could have written an email, but I’d still be doing it every time. Now I’m a click away from knowing if they’ve even installed it (for last night’s build, only one of four testers has actually installed). I could have taken the time to build my own system for distributing the test builds, but TestFlight definitely took the pain out of that for me (and did so for free). I recommend the service highly, and I plan to make time in the future to work with more of its cool… best?…  features (there’s an SDK and automation API!).

Having been so busy recently, I think it reinforces the value of TestFlight as a platform for test distribution (even for a simple hobby app!). There’s less pain and less time invested in achieving better results. That’s valuable to me as an individual and, I’m sure, to almost any team in this business. Now, if I could only get ALL my “testers” enrolled… =)

Web Pedagogy is Failing; Has failed?

Last week a friend of mine majoring in Public Relations came to me asking for help with a little web site project for a Digital Communications class at her university. In general, I find myself very pleased when people around me that are not in my profession find opportunities to learn about topics related to computer science. Something inside me finds these instances very exciting and a certain nurturing instinct manifests itself when I notice that I am going out of my way to make sure they find themselves successful at their endeavors.

Continue reading

Link

My most recent work isn’t using Automatic Reference Counting, though I am considering taking the steps to enable it if there’s time.  I’ve managed to get away with developing some good practices for managing Objective-C memory while also making frequent use of Instruments to check my work.  ARC seems powerful, and I intend on trying it out next go-around. I’m being uncharacteristically easy-migrating about this one… especially versus storyboarding.  Check the link to get a quick, dirty, and solid read on ARC.  It was convincing enough for me.

Transitioning to ARC Release Notes [developer.apple.com]

No more Navigation Controller template in Xcode 4.2?

I use navigation controllers — a lot. If I’m going to prototype something really fast, I’m just going to jam some screens into a navigation controller and let it do its magic.

Push.
Pop.
Push.
Push.
Pop.

Fast.

One could imagine my ire when I installed Xcode 4.2 and discovered the the navigation controller template had disappeared. How could they do this to me? My most beloved default template has been cut from the list of all stars never to be realized again. I guess I have the Storyboard to blame. It really removes the need for this template with all of its drag-n-drop glory, but storyboard is really f-all if I need to support iOS 4 (or just don’t like the feature).

I’m going to tell you how to get the same effect with a few simple changes in Xcode 4.2.

Continue reading

Touch Through Views With Interactive Subviews in iOS

“How do I pass touches through a view without removing the ability to interact with its subviews?”

Setting userInteractionEnabled to NO on a view passes through all touches, but we need our subviews to remain interactive. The code necessary to make this work is very simple, and this technique can also be used for solving another problem — accepting touches for subviews whose bounds extend beyond or exist entirely outside of the superview’s frame.

Understanding hitTest and pointInside

There are two methods in UIView for hit testing. These are pointInside:withEvent: and hitTest:withEvent:. When a view is touched, these two methods work together to detect which view or subview has actually been touched.

HitTest is designed to return the deepest descendant view that the touch was inside of. When hitTest:withEvent: is called for a particular view, it sends a message to pointInside:withEvent: (returns BOOL) on itself. If pointInside returns NO, then hitTest will return nil. Otherwise, hitTest will traverse subviews sending a message to hitTest:withEvent: for each one until one returns a view. If no view is ever returned, hitTest will return self.

We are going to change the behavior of pointInside:withEvent in a way that will not register a touch in an area of the view where a subview doesn’t already exist.

The Code

In our UIView subclass, we create this override:

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    BOOL pointInside = NO;

    // make sure the touch is inside the view
    if(CGRectContainsPoint(self.bounds, point))
    {
        // step through our subviews' frames
        for (UIView *subview in self.subviews)
        {
            // see if the point is inside their frame
            if([subview pointInside:[self convertPoint:point toView:subview] withEvent:event])
            {
                pointInside = YES;
                break;
            }
        }
    }

    return pointInside;
}

In general, if the touch is inside of the frame of any of the subviews (as well as the parent’s bounds), then we consider the point to be inside the view. Otherwise, NO is returned and the touch will “pass through.”

Solving Other Problems Easily

Another way to override pointInside is to allow subviews outside of their superview’s bounds to receive touches. In this example, our parent view will not pass touches through.

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event
{
    BOOL pointInside = NO;

    // step through our subviews' frames
    for (UIView *subview in self.subviews)
    {
        if(!CGRectContainsRect(self.bounds, subview.frame) && [subview pointInside:[self convertPoint:point toView:subview] withEvent:event])
        {
            pointInside = YES;
            break;
        }
    }

    // now check inside the bounds
    if(!pointInside)
    {
        pointInside = [super pointInside:point withEvent:event];
    }

    return pointInside;
}

Notice we have removed the bounds check restricting touches to the parent. Now pointInside steps through the subviews and checks any subviews that are not contained in the parent’s bounds to see if the point is in their frame. If none of the subviews outside the parent’s bounds were hit, then we do the regular old pointInside:withEvent: to see if we’re inside of the parent. Now your views can be interactive outside their superview’s bounds!

Conclusion

It’s not a complicated technique, but some of the help available out there is not complete enough. I saw one solution where the pointInside was implemented as a chain of CGRectContainsPoint() calls logically OR’d inside of an if() that returns YES. I suppose this works, but why risk forgetting about adding a call for your newest/latest/greatest subview? That’s why I’ve written this one up. Any improvements on my method? Let me know in the comments.