iPhone dev memoramda #2

January 4th, 2011

View controllers can load a view from a nib with

-(id) initWithNibName:bundle:

OR

-(void) loadView

. They CAN’T be used at the same time. Setup happening just once should occur in

-(void) loadDidLoad

but beware: bounds data are not yet set. Otherwise

-(void) viewWillAppear

should be’ used.

iPhone dev memoranda #1

January 3rd, 2011

IBOutlet views should be declared as retained properties, stnthesized and released in viewDidUnload and dealloc methods of their controllers by setting their values to nil.

@interface MyController : NSObject
{
   MyView *myView;
}
@property (retain) IBOutlet MyView *myView;
@end

@implementation MyController
@synthesize myView;
-(void) releaseViews
{
   self.myView=nil;
}
-(void) viewDidUnload
{
   [self releaseViews];
}
-(void) dealloc
{
   [self releaseViews];
....
}

Cocoa Dev Quick NotesNSTableView: Drag & Drop and Edit Menu Validation

March 14th, 2010

All methods are updated to Mac OS 10.6.

Drag & Drop

Follow this steps to use drag & drop in NSTableView:

  • Create a custom view controller class MyTableViewController based on NSViewController
  • Add a new XIB based on an empty view and assign the newly added class to its File’s Owner
  • Drop in a NSTableView and assign its dataSource outlet to File’s Owner
  • Use Core Data for populating the table
  • Define a custom pasteboard type (only if you aren’t using standard types):
    NSString *MyCustomPBoardType = @"MyCustomBoardType";
    
  • In your view controller’s awakeFromNib method add the following lines:
    NSArray *dragTypes = [NSArray arrayWithObjects: MyCustomPBoardType,nil];
    [myTableView registerForDraggedTypes:dragTypes];
    [myTableView  setDraggingSourceOperationMask:NSDragOperationCopy forLocal:NO];
    
  • Implement the tableView:writeRowsWithIndexes:toPasteboard: method to handle dragging and tableView:validateDrop:proposedRow:proposedDropOperation: and tableView:acceptDrop:row:dropOperation: to handle dropping:
    - (BOOL)tableView:(NSTableView *)tv writeRowsWithIndexes:(NSIndexSet *)rowIndexes toPasteboard:(NSPasteboard*)pboard
    {
    	NSArray	*selectedObjects = [myArrayController selectedObjects];
    	[pboard declareTypes:[NSArray arrayWithObjects:MyCustomPBoardType,nil] owner:self];
    	for( NSManagedObject *object in selectedObjects )
    		[pboard writeObjects:[NSArray arrayWithObject:[[object objectID] URIRepresentation]]];
    
        return YES;
    }
    
    - (NSDragOperation)tableView:(NSTableView*)tv validateDrop:(id )info proposedRow:(int)row proposedDropOperation:(NSTableViewDropOperation)op
    
    {
    	if ([info draggingSource] == tv)
    	{
    		[tv setDropRow:row dropOperation:NSTableViewDropAbove];
    		return NSDragOperationNone;
    	}
    	else {
    		return NSDragOperationCopy;
    	}
    
        return NSDragOperationNone;
    }
    
    - (BOOL)tableView:(NSTableView *)aTableView acceptDrop:(id )info row:(int)row dropOperation:(NSTableViewDropOperation)operation
    {
    	BOOL	acceptDrop = NO;
    
    	if( [info draggingSource] == aTableView )
    		return acceptDrop;   // it allows only drops from external sources
    
    	NSArray			*classes = [[NSArray alloc] initWithObjects:[NSURL class], nil];
    	NSDictionary	*options = [NSDictionary dictionary];
    	NSArray			*copiedItems = [[info draggingPasteboard] readObjectsForClasses:classes options:options];
    	if( !copiedItems )
    		return acceptDrop;
    
    	// do whatever you like with copied items
    	NSArray	*currentEvents = [objectsArrayController selectedObjects];
    	for( NSManagedObject *event in currentEvents )
    	{
    		NSSet	*attendants = [event valueForKey:@"attendants"];
    		NSMutableSet	*newAttendants = [[[NSMutableSet alloc] initWithCapacity:0] autorelease];
    		[newAttendants setSet:attendants];
    		for( NSURL *copiedObject in copiedItems )
    			[newAttendants addObject:[self.managedObjectContext objectWithID:[[self.managedObjectContext persistentStoreCoordinator] managedObjectIDForURIRepresentation:copiedObject]]];
    		[event setValue:newAttendants forKey:@"attendants"];
    		acceptDrop = YES;
    	}
    	return acceptDrop;
    }
    

Edit Menu Validation

