[AS][iPhone]FlashBuilder4.5のActionScriptモバイルプロジェクトで横向き固定の設定をした場合のステージサイズを正しく取得する方法

前の記事の続き、
FlashBuilder4.5のActionScriptモバイルプロジェクトでの設定のお話。

まず横向き固定にする方向は、hoge-app.xmlに

<!-- hoge-app.xml内のinitialWindow要素に指定 -->
<aspectRatio>landscape</aspectRatio>

を設定するだけでOK。
これでデバッグプレビューすると確かに横向きでプレビューされる。
が、stage.stageWidthは320、stage.stageHeightは480と変更されていない。
(ちなみにFlexモバイルプロジェクトの場合はstage.stageWidthは480、stage.stageHeightは320となり問題ないようす)

ではどうしたらいいか、
結論としては、ドキュメントクラスのコンストラクタに以下の一行を追加
stage.setAspectRatio(StageAspectRatio.PORTRAIT);

//前提で、hoge-app.xmlにlandscapeと設定
stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
trace(stage.stageWidth, stage.stageHeight); //出力:320,480
stage.setAspectRatio(StageAspectRatio.PORTRAIT);
trace(stage.stageWidth, stage.stageHeight); //出力:480,320

解せないのが、なぜPORTRAITなのか。
通常はPORTRAITは縦、LANDSCAPEは横をあらわすので、stage.setAspectRatio(StageAspectRatio.LANDSCAPE);と設定すればいいと思ったのだけど、これだとstage.stageWidthは320、stage.stageHeightは480のままとなった。

//前提で、hoge-app.xmlにlandscapeと設定
stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
trace(stage.stageWidth, stage.stageHeight); //出力:320,480
stage.setAspectRatio(StageAspectRatio.LANDSCAPE);
trace(stage.stageWidth, stage.stageHeight); //出力:320,480

解せぬ。


※2011.8.15追記
上記設定だと実機転送した際に横方向にはならない様子。。。
やはりsetAspectRatio()にはStageAspectRatio.LANDSCAPEを設定しないと横向き固定にはなりませんでした。
上に書いたLANDSCAPE設定での懸念されるステージサイズは、
trace(stage.stageWidth, stage.stageHeight); //出力:320,480
となっているようで実機起動上では特に問題なさげ。
ステージサイズがちゃんと取れないのはデバッグプレビューだけでのバグってことなのか!?

※2011.8.18追記
コメント欄にて教えていただきました。
stage.setOrientation(StageOrientation.DEFAULT)を設定することで想定したstageサイズを取得することができました。

//前提で、hoge-app.xmlにlandscapeと設定
stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;
trace(stage.stageWidth, stage.stageHeight); //出力:320,480
stage.setAspectRatio(StageAspectRatio.LANDSCAPE);
stage.setOrientation(StageOrientation.DEFAULT);
trace(stage.stageWidth, stage.stageHeight); //出力:480,320

[AS][iPhone]FlashBuilder4.5のActionSclriptモバイルプロジェクトにて、iOSでプレビューした際のステージサイズが正常に取れない場合

だいぶはまってネットに情報が見当たらなかったのでメモ。

FlashBuilder4.5でiPhone、Androind等のアプリを作るため、以下2つのプロジェクトが用意されました。

  1. Flexモバイルプロジェクト
  2. ActionScriptモバイルプロジェクト

1.はMXMLベースのプロジェクトで2はASだけで作れるプロジェクト。
ボクはMXMLはさっぱりなのでASだけで作れる2.を選択。
普通のFlashコンテンツを作ると同様にドキュメントクラスからゴリゴリ書いていけばOKですが、
iOS用の書き出しをした際にステージサイズの参照値おかしなことになりました。

こちらの想定は、シミュレートデバイスが、iPhone3GSなら320 × 480、
iPhone4設定なら、640 × 960となってほしいところですが、
stage.stageWidth,stage.stageHeightのtrace結果は常に、500, 375

なんぞこれ、と思えどステージサイズの設定する箇所は見当たらず。
ためしにapp.xmlのwidthとheightに直接値(320 480)を入れてみるも変化無し。
さらにドキュメントクラスにSWFのembedタグを書いてみるも変化無し。


FlashBuilderのHelpを観てみるとこんなページに行き着きました。
http://www.randytroppmann.com/2011/04/12/pure-as3-workflow-with-flex-builder-4-5/

そこに書かれていた見慣れぬ1行を追加してみると。。。

stage.displayState = StageDisplayState.FULL_SCREEN_INTERACTIVE;

これを入れることでstage.stageWidth,stageHeightが想定通りの値となりました。
(シミュレートデバイスを変えることにより値も変化する)
とりあえず、よくわからんけど、上記一行は必須らしい。


P.S.
Retina対応もできるらしいけど、3G/3GSとRetinaの混合設定がよくわからん。。
highを書くだけで、Objective-Cみたいに自動でいい感じに変換してくれるのか、それとも2種類の画角を分けて作らないのいけないのか。。
Retinaの実機がないから検証できんのよね。。

[iPhone]UISliderのつまみ(thumb)を独自の画像に変更するときの注意

