MOSA Multi-OS Software Artists

MOSAはソフトウェア開発者を支援します

  • iPhone/iPod touch アプリ紹介
  • MOSA掲示板
  • 活動履歴
  • About MOSA(English)

MOSA Developer News[MOSADeN=モサ伝]第346号

2009-06-09

目次

  • 「Wonderful Server Life」    第94回   田畑 英和
  • 小池邦人のCarbon視点でiPhone探求
  • ターミナルの向こうから      第49回  海上 忍 

「Wonderful Server Life」  第94回  田畑 英和

〜「Deployment」編〜

 この記事が配信されることはWWDC 09の基調講演はもう終了していることでしょうが、今年ははたしてどのような発表が行われているんでしょうか。さて、これまでNetBootのサーバ側の解説をしてきましたが、今回はクライアント側について解説します。

◇NetBoot起動
 NetBootのシステムが構築されている環境でクライアントをNetBootするには3つの方法があります。もしクライアントにすでに何らかのシステムがインストールされていれば、「システム環境設定」の「起動ディスク」からNetBoot起動を設定できます。「起動ディスク」には内蔵ディスクや外付けディスクなど、システムがインストールされていて起動可能なボリュームの一覧が表示されます。これらに加え、ネットワーク上でNetBootサービスが稼働していれば、NetBootサービスが提供している使用可能なNetBootイメージも一覧に表示されます。つまり、「起動ディスク」でNetBootイメージを選択して再起動すればクライアントをNetBoot起動することができるというわけです。
 この方法でNetBoot起動した場合、起動ディスクの変更は記録されますので再び起動ディスクを変えないかぎりクライアントは毎回NetBootで起動します。

・起動ディスクの選択
http://www.htabata.com/img/MXS105/netboot/system_pref_01.png

 2番目の方法ですが、クライアントを起動するときにCommand + Nキーを押しながら起動します。この場合、ネットワーク上でNetBootサービスが稼働していればクライアントは自動的にNetBootイメージを検出して起動します。もしサーバで複数のNetBootイメージを運用している場合には、NetBootサービスのイメージの設定でデフォルトに指定されているイメージから起動します。
 3番目の方法は2番目の方法と少し似ています。クライアントの起動時にOptionキーを押しながら起動します。このとき起動マネージャが動作してまず起動可能なボリュームの一覧が表示されます。ネットワーク上でNetBootサービスが稼働していれば、ボリュームの一覧にNetBoot起動用のアイコンが表示されますので、このアイコンからNetBoot起動することができます。
 ただしサーバ上にNetBootイメージが複数あったとしても、起動ボリュームの一覧にはNetBoot用のアイコンは1つしか表示されません。この場合NetBoot起動すると2番目の方法と同様に、デフォルトとして設定されたイメージから起動します。
 2番目と3番目の方法でNetBoot起動した場合、1番目の方法とは違い起動ボリュームの変更は記録されません。つまりクライアントをNetBoot起動した後に再起動すると、元々設定されていた起動ボリュームを使ってクライアントが起動します。一時的にNetBoot起動したい場合には便利な方法です。

◇NetBoot起動の流れ
 では次にクライアントがどのような流れでNetBoot起動するのかをみていきましょう。上記のいずれかの方法でクライアントをNetBoot起動すると、まずDHCPを使ってIPアドレスを取得します。DHCPから取得したIPアドレスを使ってネットワーク接続できるようになると、TFTPというプロトコルを使ってNetBootサーバからクライアントの起動に必要なbooterファイルをダウンロードします。