The simplest way to validate cut:, copy: and paste: actions for rows in a table without subclassing NSTableView is to delegate the view controller.

  • The responder chain will ask first the NSTableView object and then will look for the next responder. So it’s simple to set the view controller as the next responder in your awakeFromNib method:
    [myTableView setNextResponder:self];
  • Now implement the request actions in your view controller:
    - (IBAction)copy:(id)sender
    {
    ...
    }
    
    - (IBAction)cut:(id)sender
    {
    ...
    }
    
    - (IBAction)paste:(id)sender
    {
    ...
    }
    // and whatever you like
    
  • Validate the interface:
    - (BOOL)validateUserInterfaceItem:(id )anItem
    {
        if ([anItem action] == @selector(copy:)) {
    		return [self canCutCopyDeleteOrDuplicate];
    	}
        return YES;
    }
    
  • Useful links

    NSTableView
    Drag And Drop

40 giorni di WiFiPhoto

October 13th, 2009

US-AppStore-Staff-PicksWiFiPhoto has been on sale for 40 days now. Some frustrations, many satisfactions. In the beginning I didn’t know what to expect. Just after its release I discovered I had made a terrible mistake. When you submit an application to Apple you decide the release date. I chose to leave the submission date, 22nd August. WiFiPhoto went on sale on 4th September. I didn’t know I could change my release date: my app was buried amidst tons of other apps and it didn’t get any benefit from being just released. A hard lesson that I’ve definitely learned. I sent a quick press release to Macity one of the most popular Mac and iPhone related websites in Italy (perhaps the MOST popular. take a look at Alexa). My sales readily took off. In a week I had sold over 2,000 apps only in Italy. Japanese friends also gave me satisfaction: some bloggers made a good review and it helped a lot. Indeed I was primarily interested in USA but at first things were very difficult (even because of a misleading customer’s review).
I decided to release a new update implementing various features I was requested. This time I chose to promote my app via a PR on prMac. And I didn’t forget to change my release date as soon as it became available on the AppStore. Eventually I got some attention from american users. I reached #26 in US AppStore in Photography category. In the meantime I had conquered some visibility even on other foreign AppStores. By now I’ve sold more than 5,000 apps all around the world. That’s not my first job (luckily) and I’m quite happy.
Anyway I received my greatest satisfactions from customers and they’re by far more pleasant than any financial result. Now I’m ready for version 1.2 but in the meantime I’m enjoying WiFiPhoto among “Staff Picks” on US AppStore ! Apple always rewards you.

Una veloce introduzione a WiFiPhoto

September 25th, 2009

Recensioni fuorvianti

September 20th, 2009

As a developer I think it’s really weird the fact that I can’t answer to customers’ reviews. Especially if they claim something totally wrong. Two users from USA wrote in their reviews that WiFiPhoto scales down images before download. But it’s simply false. WiFiPhoto keeps photos at their original dimensions. So if you’re downloading a 1200×1600 pixel picture taken by your iPhone 3G’s camera, you’ll end up finding a 1200×1600 pixel picture on your computer. So, what’s happening ?
They simply ignore the fact that even the original photo they chose to download was not full resolution. There are different reasons. Perhaps they used some third-party camera app to take pictures with a zoom. Or perhaps, more probably, they transferred photo albums from iPhoto to their iPhones ignoring the fact the iPhoto shrinks and compresses images. So if you think to recover images from your iPhone after a crash of your hard drive, I have some bad news for you: you can’t. Or at least you won’t be able to recover your full resolution original pictures, simply because they’re NOT on your iPhone.
I’m sorry for this, but being unable to answer wrong customers’ complaints is frustrating.

WiFiPhoto

September 5th, 2009

ArtworkAt last my first iPhone application is available on the AppStore. It was thought as a solution to my worst problem with iPhone: how to download photos to computers without a usb cable. iPhoto is my first choice when I’m home on my Mac but I very often take shots for work and I can’t download them at the office. Sending in emails is complicated and sluggish. My solution ? WiFiPhoto. This app lets you pick multiple photos from the Camera Roll or from the Photo Library and lets you download them to any computer over a local network (there must be a WiFi connection for the iPhone anyway) one at a time or altogether compressed in a zipped file. It’s as easy as opening on your favourite browser the web address displayed by WiFiPhoto. Nothing more. More info at the product page.

WordPress e Thesis: coppia perfetta

August 6th, 2009