簡単にできたようで出来てなくてちょっとはまったのでメモ

基本的にはメソッドが用意されます。

//setThumbImage
//使用例
//speedLevelSliderというUISliderが宣言してあって、Resourceに"sliderThumb.pngがあるとして
//sliderThumb.pngはwidth:100px,height:100pxとする
//通常状態
[speedLevelSlider setThumbImage:[UIImage imageNamed:@"sliderThumb.png"] forState:UIControlStateNormal];
//つまみをタッチ状態も登録しておかないとデフォルトが表示されちゃう
[speedLevelSlider setThumbImage:[UIImage imageNamed:@"sliderThumb2.png"] forState:UIControlStateHighlighted];

これだけで指定した画像につまみが変更される。
が、UISliderをInterfaceBuilderで配置した場合にはこれだけではうまくいかない場合がある。
デフォルトのUISliderのheightは23になるのだけど、自分で用意したつまみ画像の高さが23を超える場合は、はみ出した部分はタッチ領域にならない。
上記の例だとつまみの高さは100pxなので見た目はでかいつまみになっているけど、実機でタッチできる領域は中心の23px分しか反応しないことになる。
InterfaceBuilder上からheightを修正してあげればいいかと思うと、Hの領域だけグレイアウトされていて修正ができない.

なのでframeプロパティを修正して描画領域を書き換えてあげないといけないのでした。

//変更前
//Sliderのx,y座標やwidthはInterfaceBuilderから確認
speedLevelSlider.frame = CGRectMake( 10, 200, 200, 23);
//変更後
//(実際は左上基準なので、つまみが大きくなった分、y座標も修正する必要あります)
speedLevelSlider.frame = CGRectMake( 10, 200, 200, 100);

/////////////////////////////////////////////////////////////////////////////////////////////////////////
というようなことが下記のブログには、しっかり書かれていましたのですが、、
スライダーバー(UISlider)のカスタマイズ的:いまログ
細かいところが理解できずに結構はまってしまった。。。

[iPhone]Objective- Cの勉強メモ:xibファイルとはどういうものなのか

・xibファイルとは、
XML Interface Builderの略。
その名の通り、xml形式のファイル。
これをxcodeから開くとInterfaceBuilder(アプリケーション:以下IB)が立ち上がってビジュアル的にxmlの中身を編集できる。
(ということだと思う)

・Flashでいったらxibファイルって何にあたるの?
とTwitterでつぶやいたら、
エライ人から「FLEXでいうところのMXMLみたいなもの」と教えてもらった。
なるほど、FLEXでもMXMLも表示オブジェクトの配置情報を持っているし、MXMLを使わなくてもASで表示オブジェクトの配置することもできる。
(でもMXMLも使い方をよくわかってない)

ちょっと調べてみようと思ったらかなり分かりやすい素敵記事発見。

iPhone:Xib/Nib ファイル(その1):「支出管理」サポート
iPhone:Xib/Nib ファイル(その2) :「支出管理」サポート

xibファイルは、UIApplicationかUIViewControllerのサブクラスによってロードされるものなのね。
どのクラスにも設定できちゃうから、この辺りの仕組みがよくわからなかった。
ありがたやありがたや。

[iPhone] Objective- Cの勉強メモ:Xcodeショートカット:ヘッダーファイルとソースファイルの切り替え

.h/.mファイルの切り替え
cmd + option + 上キー(交互に切り替わる)

[iPhone] Objective- Cの勉強メモ:NSNotificationCenterでイベント通知の管理

Objective-CはASと違ってデリゲートとという機能がある。
デリゲートとは別に色んなクラスが通知するイベントを一括で管理してくれるクラスがあるみたい。
それが、NSNotificationCenterクラス。

手順としては、
1.NSNotificationCenterのインスタンスを生成
2.通知の登録(インスタンスに通知先、リスナー関数、通知の種類、通知の送信元)
3.通知の開始
4.(通知の終了)
5:(通知の登録解除)

例)

//playerはMPMusicPlayerControllerのインスタンス

//通知センタのインスタンを取得
NSNotificationCenter* noteCenter = [NSNotificationCenter defaultCenter];
//addObserver:通知先
//selector:リスナー関数
//name:通知してほしい通知の種類?
//object:通知の送信元
[noteCenter
addObserver:self
selector:@selector(hoge:)
name:MPMusicPlayerControllerNowPlayingItemDidChangeNotification
object:player];
//通知開始を指示
[player beginGeneratingPlaybackNotifications];

nameはnilにすると全ての種類のイベントが取得対象になる。
(そもそも通知の送信元がどのようなイベントを発信してるかを把握してる必要あり?)
(ドキュメントみれば書いてあるのかな?)
objectはnilにすると、全ての送信元からイベントを受け取る。

あとNSNotificationCenterはシングルトンになるので、インスタンス変数の保持はしなくてもいいみたい。

[iPhone] Objective- Cの勉強メモ:カテゴリという概念を使って元クラスの拡張(メソッドの追加)できる

Objective-CにはASにはない機能でカテゴリという概念がある。
これはクラスファイルにメソッドを追加することができる機能。

