2010/07/31 | 3:24 am

iPad x 3D Hologram

おお、その手があったか。と言っても全然やり方わからないスけど。。。
なんという事でしょう(← ビフォーアフター風)

N-3D DEMO from aircord on Vimeo.


aircord labo
via Fubiz

COMMENT

POSTED

jam

2010/07/30 | 0:17 am

Movie のメモリリーク of iPad

MoviePlayerController と MoviePlayerViewController どちらでも、
FullScreen ではなく、画面内に埋め込んで再生している状態で「DONE」ボタンを押すか、ちゃんと最後まで見ない状態で強制的に止めるとメモリが残ってるぽい。。。

Instruments 使って計ってみたところ、終了時のメモリの下げ幅が最後まで見た場合と強制的に終わらせた場合だと半分くらいちがうという結果。。。汗
[moviePlayer retainCount] でリファレンスカウンタの値を調べても release した時点で 4(← 謎)を吐き出す。
そもそも、なんで増えてるのかしら??
[moviePlayer stop] を呼び出すと一気に増えるのは何故??

例えば、電子カタログ系とかの構造を作るとして、スクロールでページ展開していく場合、インラインで指定エリアの中でムービーを流す予定のページで、途中で遷移したときに前のページのムービーが流れっぱなしは避けたいところ。
なので、UIScrollViewDelegate の scrollViewDidEndDecelerating: などでスクロールとページ状況を検知して前後のページの状態を初期化する方法を取ってムービーを終了させると発生してしまう模様。。うう。。

やはりちゃんとフルスクリーン表示させて「DONE」ボタンなりでちゃんと終了させないとダメっぽい。

[ソースコード]
(※親の mファイルが setMovie: を呼ぶ想定で
stopMovie が遷移したときの強制終了用のメソッドです)

- (void)setMovie:(NSString *)movieName movieArea:(CGRect)frameSize pageName:(NSString *)page {
	NSBundle *bundle = [NSBundle mainBundle];
	fileName = [[NSString alloc] initWithString:[bundle pathForResource:movieName ofType:@"m4v"]];
	currentPage = page;

	movieButton = [[UIButton alloc] initWithFrame:frameSize];
	[movieButton addTarget:self action:@selector(movieButtonTouched:) forControlEvents:UIControlEventTouchDown];
	[movieButton setBackgroundImage:[UIImage imageNamed:@"movie_capture.jpg"] forState:UIControlStateNormal];
	[self addSubview:movieButton];
}

- (void)movieButtonTouched:(id)sender {
	[movieButton removeFromSuperview];
	[self playMovie];
}

- (void)playMovie {
	moviePlayer = [[MPMoviePlayerController alloc] initWithContentURL:[NSURL fileURLWithPath:fileName]];
	[moviePlayer.view setFrame:CGRectMake( 0, 0, self.frame.size.width, self.frame.size.height )];

	[moviePlayer play];
	[self addSubview:moviePlayer.view];

	isPlayMovie = YES;

	[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(moviePlayerDidFinish:) name:MPMoviePlayerPlaybackDidFinishNotification  object:moviePlayer];
}

- (void)clearMovieAsset {
	[[NSNotificationCenter defaultCenter] removeObserver:self name:MPMoviePlayerPlaybackDidFinishNotification object:moviePlayer];

	moviePlayer.initialPlaybackTime = -1;

	[moviePlayer pause];
	[moviePlayer stop];
	[moviePlayer.view removeFromSuperview];
	[moviePlayer release];

	[self addSubview:movieButton];

	isPlayMovie = NO;
}

- (void)moviePlayerDidFinish:(NSNotification *)aNotification {
	[self clearMovieAsset];
}

- (void)stopMovie {
	if( isPlayMovie ) {
		[self clearMovieAsset];
	}
}

Build and Analyze でも leak はしていないけど、Instruments のランタイムで見てると顕著にメモリリークしてます。
うーん、うーん。。。
リファレンスカウンタ方式とガベージコレクタ方式があるから、ガベージコレクタの方も調べなければ。

COMMENT

CATEGORY

POSTED

jam

2010/07/21 | 13:57 pm

Objective-CでFlashの非同期処理みたいなの

Objective-C で UIViewController を入れ子にしたときに、子UIViewController から親UIViewController の Function を呼びたいとき。
かなり前に書いてたのに、公開忘れてたので今公開。
こーゆーの中々覚えられないアフォーなのでメモ。。。

—————————-
AppDelegate
- ParentController
- ChildController
—————————-
という関係性があると仮定して、このときに ChildController が ParentController のメソッドを呼ぶ場合、
ParentController と ChildController に記述することス。

まず親側の .hファイルには子ファイルの .h ファイルをインポートして @interface 時に Delegate を加える。

//  ParentController.h
//
#import <UIKit/UIKit.h>
#import "ChildController.h"

@interface ParentController : UIViewController <ChildControllerDelegate> {
	ChildController	*childController;
}

@property (nonatomin, retain) ChildController *childController;

// 呼び出される Function を定義
- (void)calledFromChild;

@end

親側の .m ファイルで子の Delegate をセットする

//  ParentController.m
//

@implementation ParentController

@synthesize childController;

- (void)calledFromChild {
	NSLog(@"calledFromChild");
}

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

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

- (void)viewWillAppear:(BOOL)animated {
	ChildController *child = [[ChildController alloc]  initWithNibName:@"ChildController" bundle:nil];
	self.childController = child;
	[self.childController setDelegate:self];

	[self.view insertSubview:childController.view atIndex:0];
}

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

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

@end

次に子側の .h ファイルには protocol で Delegate と @optional で呼び出すメソッドを設定

//  ChildController.h
//

#import <UIKit/UIKit.h>

@protocol ChildControllerDelegate;

@interface ChildController : UIViewController {
	UIButton *checkButton;	// InterfaceBuilder で配置したボタンと仮定
	id <ChildControllerDelegate> delegate;
}

@property (nonatomic, retain) IBOutlet UIButton *checkButton;
@property (nonatomic, assign) id <ChildControllerDelegate> delegate;

- (IBAction)clickCheckButton:(id)sender;	// InterfaceBuilder で checkButton と関連づける

@end

@protocol ChildControllerDelegate <NSObject>

@optional
- (void)calledFromChild;	// ParentController で定義したメソッドと同じ名前

@end

それで子側の .m ファイルで delegate で親側のメソッドを実行

//  ChildController.m
//  

#import "ChildController.h"

@implementation ChildController

@synthesize checkButton, delegate;

#pragma mark -

// 実際に呼び出すメソッド
- (IBAction)clickCheckButton:(id)sender {
	if( [delegate respondsToSelector:@selector(calledFromChild)] )
		[delegate calledFromChild];
}

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

- (void)viewDidUnload {
	checkButton = nil;
	[super viewDidUnload];
}

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

@end

これで、checkButton に関連づけられたボタンにタッチしたときに
Xcode の[実行]-[コンソール]で表示されるウィンドウに「calledFromChild」って表示されます。
子側の処理を待ってから、親側でごにょごにょするときに使える。

COMMENT

CATEGORY

POSTED

jam

JUN NAKAJIMA
Tokyo, Japan.
member of Onawatobi.
contact@brooklyn.jp