Friday, May 22, 2009

Rounding Corners on a UIView

I've been working on an iPhone application for the last couple of months in my spare time. One need I came across that I couldn't find an existing solution for was being able to round the corners on an existing view. Specifically, I need to include a UITableView as a child view of another view, but UITableView has hard corners, which looks wrong on the iPhone. This class will soften the corners.

The RoundedView should be added last to the container that holds it, so it is drawn on top. Events are passed to the next responder. You can set the radius of the corners and the color of the fill. You can also turn on and off which corners are drawn rounded.

Sample Usage
- (void)viewDidLoad {
    [super viewDidLoad];

    UIView *tableView = [self.view viewWithTag:kTableViewTag];
    RoundedView *rv = [[RoundedView alloc] initWithFrame:tableView.frame];
    rv.cornerColor = [UIColor colorBlue];
    rv.radius = 10;
    rv.roundLowerLeft = rv.roundLowerRight = NO;
    [self.view addSubview:rv];
}

RoundedView.h
#import <UIKit/UIKit.h>

@interface RoundedView : UIView {
    int radius;
    UIColor *cornerColor;
    BOOL roundUpperLeft, roundUpperRight, 
         roundLowerLeft, roundLowerRight;
}

@property (nonatomic,retain) UIColor *cornerColor;
@property (nonatomic) int radius;
@property (nonatomic) BOOL roundUpperLeft;
@property (nonatomic) BOOL roundUpperRight;
@property (nonatomic) BOOL roundLowerLeft;
@property (nonatomic) BOOL roundLowerRight;

@end

RoundedView.m
#import "RoundedView.h"

// Private methods for RoundedView
@interface RoundedView() 
-(void) drawRoundedCornersInRect:(CGRect) rect inContext:(CGContextRef) c;
-(void) drawCornerInContext:(CGContextRef)c cornerX:(int) x 
        cornerY:(int) y arcEndX:(int) endX arcEndY:(int) endY;
@end

@implementation RoundedView

@synthesize radius, cornerColor, roundLowerLeft, roundLowerRight;
@synthesize roundUpperLeft, roundUpperRight;

-(id) initWithFrame:(CGRect) frame {
    if (self=[super initWithFrame:frame]) {
        self.cornerColor=[UIColor clearColor];
        self.backgroundColor=[UIColor clearColor];
        self.opaque=NO;
        radius=5;
        roundUpperLeft = roundUpperRight = YES;
        roundLowerLeft = roundLowerRight = YES;
    }
    return self;
}

- (BOOL)pointInside:(CGPoint)point withEvent:(UIEvent *)event {
    // We pretend like no points are inside our bounds so the events
    // can continue up the responder chain
    return NO;
}

-(void) drawRect:(CGRect) rect {
    CGContextRef c = UIGraphicsGetCurrentContext();
    if (c != nil)  {
        CGContextSetFillColorWithColor(c, self.cornerColor.CGColor);
        [self drawRoundedCornersInRect:self.bounds inContext:c];
        CGContextFillPath(c);
    }
}

-(void) drawCornerInContext:(CGContextRef)c cornerX:(int) x cornerY:(int) y
        arcEndX:(int) endX arcEndY:(int) endY {
    CGContextMoveToPoint(c, x, endY);
    CGContextAddArcToPoint(c, x, y, endX, y, radius);
    CGContextAddLineToPoint(c, x, y);
    CGContextAddLineToPoint(c, x, endY);
}

-(void) drawRoundedCornersInRect:(CGRect) rect inContext:(CGContextRef) c  {
 int x_left = rect.origin.x;
 int x_left_center = rect.origin.x + radius;
 int x_right_center = rect.origin.x + rect.size.width - radius;
 int x_right = rect.origin.x + rect.size.width;
 int y_top = rect.origin.y;
 int y_top_center = rect.origin.y + radius;
 int y_bottom_center = rect.origin.y + rect.size.height - radius;
 int y_bottom = rect.origin.y + rect.size.height;
 
    if (roundUpperLeft) {
        [self drawCornerInContext:c cornerX: x_left cornerY: y_top
              arcEndX: x_left_center arcEndY: y_top_center];
    }
 
    if (roundUpperRight) {
        [self drawCornerInContext:c cornerX: x_right cornerY: y_top
              arcEndX: x_right_center arcEndY: y_top_center];
    }
 
    if (roundLowerRight) {
        [self drawCornerInContext:c cornerX: x_right cornerY: y_bottom
              arcEndX: x_right_center arcEndY: y_bottom_center];
    }
 
    if (roundLowerLeft) {
        [self drawCornerInContext:c cornerX: x_left cornerY: y_bottom
              arcEndX: x_left_center arcEndY: y_bottom_center];
    }
}

- (void)dealloc {  
    [cornerColor release];
    [super dealloc];
}

This code is based off of some code I found that draws a rounded rectangle.

Enjoy and let me know if you make an improvements.

Saturday, May 9, 2009

How to Charge for an Application

I'm in a real quandary at the moment. I mentioned a little while ago that I'm working on a new application that is part iPhone app and part web site.

