Hi-farm blog

ActionScript 3.0 , AIR , FLEXからCocoa, OpenGL

お久しぶりです。先ほどhetmelでのsvnを設定し、XCodeのSCMの設定ができましたのでメモ代わりにポストします。

1. hetemlでsvnのレポジトリとなるフォルダを作成する。
※当然ですが、hetemlの公式サイトを参考にしています。

今回はftpログイン時の最上位階層を基準として、svn/xcode/iphone/以下にレポジトリを作成するものとします。

まず、Terminalを起動します。
a. sshでログインします。ユーザー名がmyuserでsshのホストがssh100.heteml.jpだと仮定します。下記のコマンドを実行します。

ssh myuser@ssh100.heteml.jp -p 2222

【ユーザー名】@【sshホスト】 -p 【SSHのポート番号】
-p の次はポート番号を指しhetemlでは2222番ポートになります。

ログインに成功すると、画像のように、「heteml」の文字とともにパスワードを聞かれますので、ログイン時のパスワードを入力すると、ログインに成功します。

login

次に、フォルダを作成します。
mkdir svn
cd svn
mkdir xcode
cd xcode
mkdir iphone

とコマンドを実行し、svn/xcode/iphone とフォルダを作成します。

2. レポジトリを作成する。
まず、svn/xcode/iphone にいることを確認して下さい。

まずは空のレポジトリを作成します。下記のように入力して下さい。
svnadmin create .

次にtrunk, branches, tagsを作成します。
trunk作成:
svn mkdir file:///home/sites/heteml/users/m/y/u/myuser/svn/xcode/iphone/trunk -m “create trunk”
branches作成:
svn mkdir file:///home/sites/heteml/users/m/y/u/myuser/svn/xcode/iphone/branches -m “create branches”
tags作成:
svn mkdir file:///home/sites/heteml/users/m/y/u/myuser/svn/xcode/iphone/tags -m “create tags”

それぞれのコマンド実行後に”Committed revision 1.”のような結果が表示されたら、作成が成功した事を表します。

3. Mac上の設定
次に、公式サイトの手順に従ってsvnの設定を行います。

.subversion ディレクトリを作成します。Terminalで自分のアカウントのトップに.subversionというディレクトリを作成します。
※自分のアカウントへ移動するには、 cd ~ と入力します。
「.」で始まるファイルですので、ディレクトリが既に存在しているかを確かめるには、 ls -a と入力して確認して下さい。

cd .subversion と入力し、.subversionフォルダに入ります。
次に、vi config と入力し、configファイルを編集します。
svnsetting

XCode上の設定
それではXCode上の設定を行います。
「SCM」→「SCM レポジトリを構成…」を選び、”XCode”環境設定ダイアログより、SCMを選び、この画面を開きます。

xcode

+ボタンをクリックし、まずは新たにレポジトリを登録します。ここでは、「heteml」と入力します。
上の画像を参考に、設定を入力します。
「ユーザ」「パスワード」には、sshの設定値を入力します。

パスワード欄の下に、「認証されました」と表示されれば使用可能です。

使い方の続きはまた明日にでも書きます。

久しぶりに更新します。
今回はasのああだこうだ、ではなく、iPhoneのイヤホンジャックが壊れた、そういう事です。

壊れた時期は、つい3日ほど前。
いつも通り通勤時はiPhoneを使っていて、職場に着いたからイヤホンジャックを外し、カバンの中にいれていました。

仕事をこなし、夜になったので音楽を聴こうとiPhoneを取り出し、イヤホンを差そうとするけど、
ささらない。

あれ?こんなに力なくなったのか?と思って軽くへこみながら力を強めようと思ったのですが、今まで力んでしまって壊したものがあまりにも沢山あるため、(学校のイス、職場のイス、ふろのふた、PCパーツ、・・・キリがありません)頑張るのをあきらめ、職場でiPhone持っている人に聞いてみると、どうやらイヤホンジャックのふちにある金具?とかが無い様子。
実際比較してみると、まさにその通り。
その部品がないためにイヤホン端子を引っ掛ける事ができなくなってしまったようです。

金具が外れたイヤホンジャック

正常な状態との比較は、こちらの記事にある写真をご確認下さい。