booterファイルは「システムイメージユーティリティ」を使ってNetBootイメージを構築したときに作成されています。
 booterファイルでクライアントが起動すると、NFS(またはHTTP)を使ってサーバ上のNetBootイメージをネットワーク経由でマウントします。NFSを使用するかHTTPを使用するかは前回解説しましたように、イメージごとにサーバ側で設定できます。
 NetBootのイメージは全てのデータが起動時にクライアント側にダウンロードされるわけではありません。クライアントからネットワークマウントし、必要に応じてネットワーク経由でデータが転送されます。NetBootイメージからクライアントが起動すると再びDHCPからIPアドレスを取得してネットワークの自動設定が行われます。

 以上がNetBoot起動の流れです。起動の流れを理解しておくことはトラブルシューティングにとって重要です。これまで解説してきましたようにNetBootは複数のサービスとともに使用しますので、どこか一部のサービスに問題があるとNetBoot起動に失敗します。起動に失敗した場合、その原因をつきとめる必要がありますが、起動の流れを正確に理解しておくことで原因の切り分けがやりやすくなります。

◇本格的な運用に向けて
 これでNetBootシステム構築の基礎の解説が一通り終わりました。基礎はあくまでも基礎なので実用的なシステムを構築するにはさらにいくつかのハードルが待ち受けています。例えばイメージのカスタマイズ作業やさらに他のサービスとの連携が必要になるケースがあります。
 NetInstallの場合、ネットワーク経由でインストールをしてしまいますので、インストールさえ完了してしまえば後は通常通りクライアントを使用できるわけですが、NetInstallではなくNetBootで毎回クライアントを起動する場合、クライアントからはシステムイメージ上での変更を再起動後も保存しておくことができません。そこでディレクトリサービスによるユーザの一元管理やネットワークホームの運用も必要となってきます。

 またNetBootでのクライアント起動をDeploymentの手段として使用することもできます。ディスクレスでクライアントコンピュータを起動するとクライアントの内蔵ハードディスクを未使用の状態にできます。そこでNetBootでクライアントを起動してから、クライアントの内蔵ハードディスクにシステムをインストールするといったこともできます。このような作業はシステム標準の機能だけでも実現できるでしょうが、作業を効率化するためのツールを利用することもできます。というわけで次回以降はDeploymentの応用について解説していきます。
                             次回へつづく

小池邦人のCarbon視点でiPhone探求(2009/06/05)

〜 UITableViewControllerを実装していく 〜

本アプリケーションは「Navigation-Based Application」テンプレートを使用しています。今回は、このテンプレート内容を解説した後、UINavigationControllerが管理しているUITableViewControllerのサブクラス(RootViewController)の実装へと進みます。

「Navigation-Based Application」テンプレートの場合、UINavigationControllerオブジェクトはMainWindow.xibに含まれており、
管理対象としてUITableViewControllerのサブクラスであるRootViewControllerが指定されています。 Interface BuilderでMainWindow.xibをオープンし、ウィンドウに表示されたNavigation Controllerアイコンをダブルクリックすると、デバイスサイズのウィンドウがオープンします。そこに…

Loaded From “RootViewController.nib”

と記載されていますが、これは、この場所に “RootViewController.nib”ファイルのFile’s Ownerとして定義されているビューコントローラ(クラス)が読み込まれて表示されることを示しているわけです。これを変更したい場合には、先んじてUINavigationControllerのビュー表示(点線の角丸で囲まれている領域)を選択しておき、Inspectorウィンドウの「Root View Controller Attributes」(ひとつ目アイコン選択)で表示される「NIB Name」のクラス名を入力し直します。アプリケーションを起動すると、一番最初に、ここに入力されているビューコントローラの管理ビューが、スクリーンに表示されることになります。

さて、RootViewController本体の方はRootViewController.xibの方に用意されています。このnibファイルは、Xcodeから直接オープンできますが、UINavigationControllerの “RootViewController.nib”表記(青文字部分)をクリックすることで即座にオープンすることも可能です。必要とされるアウトレット(Outlets)の接続はテンプレート自体が準備してくれていますが、自分自身で調整する場合もありますので、重要な箇所をピックアップしておきたいと思います。アウトレットの接続状況は、Inspectorウィンドウの「Root View Controller Connections」(2つ目のアイコン選択)で確認できます。

