fíam

(rhymes with liam)

  • My take on UIDatePickerController

    Feb. 23, 2009 at 13:59:59 CET

    I've recently seen some UIDatePickerController implementations around, so I think I'm going to share mine. What are the differences with others?

    • Efficient: The date formatter is just allocated once and the table view never reloads the data.
    • Configurable: The date picker and the date formatter are exposed via properties, so you can configure them however you want to.
    • Flexible: No hardcoded frames. Positions are determined at runtime, so it will work regardless of the view height (e.g. having a tab bar will change the view height).
    • No strings: This code uses no strings, which means you don't need to translate them to every language you support.

    This is the code. Alternatively, you can also download the files: UIDatePickerController.h UIDatePickerController.m

    /* UIDatePickerViewController.h */
    #import <UIKit/UIKit.h>
    
    @class UIDatePickerController;
    
    @protocol UIDatePickerControllerDelegate
    
    @required
    - (void)datePickerControllerCancelled:(UIDatePickerController *)picker;
    - (void)datePickerControllerSaved:(UIDatePickerController *)picker withDate:(NSDate *)theDate;
    
    @end
    
    @interface UIDatePickerController : UIViewController <UITableViewDelegate, UITableViewDataSource> {
        UIDatePicker *_picker;
        UITableViewCell *_cell;
        UITableView *_tableView;
        NSDateFormatter *_formatter;
        id <NSObject, UIDatePickerControllerDelegate> _delegate;
    }
    
    @property(nonatomic, readonly) UIDatePicker *picker;
    @property(nonatomic, readonly) NSDateFormatter *formatter;
    @property(nonatomic, retain) NSDate *date;
    @property(nonatomic, assign) id <NSObject, UIDatePickerControllerDelegate> delegate;
    
    @end
    
    /* UIDatePickerViewController.m */
    #import <QuartzCore/QuartzCore.h>
    
    #import "UIDatePickerController.h"
    
    
    @implementation UIDatePickerController
    
    @synthesize picker = _picker;
    @synthesize formatter = _formatter;
    @synthesize delegate = _delegate;
    
    - (id)init {
        if (self = [super init]) {
            _picker = [[UIDatePicker alloc] initWithFrame:CGRectZero];
            [_picker addTarget:self action:@selector(dateDidChange:) forControlEvents:UIControlEventValueChanged];
            _tableView = [[UITableView alloc] initWithFrame:CGRectZero style:UITableViewStyleGrouped];
            _formatter = [NSDateFormatter new];
    
            _tableView.delegate = self;
            _tableView.dataSource = self;
        }
    
        return self;
    }
    
    #pragma mark properties
    
    - (NSDate *)date {
        return _picker.date;
    }
    
    - (void)setDate:(NSDate *)theDate {
        _picker.date = theDate;
    }
    
    - (void)loadView {
        [super loadView];
    
        self.view.backgroundColor = [UIColor groupTableViewBackgroundColor];
        [self.view addSubview:_picker];
        [self.view addSubview:_tableView];
    
        UIBarButtonItem *cancelButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemCancel
                                                                                      target:self action:@selector(cancel)];
        self.navigationItem.leftBarButtonItem = cancelButton;
        [cancelButton release];
        UIBarButtonItem *saveButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemSave
                                                                                    target:self action:@selector(save)];
        self.navigationItem.rightBarButtonItem = saveButton;
        [saveButton release];
    }
    
    - (void)viewWillAppear:(BOOL)animated {
        [super viewWillAppear:animated];
    
        CGFloat pickerYOrigin = CGRectGetMaxY(self.view.layer.visibleRect) - CGRectGetHeight(_picker.frame);
        _picker.frame = CGRectMake(0, pickerYOrigin, CGRectGetWidth(_picker.frame), CGRectGetHeight(_picker.frame));
    
        CGFloat viewYOrigin = CGRectGetMinX(self.view.bounds);
        CGFloat tableHeight = 65;
        CGFloat tableYOrigin = viewYOrigin + (pickerYOrigin - viewYOrigin - tableHeight) / 2;
        _tableView.frame = CGRectMake(0, tableYOrigin, CGRectGetWidth(self.view.frame), tableHeight);
    }
    
    #pragma mark Table view methods
    
    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
        return 1;
    }
    
    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        return 1;
    }
    
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
        if (_cell == nil) {
            _cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:nil] autorelease];
            _cell.font = [UIFont systemFontOfSize:17.0];
            _cell.textColor = [UIColor colorWithRed:62/255.0 green:78/255.0 blue:111/255.0 alpha:1.0];
            _cell.selectionStyle = UITableViewCellSelectionStyleNone;
        }
    
        _cell.text = [_formatter stringFromDate:_picker.date];
    
        return _cell;
    }
    
    - (void)dealloc {
        [_picker release];
        [_tableView release];
        [_formatter release];
        [super dealloc];
    }
    
    - (void)save {
        [_delegate datePickerControllerSaved:self withDate:_picker.date];
    }
    
    - (void)cancel {
        [_delegate datePickerControllerCancelled:self];
    }
    
    - (void)dateDidChange:(UIDatePicker *)picker {
        _cell.text = [_formatter stringFromDate:picker.date];
    }
    
    @end
    
  • Blango, django-geonames, oauthsp and wapi hosted at GitHub

    Feb. 17, 2009 at 01:22:19 CET

    I've finished moving some of my git repos to GitHub. You can now check Blango, django-geonames, oauthsp and wapi from there. Those are, from now on, the official repos. The old ones at byNotes have already been closed.

  • Leaving byNotes

    Feb. 15, 2009 at 23:18:54 CET

    Well, let me start by explaining all those mails about byNotes I haven't answered in the last few months. Around mid November I got contacted by the recruiting staff of a social network. At that time, I was still working in the project for my degree (computer science students in Spain are required to write a project for the university in order to get the degree) and I wanted to concentrate on it, but I decided to just take the interviews just in case. They finally told me they wanted me to join them and we agreed to continue the negotiations once I had finished my project.

    Fast forward to January, my project is done and christmas holidays are gone, time to reestablish negotiations. Salary is good, schedule is very good (telecommuting 99% of the time) but there's something bad: I must leave byNotes, since management considers it's competing with them.

    It wasn't an easy decision, but it was the best option. byNotes has been very fun, but also such a time drain to me, and I haven't got any single eurocent from it. Plus, I'm a coder, not a designer nor a business guy, and I don't have too much money to spend on it. So I really don't think I could make it profitable.

    As of today, I've been already working for my new employer for some weeks. My name still figures as the domain holder for bynotes.com and in some about pages, but that should change soon. I'm sure the new maintainers will do a good job at keeping the project alive.

    And now comes the interesting part for you, developers. What happens with my free software projects? Well, I'm keeping all of them, but I won't be able to spend some much time working on them. Since I won't be owning byNotes anymore, I'm moving them to GitHub and using LightHouse for ticket tracking. The following is the list of projects I'll be moving to GitHub in the next few days:

    • Django projects

      • Blango
      • wapi
      • django-bundles
      • django-geonames
      • django-geocoding
      • django-storage
      • django-mediafiles
      • django-oauthsp
    • Python projects

      • ffmpeg bindings
    • Cocoa projects

      • My fork of OAuthConsumer (fixing some bugs, implementing some goodies)
      • BNMaps (map framework)