First and foremost, I'm building this application to help patients get better care from doctors. That means I want as many people to use it as possible, because it will mean people are getting better care.

I really don't expect to make a ton of money off of this application, but it would be nice to be re-numerated in some way. At the very least, I need to cover the cost of hosting the web application. I also have a designer who is helping me on this with some expectation of getting paid based on return. I'd like there to be a return to do that.

The quandary that I have is how best to do that.

I've thought about a few options. I'm hoping somebody, somewhere, might be able to give me some feedback on what could work best.

Paid iPhone App, Free Web Site

This model is very appealing because it is the least amount of work for me. Put a price tag on the app and be done with it.

I see a couple of problems with this model, though. First, prices in the app store are so depressed that I doubt I could charge more than a dollar or two for the app. I don't believe my target market is such that I'll make it up in volume.

The second problem is that it will likely reduce the penetration of the application. Remember, one of my goals is to help patients get better health care. I'd hate for a couple of dollars to stand in the way.

Free iPhone App, Basic Ads on Web Site

This would alleviate the concerns about the penetration, as the app is free. However, I'm not convinced that I'll see enough revenue to cover the cost of hosting. Maybe a couple of years ago this would have worked, but today? I'm not so sure.

Free iPhone App, Affiliate Programs on Web Site

This is strongly related to the previous one, but instead of "random" ads, I go find affiliates who will pay better money for more qualified leads. Given my users will be very tightly defined, this is possible.

My concern here is how much time do I have to put into managing affiliate programs? Is this something that is a few days to set up, then self sustaining, or am I going to need to spend time daily on it?

Others

There are other options in there, such as paid app and affiliate programs. There may be other options that I'm not even familiar with. An ideal would be some sort of subscription model, but I have not been able to figure out how that would work.

If you have ideas here, I'd love to hear them. I don't expect anybody to come up with my business plan, but I'd love to here is I missed something.

Thursday, May 7, 2009

Learning is Good for You (I Think)


They say learning is good for your brain. Keep the neurons firing strong, keep the brain nimble, what-have-you.

This has been an interesting year for me. In the last twelve months, I've spent serious time with the following technologies. Some of them, I've never touched before. I think I may be nearing a serious case of brain overload...

  • Groovy

  • Java: Yes, I've used it for 12 years, but it's still a context change, especially with all the libraries.

    • Spring

    • Acegi

    • iBatis

    • JMS

  • HTML: Libraries like jQuery and updates to CSS make it a new game!

    • CSS: It's changed a lot since I last used it!

    • jQuery JavaScript the way it should have been.

  • ReST

  • BungeeConnect: I still wish them the best of luck.

  • Objective C

    • The iPhone SDK

    • Sqlite3 C API

  • Python

    • Django

    • SciPy

    • NumPy

  • Flex

    • Flex Data Services

    • ActionScript 3

  • SQL Sybase is the flavor of the month.



On the one hand, I can't imagine being the type who didn't want to keep learning and trying new things. On the other hand, sometimes it would be nice to not think about this stuff for a while. But I still want to become learn Emacs lisp, Haskell, and Ruby. Oh, and I want to find the perfect project for Erlang, too.

Overall, I think I'm spending too much time in front of my computer. Maybe it's time to write a Photoshop plugin so I can force myself to pull out my camera. :) Hmm, maybe I can write a filter that will parallelize nicely across multiple machines using Erlang.

I might even have time for it if I could reduce my Hacker News (good, insightful comments) and Reddit (a sense of humor) time.
Image provided by Clipart from Clipartheaven.com

Tuesday, May 5, 2009

Pearls From Multiple Languages

I've long been a proponent of learning multiple languages. While I have no empirical evidence, I do believe that it gives a market advantage in understanding how best approach software problems. Peter Norvig agrees and Steve Yegge seems to agree, given the amount of time he spends discussing different languages. I'll try to ride on their laurels, since they are way smarter than I am.

Just saying it is a good thing doesn't mean much if you can't specifically say what is good. Very briefly, here are some thing I've learned as I've learned different languages. I am not saying that I'm an expert at all of these languages; in fact, in many cases, it's the opposite. However, I have spent enough in them to gain some pearls of wisdom for my career. These pearls, taken together, have made me a better developer.

BASIC

I included it, because through it came my first understanding of loops and basic programming constructs: the wonders of GOSUB. Yes, my BASIC pearl was, in fact, GOSUB.

Pascal

Pascal took all those hand-rolled constructs from BASIC and formalized it. My pearl was that, when put into the native constructs of a language, the constructs learned in BASIC were much more useful and usable.

Assembly

My pearl here was understanding how the metal works. Understanding that those thirty variables sitting in your function have to be swapped in and out of a limited number of registers was an important lesson. I wonder now, though, whether that lesson is as important today as it was when I was learning Assembly 15 years ago or if compilers have largely made this learning irrelevant. Still, it surprises me how many people don't understand why 1.1 cannot be represented in a native float type.

Scheme