まず最初に、File’s Owner(RootViewControllerクラス)のtableViewとviewアウトレットが、同じnibファイルに登録されているテーブルビューアイコン(Table Viewと表記されている)に接続されていることを確認してください。
このアウトレットの設定が正しく行われていないと、アプリケーション起動時にテーブルビューが表示されません。次にテーブルビューのアイコンをクリックして、同じくアウトレットの接続状態を確認します。こちらは、dataSourceとdelegateアウトレットが「File’s Owner」アイコンに接続されていることを確認してください。こちらのアウトレットの設定が正しくないと、後からソースコードでクラス実装を行った時に、関連メソッドが正しく働かないことになります。

次に、ソースコード処理を順番に追いかけてみます。まず、ナビゲーションコントローラを準備する処理は、アプリケーションデリゲートクラス(SymmetryAppDelegeta.m)のapplicationDidFinishLaunching:メソッド(デリゲート)に記述されています。

- (void)applicationDidFinishLaunching:(UIApplication *)application
{
  //  ここにアプリケーション起動時に必要な処理を記述する

  [window addSubview:[navigationController view]];
  [window makeKeyAndVisible];
}


ここで使われているwindowとnavigationControllerという2つのアウトレットは、テンプレートにより用意されており、MainWindow.xibの「App Delegate」アイコンに接続されています。処理内容は、ウィンドウ(UIWindow)のサブビューにナビゲーションコントローラのビューを配置し、そのウィンドウをキーウィンドウとします。つまり、ナビゲーションコントローラで指示したテーブルビューコントローラ(RootViewControlle)がnibファイルから読み込まれ、最終的には、それが管理しているテーブルビュー(UITableView)が表示されるわけです。

ここから、ようやRootViewController.mに実装したメソッドの出番となります。まずは、クラス定義のRootViewController.hの方ですが、今のところインスタンス変数はひとつも定義されていません。クラスが対応しているプロトコルについては、以前お話した「画像の取り込み処理」に必要とされるクラスのものが3つ定義されています。

#import 

@interface RootViewController : UITableViewController
                            < UINavigationControllerDelegate,
                              UIActionSheetDelegate,
                              UIImagePickerControllerDelegate >
{
}

@end


次は、クラス実装をするRootViewController.mです。すでに、テンプレートがオーバライドすべきメソッドを幾つかピックアップし、コメント行として用意してくれています。このうちどれをオーバライドすべきなのかは、クラスの処理内容によって違ってきます。

- (void)viewDidLoad
{
  [super viewDidLoad];
}


viewDidLoadは、ビューコントローラがnibファイルから呼び込まれる時に一度だけ呼ばれます。通常、ビューコントローラの「初期化」処理に用いられます。

- (void)viewWillAppear:(BOOL)animated
{
  [super viewWillAppear:animated];
}


viewWillAppear:は、ビューコントローラに属するビューがスクリーン上に表示される直前に呼ばれます(この時点でまだビューは表示はされていない)。このメソッドは、一番最初だけでなく、別のビューコントローラから切り替わる時にも呼ばれますので御注意ください。 通常、ビューコントローラの「準備」処理に用いられます。

- (void)viewDidAppear:(BOOL)animated
{
  [super viewDidAppear:animated];
}


viewDidAppear: は、ビューコントローラに属するビューがスクリーン上に表示された直後に呼ばれます。

- (void)viewWillDisappear:(BOOL)animated
{
  [super viewWillDisappear:animated];
}


viewWillDisappear:は、ビューコントローラに属するビューがスクリーンから消える直前に呼ばれます。このメソッドはアプリの終了だけでなく、別のビューコントローラへの切り替え時にも呼ばれます。通常、ビューコントローラの「後始末」処理に用いられます。

- (void)viewDidDisappear:(BOOL)animated
{
  [super viewDidDisappear:animated];
}