なのであきらめてまずはソフトバンクショップへ。
しばらく確認してもらった後、お店からの回答はこの通り。
・iPhoneに関しては、修理というのはなく、交換のみ。
・基本的には保証期間内なので(iPhone 3GSです)無料ではあるが、僕が行った事に問題があるか判定を行って、問題が無ければお代は当然支払わなくてよいが、何かあった場合は、22,800円かかってしまう
・その判定はソフトバンクショップではなく、Appleが行う。
・ソフトバンクショップでは前もって判定結果を知らせる事はできないので、結果を聞いてから判断する場合は直接Apple Storeに行った方が良い

との事でした。
まあ何もしてないので大丈夫とは思うのですが、事後報告でお金払うのは嫌だったので、直接Apple Storeに行ってみる事にします。

その結果どうなるかは、後ほどアップします。

万が一有料だった場合には、こういう回避方法があるらしいので、これで我慢ですね。

追記:—————–
Apple Storeに持って行って話しをすると、直ぐに交換してもらえました!!
ただし、Developer Programとかで何かしている場合は結構面倒らしいです。

iPhoneでFlashの画面を操作する

以前、名古屋のFxugにて少し発表した内容なんですが、ずっと記事にできてなかったので、今更ながらまとめます。

密かに前から社内用発表会のネタとして作ってはいたのですが、僕個人的にも、なかなか披露する機会がないまま、時間が過ぎてしまいました。

概要としては、
1. iPhone上でボタンをタップすると、AIR 2で作ったサーバーに、iPhoneからSocket経由で信号を送ります。
2. AIR 2のサーバーが、信号を受け取り、信号に応じた処理を行います。

これが作ったアプリのキャプチャです。

viewer

iPhoneとAIR 2サーバーの関係は、この通りです。

kousei

簡単に行ってしまえば、これだけです。
では、ここから説明します。

1. AIR 2のサーバー部分を作成
AIRでサーバーを作るには、UDPとTCPのサーバーがありますが、今回はTCPで通信するので、flash.net.ServerSocketクラスを使用します。

宣言〜受付開始

<pre>import flash.net.ServerSocket;

// 接続してきたSocketを保持する
var socks:Vector. = new Vector.();
// インスタンス生成
var server:ServerSocket = new ServerSocket();
// 接続時のイベントハンドラ作成
server.addEventListener(ServerSocketConnectEvent.CONNECT, serverSocketConnectHandler, false, 0, false);
// 待ち受けポートを指定(43243番で受け付ける)
server.bind(43243);
// 待ち受け開始
server.listenen();</pre>

接続時:

function serverSocketConnectHandler(event:ServerSocketConnectEvent):void
{
  // 接続してきたSocket
  var socket:Socket = event.socket;
  // 接続してきたSocketにデータを返すため、イベント設定
  socket.addEventListener(ProgressEvent.SOCKET_DATA, receiveHandler, false, 0, false);
  // 接続してきたSocketを保持する
  socks.push(socket);
}

受信時:(本来は宛先を指定するべきだが、特に指定せず、全てのSocketに送信しています)

function receiveHandler(event:ProgressEvent):void
{
  // データを送信したSocketを取得
  var socket:Socket = event.target as Socket;
  if(socket!=null)  // nullチェック
  {
    // 受信データを取得
    var recv:String = socket.readUTFBytes(socket.bytesAvailable);
    // 操作対象のVideoPlayerを取得
    var target:VideoPlayer = getCurrentVideo(); // 自作のメソッドです
    // コマンドを取得し、操作を実行。コマンドを取得するため、indexOfを使っています。
    if( recv.indexOf("prev") >= 0) {
      setPos("prev");
    } else if( recv.indexOf("next") >= 0) {
      setPos("next");
    } else if( recv.indexOf("play") >= 0) {
      if( target.playing ) {
        target.pause();
      } else {
        target.play();
      }
    }
  }
}

AIRで作るサーバー周りは、こんなところです。エラー処理や切断時の処理などは書いてなくてごめんなさい。

iPhone側アプリケーションのSocket処理
では、次。iPhoneのほう。これも簡単な書き方でごめんなさいね。と、いうかCで最低限の実装しかしていないです。

TCPSendClient.m
接続:

-(void)connect:(NSString *)ip toPort:(NSInteger)port
{
  	if(_connected)  // TCPSendClientが持っている、接続状態を保持する変数
	{
		return;
	}
	_connected = NO;
	// IPアドレスを取得
	servIP = [ip UTF8String];
	// portを取得
	servPort = port;
	// socketが正しく生成できているかチェック
	if((sock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
	{
		NSLog(@"socket creation error.");
		return;
	}
	// socketの設定
	memset(&servAddr, 0, sizeof(servAddr));
	servAddr.sin_family = AF_INET;
	servAddr.sin_addr.s_addr = inet_addr(servIP);
	servAddr.sin_port = htons(servPort);
	// 接続
	if(connect(sock, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0)
	{
		NSLog(@"connect error.");
		return;
	}
	_connected = YES;
	NSLog(@"connect succeed.");
}

送信:

-(void)send:(NSString *)message
{
  mes = [message UTF8String];
  mesLen = strlen(mes);
  // 送信
  if(send(sock, mes, mesLen, 0) != mesLen) {
    NSLog(@"send failed.");
  }
}

ちなみに、
TCPSendClientクラスは、Socket処理を受け持つクラスで、自作しています。
TCPSendClient.hはこんな風に書いています。

#import <Foundation/Foundation.h>
#import <stdio.h>
#import <sys/socket.h>
#import <arpa/inet.h>
#import <stdlib.h>
#import <string.h>
#import  <unistd.h>

@interface TCPSendClient : NSObject {
	int sock;
	struct sockaddr_in servAddr;
	unsigned short servPort;
	const char *servIP;
	const char *mes;
	unsigned int mesLen;
	BOOL _connected;
}

-(void)connect:(NSString *)ip toPort:(NSInteger)port;
-(void)send:(NSString *)message;
-(void)close;
-(BOOL)getConnected;
@property(readonly) BOOL connected;

@end

このサンプルでは、このようにTCPSendClientを使っています。

PagerViewController.m

-(IBAction) processConnect:(id)sender  // ボタンをタップした時のAction
{
	if([connectSwitch isOn])  // これは、接続のon/offを切り替えるUISwitchです。
	{
		[sendc connect:@"10.0.2.1" toPort:43243];  // sendcというのがTCPSendClientです
		stateField.text = @"connect";
	}
	else
	{
		[sendc close];  // 本文では紹介しなかったですが、切断します。
		stateField.text = @"disconnect";
	}
}

データ送信:

-(IBAction) btnUp:(id)sender  // 各ボタンのTouchUpInsideと関連づけています。
{
	isPress = NO;
	prevValue = 0;
	if( (UIButton*)sender == btn) // btnとは、一つ前の動画にフォーカスをあてるためのボタンです。
	{
		dir = @"prev";
		[sendc send:dir];
	}
	else if((UIButton*)sender == nextBtn) { // nextBtnとは、一つ次の動画にフォーカスをあてるためのボタンです。
		dir = @"next";
		[sendc send:dir];
	}
	else if((UIButton*)sender == playBtn) { // playBtnとは、フォーカスがあたっている動画を再生するためのボタンです。
		dir = @"play";
		[sendc send:dir];
	}
}

ちなみに、こちらがiPhoneアプリの画面です。(すごい地味ですね。。。笑えない)

Interface Builderのキャプチャです。

ib

Macをルーターにする
最後に、iPhoneとAIRサーバーを接続するための設定をします。Macなら「インターネット共有」を使えば簡単にルーターにして連携させる事が可能です。こういうときに、一つのメーカーが作っている事が良い事に思えますね。
今回は、AirMac経由で共有します。

kyouyuu

1. 「システム環境設定」を開く
2. 「共有」を開く
3. 「インターネット共有」を選択する
4. 「共有する接続回路」がAirMac以外であることを確認。なっていなければ変更します。
→iPhoneとMacをAirMac(無線)で接続する
5. 「インターネット共有」のチェックを入れると、共有を開始するか確認してきますので、開始をクリックします。すると、画面右のAirmacのアイコンがこのようになります。

airmac

開始順としては、AIRサーバーとiPhoneが接続する必要があるので、
1. Macをルーターにする
2. AIRサーバーアプリを起動する
3. iPhoneアプリを起動して接続する。
4. iPhone上で操作する。

というところです。

今回簡単に紹介しすぎててすみません。このままでわかりにくいなどご意見ありましたら整理した上で、ソース込みで全て公開します。

久しぶりのブログ記事がメモレベルですみません。

Flash BuilderとFlashとを共存させたい場合、Flash Builder側にもflパッケージの場所を教えてあげたい場合があると思うのですが、なかなかこれが忘れやすいところにありますので、メモ代わりに残しておきます。

ちなみに、Snow Leopard, Flash CS4の環境です。
Application/Flash CS4/Common/Configuration/以下です。(Flash CS4の位置はインストールした場所により異なるでしょう)

.swcの中身は今イチ解らなかったのですが、
コンポーネント類 .swc : Components/以下
コンポーネント類のソース:Component Source/ActionScvript 3.0/以下

です。
もしかしたらもっと簡単に使えるようになる方法があるのかな、とも思いますが、ソースもみれるのはこれはこれでいい事があるかもしれないので残しておきます。

イージング系:libs/projects/Flash/src/以下

ListBoxとDataTemplate

なんと今回はC#あるいはWPFについてです。

自分があまりにも物事を忘れやすいことを反省して、忘れないようにするためのタスク管理アプリを作りました。
その時にListBoxで困ったのでメモ。
やりたい事は、ListBoxのItemsSourceに自分で作成したクラスのプロパティのコレクションを適用させる、ということ。

Window1.xamlの一部
ListBoxの定義:

<ListBox x:Name="dataList" ItemTemplate="{StaticResource listTemplate}"/>

DataTemplateの定義(TodoEntityというのが自分で定義したエンティティクラスです。):

<DataTemplate x:Key="listTemplate" DataType="{x:Type local:TodoEntity}">
            <Grid ToolTip="{Binding Path=DescriptionValue}">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="*"/>
                    <ColumnDefinition Width="*"/>
                </Grid.ColumnDefinitions>
                <StackPanel Orientation="Horizontal" Grid.Column="0">
                   <TextBlock Text="件名:"/>
                   <TextBlock x:Name="subject_tb" Text="{Binding Path=SubjectValue}" />
                </StackPanel>
                <StackPanel Margin="10,0,0,0" Orientation="Horizontal" Grid.Column="1">
                    <TextBlock Text="概要:"/>
                    <TextBlock Text="{Binding Path=DescriptionValue}"/>
                </StackPanel>

            </Grid>
        </DataTemplate>

で、これがエンティティクラスのTodoEntity

/// <summary>
        /// 終了しているか。
        /// 1: 終了
        /// 0: 未
        /// </summary>
        public int isFinished;
        /// <summary>
        /// 件名
        /// </summary>
        public string subject;
        /// <summary>
        /// 詳細
        /// </summary>
        public string description;
        /// <summary>
        /// 登録時間
        /// </summary>
        public DateTime registerDateTime;

        #region アクセサ。なぜかこうしないとデータバインドしなかった.

        public string SubjectValue
        {
            get
            {
                return subject;
            }
            set
            {
                subject = value;
            }
        }
        public string DescriptionValue
        {
            get
            {
                return description;
            }
            set
            {
                description = value;
            }
        }
        #endregion

DataTemplateにTodoEntityのsubjectプロパティを表示させたかったのですが、なぜか表示できなくて困ってたのですが、#regionに書いているようにアクセサ(SubjectValue, DescriptionValue)を作ってそれにバインドさせてやると、無事にデータが表示されました。

これなんでだろう。。。

あ、コードの書き方が統一されてなくてすみません。。。

アプリは見栄えがもう少しまともにできたらアップしますね。

現在作っているアプリでは、iPhoneからファイルとデータをアップロードする仕組みが必要になり調べてみたのですが、なかなか目的を達成してくれるクラスやライブラリが見つからなかったので自分で作ってみました。
ソースとテストで使ったPHPのファイルもgithubのここにおいています。
http://wiki.github.com/mmlemon/HTTPMultipartPost

ソースにはcopyrightとか書いていますが、改編などはご自由にどうぞ。ただし、こちらではいかなる責任も負いませんのでご了承下さい。

内容は、こんな感じです。

MultipartPostHelper:このクラスを使ってファイルのアップロードを行います。
実際の使い方は、HTTPPostSample2ViewController.mをご確認下さい。

使用する流れは下記の通りです:

  1. 送信先URLを設定する
  2. 文字列データ部分を作成する(Key用の配列と値用の配列が必要です。)
  3. バイナリデータ部分を作成する(このとき、data=実際のデータ:NSData、orgName:ファイル名、postName:Postで使われる名前。例:orgName=”file.txt”, postName=”postFile”の場合、PHPでは、$_FILES["postFile"]["name"]とすると、”file.txt”が返されます。)
  4. 文字データをMultipartPostHelperに追加
  5. バイナリデータをMultipartPostHelperに追加
  6. sendで送信

以上です。

Word Pressの自動アップデート

連続Postですみません。

最近WordPress上でアップデートが可能になってとても便利だな〜なんてのんびり喜んでいたのですが、google analysisのプラグインの設定が消えてしまう、という問題が起こりました。

実際このサイトは誰が見ているんだろう、という位なのでpvとかあまり意識していなかったのですが、ある日を境にアクセス数が0になってたので、さすがにこれはおかしいと思い調べてみると、UA-00000-0というような値になってしまっていました。。。。

メニュー下部のここをクリックして設定を確認してみるとよいと思います。

wpの環境設定

wpの環境設定

provisioningファイルのアイコン

つい先日、iPhoneに新しい機種、iPhone 3GSが発売されました。
なので早速僕も購入して、現在開発中のアプリを実機に入れて試そうとしたときにちょっと上手くいかなかったのでメモしておきます。

プロジェクトファイルを開いて、Device – 3.0 | DebugとしてiPhone 3GSに繋ごうとすると、

「供給された iPhone OS デバイスが接続されていません」


とか言われてしまい、実機にアプリをインストールすることができなかった。

当然と言えば当然の話しなんですが、provisioningファイル作るときに、DevicesでIDを登録してるんでした。この辺に関しては、iTunes経由で古いiPhoneからうまい具合に調整してくれていると思ってたのですが、そんなこと無かったです。考えてみれば

Deviceが違う=Device IDが違う、


ということなので当然なのですが。

Deviceに対応していないprovisioningファイルを使おうとしても使えないのは当然です。なので、iPhone Developer Programで新しい機種のIDを登録し、Provisioningを修正して新しい機種にも対応するProvisioningファイルを再生成し、インストールすると、無事に実機にアプリケーションをインストールすることができるようになりました!めでたしめでたし。

追伸:

こんなところでつまづく僕ですが、ほそぼそと開発合宿なるものをやっていますので、ご興味あれば参加表明していただければと思います。

http://blog.hi-farm.net/2009/07/01/200907の近況/

タイマー表示

今作っているアプリで時間経過を表示する必要がありましたので、サンプルを作成しました。

ほとんどこちらのサイト様を参考にしています。ありがとうございます。

http://cocoa.synck.jp/1237172145.html


一式はgithubにおきましたので、必要でしたらこちらからどうぞ。
http://github.com/mmlemon/iPhoneTimerSample/tree/master

ストップウォッチアプリのキャプチャ

ストップウォッチアプリのキャプチャ

操作方法:

  • Startボタンをタップ:計測開始
  • Stopボタンをタップ:計測終了
  • 再びStartをタップした場合、0秒から再計測します

ソースについて:

時間を測る事は、

開始時刻をNSTimeIntervalで保持します。

現在時刻を保持する方法は、

NSTimeInterval time = [NSDate timeIntervalSinceReferenceDate];

を使うだけです。

二つのNSTimeIntervalを比較するには、単純に引き算するだけです。

NSTimeInterval currentTime = [NSDate timeIntervalSinceReferenceDate] – time;

(※timeは計測開始時刻を保持するNSTimeInterval)

定期的に表示時刻をアップデートするにはNSTimerを使います。こんな感じ。


self.timer =  [NSTimer scheduledTimerWithTimeInterval: 0.01                                   target:self                                  selector:@selector(updateTimer:)                                  userInfo:nil                                   repeats:YES];

scheduledTimerWithTImeIntervalがタイマーが呼ばれる期間であり、

selectorがこのscheduledTimerWithTimeIntervalで定期的に呼ばれるセレクタ(メソッド?)である、という事を押さえておけばよいと思います。

ちなみに、selectorで呼ばれるものは、

-(void)updateTimer:(NSTimer *)t

のようになる必要があります。

ここで経過時刻を測定、表示すれば継続的に表示が更新されるようになります。

タイマーを終了する場合は、

[self.timer invalidate];

として下さい。

追記1:

開始時刻と累積時刻が二重に存在しているので上手くないですね。。

追記2:

github初めて使ったんですけど、つまらないところでひっかかっちゃいましたが、それはまた別記事にします。

追記3:

こんな程度の内容ですが、記事を書く事で改めて気づく事がありました。

これからも続けようと思います。


2009/07の近況

かなり投稿回数が少なくなってしまっているブログですが、つい先日までは本業で時間をいっぱいいっぱい使ってて、全く動けない状態でした。

だけど、これからは時間ができたのでiPhone開発合宿の予定を再調整したいです。http://123.writeboard.com/8464cc38ec43064f5 pass:ipdc09

とてもありがたいことに今月は結構休みを頂けることになったので、この間にflashとiPhoneの一人合宿?も行って成長しないと!