2012年6月14日木曜日

リアルなテトリス


アメリカの大学生が5日で制作した動画だそうです。
すごい完成度!アイデアも面白いです。


2012年6月5日火曜日

デザイン、ユーザーインターフェースが素晴らしいiPhoneアプリケーション Clear for iPhone

ユーザーインターフェースが美しく、動きも新鮮なiPhoneアプリです。
実際使った感想はシンプルですが動きがスタイリッシュで使っていて楽しくさせてくれるアプリケーションですね。

ToDo管理や買い物メモなどとして使えそうです。
価格は200円(2012/5/31現在)です。






2012年6月2日土曜日

シャープから全部入り?お掃除ロボット発売-COCOROBO

シャープからいよいよCOCOROBOが発売されますね。
「人工知能」、「プラズマクラスター」、「スマホ連携」と全部入りみたいなお掃除ロボットです。

中でもスマホからCOCOROBOを通して家の中が見れる機能は家で犬を飼ってる私には欲しい機能です。
意外と家の中を動画で見られる機械ってこれまで意外となかったアイデアだと思います。






Woody Allen-Midnight in Paris

ウッディ・アレンの最新作。一昨年にロンドンに向かう途中機内で見ましたがようやく日本公開!主人公(小説家)がひょんな事からそれまで憧れていたヘミングウェイなどに出会い、色々と話をするところが面白いアイデア。


Midnight in Paris Poster






Sqlite+FMDB+UITableViewで一覧→詳細アプリの作り方

fmdbを使うとADO.Netのような手順でDBを扱うことができるのでWindowsで開発していた人にとっては取っ付きやすいです。

■最終イメージ



サンプルソースは以下からどうぞ。


■手順

  • プロジェクトの作成
  • sqliteフレームワークの追加
  • fmdbライブラリの追加
  • サンプルDBの作成
  • 一覧画面の作成
  • 詳細画面の作成

■プロジェクトの作成

iPhoneSDK:5.1
Xcodeバージョン:4.3.2
iPhoneシュミレーター:5.0.1

新規プロジェクトを作成します。

■プロジェクトにsqliteフレームワークを追加する

xCodeのトップノードを選択し、Build PhasesタブのLink Binary with Libraries欄で+ボタンを押す。


libsqlite3.0.dylibを選択してAddボタンを押す。



■プロジェクトにFMDBライブラリを追加する

以下のページでZIPボタンを押してライブラリをダウンロードします。


ダウンロードしたファイルを解凍してプロジェクトの適当な場所にファイルをコピーします(ここではFMDBというグループを作成してそこにコピー)。


■サンプルDBの作成

新規にデータベースを作成します。ここではLitaを使用して作成しています。
テーブルを作成します。ここではArtistという名前のテーブルを作成しています。

データを入力しておきます。

データを入力したらCompact DBボタンを押して作業を保存します。

作成されたデータベースをプロジェクトに追加します。



■一覧画面の作成

さて準備ができたのでコーディングを進めていきます。
何もしていなければ以下のようにstoryboardが表示されます。
ここからViewControllerを削除します。ついでにViewController.hとViewController.mを削除します。
ViewController.hとViewController.mを削除するときに以下の確認が出ますが、Move To Trashを選んでください。
削除した後はこんな感じ。
storyboard上にNavigation Controllerを追加します。すると以下のようにNavigation ContrllerとTable View Contllerが対で追加されると思います。
Table View Contollerに対応するクラスファイルを追加します。

Subclass OfでUITableViewContollerを選択します。

Table View ContollerのクラスにMasterTableViewControllerを指定します。

ここでArtistのデータをメモリ上で格納するためArtistクラスを作成します。
Artist.h,Artist.mをそれぞれ編集します。
<Artist.h>
#import 

@interface Artist : NSObject
{
    NSString *id;
    NSString *name;
    NSString *genre;
}

@property(nonatomic,retain)NSString *id;
@property(nonatomic,retain)NSString *name;
@property(nonatomic,retain)NSString *genre;

@end

<Artist.m>
#import "Artist.h"

@implementation Artist
@synthesize id;
@synthesize name;
@synthesize genre;
@end
続いてTable View Controllerを記述していきます。

<MasterTableViewController.h>
#import "FMDatabase.h"

@interface MasterTableViewController : UITableViewController
{
    NSMutableArray *mArtists;
}
@end
<MasterTableViewController.m>
#import "MasterTableViewController.h"
#import "Artist.h"

@interface MasterTableViewController ()

@end