viewDidDisappear:は、ビューコントローラに属するビューがスクリーンから消された直後に呼ばれます。

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


shouldAutorotateToInterfaceOrientation:は、ビューコントローラの向き(デバイスに対して縦方向なのか?横方向なのか?)を指示します。デフォルトは縦向きだけを容認するソースコードの記述となっています。

- (void)didReceiveMemoryWarning
{
  [super didReceiveMemoryWarning];
}


didReceiveMemoryWarningは、メモリの使用状況がタイト(メモリ不足)になった場合にOSから呼ばれます。開発者は、ここに不用になったメモリ(キャッシュやテンポラリ作業領域など)を開放する処理を記載します。ただし、間違ったメモリ解放(まだ必要なのに…)をするとクラッシュの原因となりますので、くれぐれも注意してください。ここで何もしなくとも、スーパクラスのビューコントローラではメモリ領域を増やすために不用ビューを解放するといった処理が実行されます。

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


deallocでは、通常のクラスと同じく、このビューコントローラクラスで仕様したインスタンス変数を解放します。

上記メソッドの中には、先んじてスーパクラスを呼び出す必要の無い種類もありますが(スーパクラスは何もしていないと言うこと)今後仕様変更があるかもしれませんので、必ずスーパクラスを呼ぶようにしましょう。ちなみに、didReceiveMemoryWarningやdeallocでは今でもスーパクラスの呼び出しは必須です。

ところで、少し上級者向けの話となりますが、initWithNibName:bundle:でnibファイルからUIViewControllerを読み込んで表示する時にpushViewController: animated:を使うと、最初の処理ではUIViewController側でオーバライドしたメソッドが…

- (void)viewDidLoad 
- (void)viewWillAppear:
- (void)viewWillDisappear:


の順番で呼ばれます。しかし呼び出しにpresentModalViewController:animated:を使うと、何故だか…

- (void)viewWillAppear:
- (void)viewDidLoad 
- (void)viewWillDisappear:


の順番でメソッドが呼ばれます。この現象はv2.2になってから起こるようになり、v2.1では問題ありませんでした。iPhone OS 3.0では修正されている様ですので、この現象はバグだったようです。v2.2をアプリ起動対象とされている方は御注意ください。

次回は、テーブルビュー(UITableView)に必要とされるデータソース(dataSource)とデリゲート(delegate)メソッドの解説を行います。これらの仕組みは、Mac OS XのNSTableViewと似ているのですが、iPhone OS独自の仕組みも沢山見受けられますので、そちらを中心に話を進めたいと思います。

ターミナルの向こうから      第48回  海上 忍

〜 リモートでシェルを使う(4) 〜

・sftpでファイルを一括転送
 前回紹介した手順で鍵ペア登録などの作業を行えば、つどパスワードを入力することなく安全にリモートサーバと通信できるようになります。これだけで、Webサイトを更新する目的でファイルを転送する場合などリモートサーバとのやり取りが簡略化されますが、複数のファイルを一括して送受信する用途には不向きです。
 そのような場面で利用したいのが「sftp」です。sftpは、SSH実装系におけるファイル転送プロトコルの一種で、Mac OS Xには同名のクライアントソフト「sftp」がコマンド(/usr/bin/sftp)として収録されています。つまり、ターミナルからsftpコマンドを実行することで、大量のファイルを安全かつ効率的にリモートサーバとやり取りできます。
 sftpとscpとの機能差ですが、暗号化された経路を通じてファイルを転送するという機能自体に違いはありません。しかし、リモート(SSHサーバ)上のシェルでコマンドとして実行されるscpは、1つのコマンドが完了しなければ次のコマンドを実行できない、すなわちファイル転送を一時停止したり再開したりすることはできません。一方のsftpは、SSHサーバ上で起動されたSFTPサーバがサブシステムを介してSSHサーバと接続し、通信路を確立したうえでファイル転送に関する内部コマンドを実行するスタイルのため、ファイル転送の一時停止/再開といった処理にも対応できます。