At last I’ve managed to replace Joomla with WordPress. And I’m not going back. WordPress is simply easier, prettier and faster. Whatever you do, whatever you goal maybe it’s definitely The Choice. Each new release brings new options, more eye-candies and time saving features. Moving from Joomla 1.0 to 1.5 brought nothing really rewarding to mere users. It’s as if programmers wrote just for themselves (APIs change ? Who minds ? Everything looks the same to me). The more wonderful feature of WordPress anyway is automatic update. I had stopped updating Joomla since each time I ran into some problems. Moving to 1.5 simply compelled me to copy and paste my posts since something didn’t go the right way with migrator tool. It’s not supposed to be this way. Even if it’s free open source software, it should be usable even by people who don’t spend their time digging into docs to find the magic formula. WordPress is really another story. Nevertheless it provides all levels of customization necessary to turn your website into a complex CMS.
While searching for a suitable theme, I’ve come across Thesis. It’s not only a theme. It’s a framework. It adds a large number of options and yet it holds the flexibility to make it look the way you like. By means of hooks, you can customize behaviour and layout of your pages. See this post for further explanations. In a short time I was able to achieve this result. I’m very happy with Thesis and I’m working to adapt this website as soon as possible.
P.S. Autosave is really cool !

Rifugio Benigni, valle d’Inferno e ritorno

July 26th, 2009

Due mesi dopo la salita al Resegone, approfittando dell’assenza delle due bimbe in vacanza dai nonni, decidiamo di regalarci una gita in quota. La scelta cade sul rifugio Benigni da Cusio: due ore per 700m di dislivello: fattibile anche senza allenamento. Ma la sorpresa e’ dietro l’angolo: poco fuori Cusio, lungo la strada che sale ai piani dell’Avaro, incontriamo le indicazioni per l’agriturismo Ferdi in Val d’Inferno. L’idea ci solletica. Un bel giro ad anello passando a gustare qualche delizia d’alpeggio e’ proprio quel che ci vuole per una giornata da ricordare. Lasciata la macchina al solito tornante saliamo tranquillamente verso il rifugio.
Dudu nello zainetto ci assilla con mille richieste: pello (cappello), puccio (il cappuccio dello zainetto), goffe (il golf per quando ha freddo), acqua, ca(l)do, puia (paura di qualsiasi cosa, dalla marmotta al burrone). Dopo aver perso il cappello tranquillizza la madre con “fa niente dai mamma calma”. Mitico. Lungo il percorso incontriamo numerose lingue di neve, alcune anche da un metro e mezzo di spessore. Riscaldamento globale… mah.
Al rifugio (2222m) chiediamo informazioni sulla strada e dopo un’oretta di sosta ripartiamo lungo il sentiero 101. Passata la bocchetta di Val Pianella (2224m) procediamo in salita fino a raggiungere la cima di Giarolo (2314m) che ci ricompensa con una bellissima vista sulla Val Gerola. Riprendiamo in discesa lungo un canalone che infine ci porta alla testa della Val D’Inferno (1,5 ore dal Benigni).
Dopo un pediluvio ristoratore puntiamo decisi al Ferdi (1 ora) e qui tra una torta e l’altra ci informiamo sul ritorno. Le possibilità sono due. La prima e’ quella di seguire la strada sterrata fino al bivio per le Cinque Vie, salire alla Casera del Valletto (400m di dislivello, 1.20 h) e ritornare dal sentiero dell’andata. La seconda e’ quella di seguire tutta la strada sterrata verso sinistra, ignorando le deviazioni per Ornica per arrivare sopra Cusio lungo la strada dell’Avaro (1,5 ore, 200m di dislivello). Scegliamo questa seconda pur sapendo che senza passaggio in auto mi toccherà poi risalire altri 300m su strada per riprendere la macchina. Ma ho fiducia e faccio bene: al primo tentativo di autostop vengo prelevato da un autoctono di Olmo. Grazie, ero proprio morto! Sette ore con Dudu sulle spalle si sentono. Ma siamo agli sgoccioli: l’anno prossimo camminerà anche lui.

Medialayer rocks !

June 4th, 2009

After searching for a while a host which could keep up with my expectations, I finally got into this article which led me to the (hopefully) right choice. In the meantime I went through several blogs, reviews, advices and so on which were contradictory and misleading. The real problem in picking up the right host is that there’s no way to select the right criteria for googling. Generally I start by searching how many occurencies I can find for ‘hostofmydreams SUCKS’ versus ‘hostofmydreams ROCKS’. It’s a dead end path. A good ratio is 1 to 10 but it’s not that easy when you find more the a thousand pages stating that hostofyourdreams is a crap. In addition there are websites whose only purpose is to debate about a single host. Reviews are totally useless since they’re generally written by people who are paid by the same hosts they revise. To make things more complicated, I’ve found that even on wordpress.org hosts suggested are unreliable.I checked Bluehost, Dreamhost, GoDaddy, AN Hosting and many others. Media Temple was the most promising but some posts pointed out that it had its own problems. So I’ve finally got here. MediaLayer is not one of the cheapest around but as long as I can tell it’s really really fast. I’m from Italy and their server is in Chicago. Pages load even faster than with my previous (expensive) italian server. SSH, shared SSL, unlimited emails, unlimited ftp accounts, 500MB of disk space and 10 GB/month of bandwidth for 10$/month. Let’s see how long my honeymoon lasts.