@implementation MasterTableViewController

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.title = @"Master";

    NSFileManager *fileManager = [NSFileManager defaultManager]; 
 NSError *error;
 NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
 NSString *documentsDirectory = [paths objectAtIndex:0];
 NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:@"Sample.db"];
 BOOL success = [fileManager fileExistsAtPath:writableDBPath];
 if(!success){ 
  NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"Sample.db"];
  success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
 }
 if(!success){
  NSAssert1(0, @"failed to create writable db file with message '%@'.", [error localizedDescription]);
 }

    FMDatabase* db = [FMDatabase databaseWithPath:writableDBPath];
    if(![db open])
    {
        NSLog(@"Err %d: %@", [db lastErrorCode], [db lastErrorMessage]);
    }
    
    [db setShouldCacheStatements:YES];

    NSString*   sql = @"SELECT * FROM Artist;";
    FMResultSet*    rs = [db executeQuery:sql];
    mArtists = [[NSMutableArray alloc] init];
    while( [rs next] )
    {
        Artist * artist = [[Artist alloc] init];
        artist.id = [rs intForColumn:@"ArtistID"];
        artist.name = [rs stringForColumn:@"ArtistName"];
        artist.genre = [rs stringForColumn:@"Genre"];
        artist.origin = [rs stringForColumn:@"Origin"];
        artist.yearsActive = [rs stringForColumn:@"YearsActive"];
        [mArtists addObject:artist];
        
    }
    
    [rs close];
    [db close];
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
    // e.g. self.myOutlet = nil;
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    // Return the number of sections.
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // Return the number of rows in the section.
    return [mArtists count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] ;
    }

    Artist *artist = [mArtists objectAtIndex:indexPath.row];
    cell.textLabel.text = artist.name;
    cell.detailTextLabel.text = artist.genre;
    cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

    return cell;
}

/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Return NO if you do not want the specified item to be editable.
    return YES;
}
*/

/*
// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Delete the row from the data source
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
    }   
    else if (editingStyle == UITableViewCellEditingStyleInsert) {
        // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view
    }   
}
*/

/*
// Override to support rearranging the table view.
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
}
*/

/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Return NO if you do not want the item to be re-orderable.
    return YES;
}
*/

#pragma mark - Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    // Navigation logic may go here. Create and push another view controller.
    /*
     <#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil];
     // ...
     // Pass the selected object to the new view controller.
     [self.navigationController pushViewController:detailViewController animated:YES];
     */
}

@end

ここまでで実行すると以下のような画面が表示されると思います。
(まだdidSelectRowAtIndexPathメソッドは記述していません


■詳細画面の作成

storyboardに戻りView Controllerを一つ追加します。


DetailViewControllerとしてクラスファイルを一つ追加し、先ほど追加したView Controllerに割り当てます。


DetailViewControllerを実装していきます。
<DetailViewController.h>
#import "Artist.h"

@interface DetailViewController : UIViewController
{
    Artist *artist;
    UILabel *name;
    UILabel *genre;
    UILabel *origin;
    UILabel *yearsActive;
}
@property (nonatomic,retain) Artist *artist;
@property (nonatomic,retain) IBOutlet UILabel *name;
@property (nonatomic,retain) IBOutlet UILabel *genre;
@property (nonatomic,retain) IBOutlet UILabel *origin;
@property (nonatomic,retain) IBOutlet UILabel *yearsActive;
@end


<DetailViewController.m>
#import "DetailViewController.h"

@interface DetailViewController ()

@end

@implementation DetailViewController
@synthesize artist;
@synthesize name;
@synthesize genre;
@synthesize origin;
@synthesize yearsActive;

- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        // Custom initialization
    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
 
    name.text = artist.name;
    genre.text = artist.genre;
    origin.text = artist.origin;
    yearsActive.text = artist.yearsActive;
}

- (void)viewDidUnload
{
    [super viewDidUnload];
    // Release any retained subviews of the main view.
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    return (interfaceOrientation == UIInterfaceOrientationPortrait);
}

@end

labelを配置し、コードのOutletとひもづけます。



DetailViewのIdentifierをDetailViewに修正します。


最後にMasterTableViewController側の呼び出し部分を記述します。

<MasterTableViewController.m>   以下の2点を追記するだけです。
#import "DetailViewController.h"

#pragma mark - Table view delegate

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    DetailViewController *detailViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"detailView"];
    detailViewController.title = @"Detail";
    detailViewController.artist = [mArtists objectAtIndex:indexPath.row];
    [self.navigationController pushViewController:detailViewController animated:YES];
}
できあがり
サンプルソースは以下からどうぞ。