・sftpを起動する
 sftpの起動はかんたんです。sshコマンドでログインする(リモートシェルを実行する)ときと同様に、引数を「ユーザ名@サーバのドメイン名」の形式にしたうえでsftpコマンドを実行すれば、セッションが開始されます。鍵ペアの登録が完了していれば、パスワードの入力は必要ありません。

- – - – -
$ sftp yourname@dokka.com
Connecting to dokka.com…
sftp>
- – - – -

 セッションが開始されると、プロンプトは「sftp>」に変化し、sftp内部コマンドの入力待ち状態となります。基本的な操作方法はCUIのFTPクライアント(ftpコマンド)と同様で、以降セッション終了までは内部コマンドを利用します。まずは「help」を実行し、内部コマンドを確認しましょう。

- – - – -
sftp> help
- – - – -

・sftpの使い方
 ふだんsftpを使うとき、最初に実行すべきは「pwd」と「lpwd」コマンドです。前者でリモートホスト(サーバ)上の、後者でホーカルホスト上のカレントディレクトリを確認し、これから行うファイルの転送に備えます。続けてcd / lcdコマンドでアップロード / ダウンロード先のディレクトリを変更しますが、「~」や「..」といった記号やディレクトリ名の入力補完など、シェルでお馴染みの機能は利用できません。

- – - – -
sftp> pwd
Remote working directory: /virtual/yourname
sftp> lpwd
Local working directory: /Users/shinobu
- – - – -

 ファイルのアップロード(ローカル→リモート)には、「put」コマンドを利用します。最初の引数がローカルホスト上のファイル名、2番目の引数がリモートホストへコピー後のファイル名となるため、「put A B」の要領でコマンドを実行しても、2つのファイルをアップロードすることにはなりません。
複数のファイルをまとめてアップロードする場合には、「*」や「?」といったメタキャラクタを使用します。たとえば、拡張子「.pdf」のファイルを一括アップロードする場合には、次のとおりコマンドを実行します。

- – - – -
sftp> put *.pdf
- – - – -

 ファイルのダウンロード(リモート→ローカル)には、「get」コマンドを利用します。引数の指定方法はputコマンドと同様で、複数のファイルをまとめてダウンロードする場合にはメタキャラクタを利用します。

- – - – -
sftp> get *.html
- – - – -

- – - – -
表:sftpの主要な内部コマンド

cd <パス> リモートホストのディレクトリを指定のパスに変更する
lcd <パス> ローカルホストのディレクトリを指定のパスに変更する
ls リモートホストのディレクトリの内容を一覧する
lls ローカルホストのディレクトリの内容を一覧する
help 有効なコマンドと用例を一覧する
get <名前> リモートのファイルをローカルへ転送する(ダウンロード)
put <名前> ローカルのファイルをリモートへ転送する(アップロード)
rm <名前> リモートホストのファイルを削除する
mkdir <名前> リモートホストにディレクトリを作成する
rmdir <名前> リモートホストのディレクトリを削除する
pwd リモートホストのカレントディレクトリのパスを表示する
lpwd ローカルホストのカレントディレクトリのパスを表示する
exit sftpを終了する(quitも同様)
- – - – -

◇MOSAからのお知らせと編集後記は割愛します◇

 

 MOSA Developer News   略称[MOSADeN=モサ伝]
        配信停止 mailto:mosaden-ml@mosa.gr.jp
 記事内容に関するご意見 mailto:mosaden-toukou@mosa.gr.jp
      記事投稿受付 http://www.mosa.gr.jp/?page_id=850
Apple、Mac OSは米国アップル社の登録商標です。またそのほかの各製品名等
はそれぞれ各社の商標ならびに登録商標です。
このメールの再配信、および掲載された記事の無断転載を禁じます。
特定非営利活動法人MOSA  http://www.mosa.gr.jp/
Copyright (C)2009 MOSA. All rights reserved.