通常クラスを拡張するにはそのクラスを継承したサブクラスを定義すればいいと思う。
でも根本的に弄りたくなった場合、元のクラスを書き換えちゃうということもできる。
(ASだと、Flash8でAS2のときは直接編集できたけど、AS3ではSWCになってるから無理ぽ)
でも書き換えちゃうと何か不具合がおきたときとかバックアップとってないと元に戻すのが大変。

というわけでカテゴリという概念は、元クラスを簡易的に拡張できるという概念。
ただし追加できるのはメソッドだけ。
変数は追加できない。
手順は拡張用のクラス(?)ファイルを作ってそこで定義する。

例)UIViewを拡張する、UIViewExファイルを生成する場合
//ヘッダーファイル

#import <UIKit/UIKit.h>
//ここでの()の中の名前は任意(ファイル名と同じでなくてよい)
@interface UIView (AnimationExtension)
//メソッドの定義
//ここに追加したいメソッドを書く
-(void) hoge;
@end

//実行ファイル

#import "UIViewExtention.h"
@implementation UIView(AnimationExtension)
//メソッドの実装
    //ここで定義したメソッドを実装する
 -(void) hoge{
    //処理
}
@end

書き方で注意するのは、ヘッダーファイルでのinterfaceのくだり。
変数は定義できないので、{}は書く必要なし。

これを反映されるには、反映させたいクラスファイルにて

#import "UIViewExtention.h"

を記述すればよい。
これが記述されたクラス内では、UIViewインスタンスにUIViewExで追加したメソッドが普通に使えるようになる。

//例

-(void) init{
//imageViewはUIImageVIewクラスのインスタンス
//(UIImageViewのスーパークラスはUIImageなのでhogeメソッドが使える)
[imageView hoge];
}

[iPhone]Objective- Cの勉強メモ:乱数の取り扱い

まずはObjective-CというかC言語での乱数の発生させる方法。
使える関数は2種類
まず
int rand(void);
という関数でint型の乱数を返すことができる。
このときに返る値は、0~馬鹿でかい数という感じ。
馬鹿でかい数はコンパイラによって変わるらしい。
(ASのMath.random()のように、0~1未満というわけでない)

int i;
i = rand();
printf(%d,i);//0から馬鹿でかい数の間の間

ただ、このままだと乱数は実行するたびに常に同じ値を返すことになるので、初期化処理という行為が必要になる。
そこで使うのがsrand();
void srand(unsigned int 初期値);

使い方としては、rand()関数を実行する前にsrand()関数を実行することで初期化すればよし。
初期値には、絶対にかぶらない値を日付データから取ればよし。

//time(NULL)で現在の時刻が1970年1月1日午前0時0分0秒からの通算秒数で得られる。
srand(time(NULL));
rand();

以上が、C言語での設定方法

Objective-Cではsrandは以下のようにするらしい。

//NSDateインスタンスを作って、本日の日付けを秒数に換算してる
srand([[NSDate date] timeIntervalSinceReferenceDate]);
rand()

※C言語のやり方でも問題なさげ。

[iPhone]Objective- Cの勉強メモ:プロパティ宣言:@propertyの意味

ヘッダーファイルにて、プロパティ宣言をすることでそのプロパティについてのゲッターセッターが実装される。
プロパティ宣言をしなくても、自分で実装処理を書いてもよい

プロパティの書式は、

//ヘッダーファイルに書く
//@property (属性 , 属性, ・・・) データ型, 名前
//例
@property ( nonatomic, retain ) NSTimeZone* timeZone;

//ソースファイルに書く
@synthesize timeZone;

上の例を自分で実装した場合は

//ソースファイルに書く
//ゲッター
-(NSTimeZone*) timeZone{
//同時実行不可のための処理:属性nonatomicに相当
@synchronized(self){
return timeZone;
}
}
//セッター:読み書きについて属性が未設定なのでセッターまで生成される
-(void) setTimeZone:(NSTimeZone *)zone{
//同時実行不可のための処理:属性nonatomicに相当
@synchronized(self){
if(timeZone != zone){
[timeZone release];
timeZone = [zone retain];//保持する際は保持カウントをアップさせる:属性retainに相当
}
}
}

※@synchronizedは排他制御するかしないか。
マルチスレッドで同時に実行して欲しくない処理があるとき、これを指定することで片方のスレッドを停止することができる。
上の例では排他制御に対応しており、プロパティの属性でnonatomicを指定すると、排他制御はしなくなる。

[iPhone]Objective-Cの勉強メモ:dealloc

クラスファイルの最後の方にやたら登場するdeallocメソッド
NSObjectのメソッドで、それをオーバーライドしている。
dealloc実行のタイミングは保持カウントが0になったときに実行される。

保持カウントはインスタンスの生成、retainさせた参照の追加でカウントアップ。
releaseでカウントダウンされるのでカウント数には注意が必要。

例)

- (void)dealloc {
    [window release];
//スーパークラス(NSObject)のdeallocを実行することで実際のメモリの破棄
//C言語のfree関数のようなもの
    [super dealloc];
}