Once upon a time, it was the college teaching language. To be honest, I had a very difficult time with it. As I struggled to build a Pascal interpreter in Scheme, the pearl I learned was that all languages are equally powerful. It just so happens that some languages are more expressive in ways that are important for particular problems.

C

What can I say? The workhorse of systems programming. As I played with making code compile on various systems, the I learned was that it is possible to write close to the metal in a more abstract, efficient way. The pearl learned was that languages provide many trade-offs, and it is important to understand what you are trading when you choose a language.

C++

C++ was my introduction to object oriented programming. While that could be pearl right there, it wasn't. My pearl came when I realized that a large team could effectively work together using the structure that object oriented applications created. While this is undoubtedly possible with other programming models, it felt right with OO.

Perl

I started using Perl as my first foray into web development. I had played around with shell scripts, awk, and the like for several years; but Perl was light-years ahead of those. My Perl pearl (don't pardon the pun...) was that a scripting language could be not just as powerful as a compiled language, but, in some ways, more powerful.

Visual Basic

I debated admitting to this one, but I did find a pearl here and it's an important one. I was working for a company building CD-ROMs and for this project, time was of the essence. Given the form-building capabilities of Visual Basic, I could build the application very quickly. The pearl: focus on the business objective and not the technology. Even though the technology was...umm...sub-par, the business objective was successfully met.

Java

I have a love-hate relationship with Java right now. I've learned more about how to develop software while writing Java than any other language (because I've written so much of it), but the language has not aged well (unlike the JVM, which has aged marvelously!). Ironically, given how strongly typed Java is, the pearl I learned from Java is that you don't always have to know the type (think Collections before [evil] templates).

JavaScript / ActionScript

I've had a long history with JavaScript, starting with simple browser manipulations to building a significant Flex application. Interestingly enough, my pearl here comes from comparing JavaScript as I've used in the browser to ActionScript that I've used in Flex (both of which are flavors of ECMAScript). The pearl is that, when you've got something good, it is OK to leave it alone. I'm watching ActionScript turn into Java and, frankly, not enjoying it.

Python

It is funny how people love or hate Python, and most of it seems to come from significant white-space. I'd be lying if I didn't admit to needing to get over that as well. Once I overcame that, though, I gained my pearl: If you can write concise, readable code, you can introduce fewer bugs and be more efficient.

Erlang

Erlang is a great language. I wish I had an opportunity to use it more. I honestly believe it could go a long way to reducing the difficulties so many developers have with multi-threaded code and so many systems have with scaling. And that, really, is my pearl: sometimes the tools we use are a variable in how tractable a problem is to solve.

Conclusion

These tid-bits do not encompass all I've learned from these languages. They do highlight what I consider to be key learnings I've taken from them. More important than any single pearl is the combination of unique pearls the whole gives.

I've also learned a few other languages over the years. My latest excursion is Objective C, which I can't say I've used long enough to gather my pearl yet. I'm sure it's in there somewhere, and I'll keep looking until I find it.

My point in this is two-fold: First, no matter what language you are "stuck" with at work, there is value in learning other languages. These pearls will make you rich.

Second, if you haven't found a pearl yet, keep looking. Try to find it, because the exercise of looking for your pearl is where all the value is.

Sunday, May 3, 2009

iPhone and Django Beginnings

Over the last couple of months, I've been working on a new application. I'm not quite ready to talk about the application yet. I have no illusions about it being a smashing success or anything like that (oh, wait, never mind, it is a Google killer ;). I just think it will be easier to show than talk about when it is ready. For the short-term, I'll be talking a little about the technology choices and how I got from start to (eventually) finish.

First, let me say that this is not a game (unlike most iPhone apps :). It is a personally utility that will go in the Medical category. I'm still trying to decide exactly what the revenue model will be. At present, my options are ad-supported (both iPhone app and website) or charging for the app. That's a decision (and discussion) for another day, I suppose.

Learning Objective C for the iPhone has been a lot of fun. It has been a bit of a throw-back to do weird things like memory management again, but the overall novelty of the environment has renewed some of the interest that waned over years of same-language programming. I'm about 75% of the way complete on the application. There's probably 15% more code and 10% design updates.

The iPhone application is just a few screens using a UINavigationController to manage the screens. All data is stored in a Sqlite3 database on the device. I've built a few custom UIViews that are just aggregates of other controls. Data will be transferred from the phone using a JSON and a RESTful API.

The other half of the project is the web site that will visualize the data. After more than a decade of using Java to build web sites, I needed a change. I've been using Python for some time for scripts and testing. This time, I decided it was time to use it for the entire site.

The technologies for the site are Python, Django, Django-Piston (for REST), NumPy, and SciPy (for graphing). The pages will also include jQuery and assorted plug-ins as needed. So far, I'm deepest into Django and Django-Piston; I'm looking forward to the NumPy and SciPy integration.

Over all, it is nice to be enjoying writing code again. The biggest issue that I'm facing now is not technological. I have enough of an idea to be a good "Feature", but not a full "application." I'm left with building a feature and maybe getting some side-cash or trying to build a real application to turn into a business.