cocos2dの最近のブログ記事

cocos2dとcocoaインタフェースのハイブリッドを実装する際、つい便利なaddChildViewControllerを使ってしまいがちですが、使うとアプリがバックグラウンドに移行するタイミングで終了してしまいます。

昔の方法になりますが、addChildViewController:を使わずにメンバ変数にviewControllerを保持しておき、rootViewController.viewに対してaddSubView:を実行するようにします。
こんにちは。開発担当のICTFです。

cocos2dで作ったアプリで広告を表示して収益化を目指したい事があるのではないでしょうか。
今回はその方法についてご紹介します。
サンプルとして広告はAppBank様のNendSDKを使用します。

cocos2d環境で広告を表示する事に主眼を置きますので、NendSDKの導入については触れません。
まずはNendSDKをプロジェクトに追加し、正常にビルドできる事を確認して下さい。

広告用のレイヤを作ります。こうすれば画面遷移が多くてもぺたぺた広告レイヤを張るだけで広告表示ができますので便利です。
且つNend以外の広告にもすぐ対応できるよう、広告レイヤのベースクラスを作成し、基本処理を実装しようと思います。

【AdLayerBase.h】

// 広告の全画面表示開始通知

#define IAD_LAYER_NOTIFY_SCREEN_SHOW_BEGIN @"iAdLayerNotifyScreenShowBegin"


// 広告表示位置

typedef enum {

iAdLayerPosition_Top_Center,

iAdLayerPosition_Botton_Center

} eiAdLayerPosition;


// 広告レイヤの基底クラス

@interface AdLayerBase : CCLayer 

{

UIView* _adView;

BOOL _isAllowShow; // 広告の表示が許されているか

eiAdLayerPosition _framePosition; // 表示位置

}


@property (nonatomic, readwrite) eiAdLayerPosition FramePosition;


// 表示位置を指定して初期化する

+(id) nodeWithFramePosition:(eiAdLayerPosition)position;


// バナーを意図的に隠す

-(void) hideIAd;


// バナーを表示する

-(void) showIAd;


// 通知センタからの通知イベント

-(void) NotifyFromNotificationCenter:(NSNotification*)notification;


// 広告ビューの生成

-(void) createIAd;


// 広告ビューの解放

-(void) releaseIAd;


// 表示位置を得る

-(CGPoint) getShowPoint;


@end


【AdLayerBase.m】

@implementation AdLayerBase


@synthesize FramePosition = _framePosition;


// 表示位置を指定して初期化する

+(id) nodeWithFramePosition:(eiAdLayerPosition)position

{

return nil;

}


-(id) init

{

if (self = [super init]) {

// 通知センタのオブザーバ登録

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(NotifyFromNotificationCenter:) 

name:nil object:nil];

_adView = nil;

_isAllowShow = YES;

_framePosition = iAdLayerPosition_Top_Center;

}

return self;

}


-(void) dealloc

{

// 通知センタのオブザーバ登録を削除する

[[NSNotificationCenter defaultCenter] removeObserver:self];

[self releaseIAd];

[super dealloc];

}


// 画面遷移完了通知

-(void) onEnterTransitionDidFinish

{

[self createIAd];

}


// 通知センタからの通知イベント

-(void) NotifyFromNotificationCenter:(NSNotification*)notification

{

if (notification.name == ROOTVIEWCONTROLLER_NOTIFY_MSG_ROTATE) {

// 画面回転通知

// 広告の位置を調整する

CGRect rect = _adView.frame;

rect.origin = [self getShowPoint];

_adView.frame = rect;

// 表示許可があれば、広告を表示する

if (_isAllowShow) {

_adView.hidden = NO;

}

}

else if (notification.name == ROOTVIEWCONTROLLER_NOTIFY_MSG_WILL_ROTATE) {

// 回転前準備通知

// 広告を非表示にする

_adView.hidden = YES;

}

}


// バナーを意図的に隠す

-(void) hideIAd

{

_adView.hidden = YES;

_isAllowShow = NO;

}


// バナーを表示する

-(void) showIAd

{

_adView.hidden = NO;

_isAllowShow = YES;

}


// 表示位置を得る

-(CGPoint) getShowPoint

{

CGPoint position = CGPointZero;

CGSize winSize = [[CCDirector sharedDirector] winSize];

switch (_framePosition) {

case iAdLayerPosition_Top_Center:

position = CGPointMake((winSize.width - _adView.frame.size.width) / 2, 0);

break;

case iAdLayerPosition_Botton_Center:

position = CGPointMake((winSize.width - _adView.frame.size.width) / 2, winSize.height - _adView.frame.size.height);

break;

default:

break;

}

return position;

}


// 広告ビューの生成

-(void) createIAd

{

}


// 広告ビューの解放

-(void) releaseIAd

{

}


@end


通知センターから画面回転に関する通知を受け取り、画面の回転に合わせて広告が移動するようにしています。

画面回転の通知を発行する箇所については今回は省きます。

次にNend広告のレイヤを作ります。


【NADViewLayer.h】

@interface NADViewLayer : AdLayerBase <NADViewDelegate>

{

    

}


@end


【NADViewLayer.m】

@implementation NADViewLayer


// 表示位置を指定して初期化する

+(id) nodeWithFramePosition:(eiAdLayerPosition)position

{

NADViewLayer* layer = [NADViewLayer node];

if (layer != nil) {

layer.FramePosition = position;

}

return layer;

}


// 広告ビューの生成

-(void) createIAd

{

// 広告ビューが生成済みの場合、一度解放する

[self releaseIAd];

// 広告ビューを初期化

_adView = [[NADView alloc] initWithFrame:CGRectMake(0, 0, NAD_ADVIEW_SIZE_320x50.width, NAD_ADVIEW_SIZE_320x50.height)];

[(NADView*)_adView setNendID:NAD_KEY spotID:NAD_ID];

[(NADView*)_adView setBackgroundColor:[UIColor clearColor]];

[(NADView*)_adView setDelegate:self];


     AppDelegate* delegate = (AppDelegate*)[UIApplication sharedApplication].delegate;

UINavigationController* rootViewController = delegate.navController;

[(NADView*)_adView setRootViewController:rootViewController];

// 広告位置の調整

CGPoint offset = [self getShowPoint];

_adView.frame = CGRectOffset(_adView.frame, offset.x, offset.y);

[rootViewController.view addSubview:_adView];

// 広告のロード

[(NADView*)_adView load:nil];

}


// 広告ビューの解放

-(void) releaseIAd

{

if (_adView != nil) {

[(NADView*)_adView setDelegate:nil];

[_adView removeFromSuperview];

[_adView release];

_adView = nil;

}

}


// 広告のロード成功時にコールされる

-(void) nadViewDidFinishLoad:(NADView*)adView

{

CCLOG(@"NAD Load Success");

}


@end


使い方は次の通りです。

CCLayer adLayer[NADViewLayer nodeWithFramePosition:iAdLayerPosition_Top_Center];

[self addChild:adLayer];


その他原語環境によってiAdやGoogleAdMobに適宜切換える事も考えられますので、コールするだけで適した広告レイヤを返してくれるFactoryクラスを設計するのも良いかもしれません。

こんにちは。開発担当のICTFです。

右に行ける時は右矢印、左に行ける時は左矢印といった具合に、状況によって表示するイメージを変えたいといったことは無いでしょうか。
同じ座標に2枚のCCSpriteを重ね、表示・非表示を切換える方法が楽ではありますが、フレームレートの保持やメモリがギリギリの時など少しでも節約したい場合には控えたい方法ですね。

今回は、1つのCCSpriteオブジェクト内で複数のテクスチャを表示する為の方法を紹介しようと思います。
紹介といっても、している事はCCSpriteの初期化処理と大差ありません。

まずは普通にCCSpriteオブジェクトを生成します。

CCSprite* sprite = [CCSprite spriteWithFile:@"image1.png"];


このspriteオブジェクトに表示するイメージを「image2.png」に変更するには、次の手順を記述します。

CCTexture2D* tex = [[CCTextureCache sharedTextureCache] addImage:@"image2.png"];

[sprite setTexture:tex];

CGRect rect = CGRectMake(0, 0, sprite.contentSize.widthsprite.contentSize.height);

[sprite setTextureRect:rect];


setTextureメソッドのみだとテクスチャの切換えが行なわれませんので、忘れずsetTextureRectメソッドもコールするようにしてください。
こんにちは。開発担当のICTFです。

今回は久しぶりにcocos2dの話題です。
CCSpriteなどにタッチイベントを持たせたい場合、CCTouchDispatcherを用いますね。
CCTouchDispatcherは非常に便利なクラスですが、ディスパッチャからオブジェクトを削除するタイミングを違えるとメモリリークの原因ともなります。

CCTouchDispatcherへの登録は、対象となるクラスがオブジェクトとして成立してから行なう必要があります。
init()内で登録を行なっても、正常にタッチイベントを受け取る事ができません。
オブジェクトとして成立した直後にフレームワークからコールされるメソッドとしてonEnter()というものがありますので、その中でCCTouchDispatcherへの登録を行なう必要があります。

またCCTouchDispatcherからの削除もdealloc()内で行なうと正しくタッチイベントの登録を解除する事ができません。
例えばボタンのイメージを表示しているCCSpriteをCCTouchDispatcherに登録しているとします。
そのCCSpriteのdealloc()内でCCTouchDispatcherからの削除処理を記述しているとした場合、どのようになるでしょうか。
dealloc()が呼ばれるのは、CCSpriteが親ノードからremoveされるタイミングです。
一見ボタンは画面から消えたように見えますが、CCTouchDispatcherからの削除とCCSpriteの解放処理が正しく行なわれずに、透明なオブジェクトが相変わらず画面上に存在する様なイメージになります。
ボタンは見えないのにタッチイベントだけはブロックされてしまい、なぜか思うようにタッチイベントの受信ができなくなるのです。
この問題を起こさない為に、dealloc()内でCCTouchDispatcherからの削除処理を記述するのではなく、dealloc()前にフレームワークからコールされるonExit()内で記述するようにします。

特にCCTouchDispatcherからの解放ミスについては、アプリが落ちやすくなるだけでなく、タッチイベントが異常動作をするという非常に分かり辛い現象となってしまいますので注意が必要です。
こんにちは。開発担当のICTFです。

coco2dでゲーム画面を作成しています。
ゲーム機能の1つとして写真を撮影する必要があり、RootViewControllerを親としてUIImagePickerControllerをModal表示していたのですが、困った現象が起こりました。
撮影画面を表示中に画面を回転させると、撮影画面自体は正常に動作するのですが、裏のcocos2dレイヤーが縦横比が狂った状態で固まってしまうのです。
ログビューにもOpenGLの描画失敗関連のエラーが大量に発生します。
画面全体が1枚の絵のようになってしまい、もちろん貼付けているボタンなども反応しません。
UIImagePickerControllerをModalではなく、AddSubviewした場合はcocos2dレイヤーに問題が発生しませんので、予想ですが恐らく撮影画面をModal表示する事でcocos2d側に画面回転の通知が届かなくなり、結果として「画面横のつもりで描画してみた⇒実は画面縦だった⇒エラー」という流れになっているのではないでしょうか。

上でAddSubviewだと問題無しという表現をしましたが、実はAddSubviewした場合撮影画面の動作がおかしくなってしまいます。
撮影画面を開いた状態で画面を回転させると、iPhoneに表示されている風景画像までもが回転してしまうのです。ですので、やはり撮影画面はModal表示する事が前提に作られているようです。

最終的に撮影画面を表示中は、cocos2d側の画面回転を禁止すれば良いという結論に至り、RootViewControllerに画面回転を抑制する為の機能を盛り込みました。
ついでに単純に画面回転を禁止するだけではなく、動的に「縦のみ」「横のみ」「全方向
」を切換えられるようにもしました。
どちらかというと画面回転抑制機能の実装が今回の主題に近いかもしれません。

RootViewController.hに画面の方向を指す以下の定数を列挙します。

typedef enum {

eOrientationMode_INVALID,

eOrientationMode_Full,

eOrientationMode_Portrait,

eOrientationMode_Landscape,

eOrientationMode_COUNT

} eOrientationMode;


INVALIDとCOUNTは単に私の癖ですので、無くても構いません。
次に、クラスの定義を以下のようにします。

@interface RootViewController : UIViewController

<

UIImagePickerControllerDelegate

, UINavigationControllerDelegate

>

{

BOOL m_isOrientationLock;

eOrientationMode m_OrientationMode;

}


@property (nonatomic, readwrite) BOOL isOrientationLock;

@property (nonatomic, readwrite) eOrientationMode OrientationMode;


isOrientationLockは画面方向のロック状態を表します。
このフラグがYESの場合、どのような状況でも画面回転を許可しません。
OrientationModeは上で定義した列挙子を用います。
Fullは、どの画面方向も許可します。
Landscapeは、画面が横の場合のみ許可します。
Portraitは、画面が縦の場合のみ許可します。

最後にRootViewController.mに画面回転制御の実処理を組み込みます。

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {

//

// There are 2 ways to support auto-rotation:

//  - The OpenGL / cocos2d way

//     - Faster, but doesn't rotate the UIKit objects

//  - The ViewController way

//    - A bit slower, but the UiKit objects are placed in the right place

//

#if GAME_AUTOROTATION==kGameAutorotationNone

//

// EAGLView won't be autorotated.

// Since this method should return YES in at least 1 orientation, 

// we return YES only in the Portrait orientation

//

return ( interfaceOrientation == UIInterfaceOrientationPortrait );

#elif GAME_AUTOROTATION==kGameAutorotationCCDirector

//

// EAGLView will be rotated by cocos2d

//

// Sample: Autorotate only in landscape mode

//

if( interfaceOrientation == UIInterfaceOrientationLandscapeLeft ) {

[[CCDirector sharedDirector] setDeviceOrientation: kCCDeviceOrientationLandscapeRight];

} else if( interfaceOrientation == UIInterfaceOrientationLandscapeRight) {

[[CCDirector sharedDirector] setDeviceOrientation: kCCDeviceOrientationLandscapeLeft];

}

// Since this method should return YES in at least 1 orientation, 

// we return YES only in the Portrait orientation

return ( interfaceOrientation == UIInterfaceOrientationPortrait );

#elif GAME_AUTOROTATION == kGameAutorotationUIViewController

//

// EAGLView will be rotated by the UIViewController

//

// Sample: Autorotate only in landscpe mode

//

// return YES for the supported orientations

if (m_isOrientationLock) {

return NO;

}

switch (m_OrientationMode) {

case eOrientationMode_INVALID:

return NO;

break;

case eOrientationMode_Full:

return YES;

break;

case eOrientationMode_Portrait:

return ( UIInterfaceOrientationIsPortrait(interfaceOrientation) );

break;

case eOrientationMode_Landscape:

return ( UIInterfaceOrientationIsLandscape( interfaceOrientation ) );

break;

default:

return NO;

break;

}

#else

#error Unknown value in GAME_AUTOROTATION

#endif // GAME_AUTOROTATION

// Shold not happen

return NO;

}


使い方は、UIImagePickerCoontrollerをModal表示する前にRootViewController.isOrientationLockにYESを設定し、撮影画面が消え次第NOに戻すだけです。
こんにちは。開発担当のICTFです。

iAd(広告)をアプリに組み込む場合、通常は複数の画面にわたって実装しますよね。
さらにiAdの表示を行なう為にはcocos2dフレームワーク外の仕組みを使わねばなりません。
cocos2dフレームワーク外という事は、ある画面でiAdを表示している状態で次の画面に遷移した場合、フレームワーク外のiAdはそのまま残ってしまうという事です。
ある意味画面をまたいで表示し続けられるのは利点とも受け取れますが、iAdを表示したくないメインゲーム画面などに残ってしまい、大切なパラメータが隠されてしまうという不具合の原因にもなり得ます。
そこで今回は1つのCCLayerにiAdの表示から消去までの仕組みをすべて乗せてしまいたいと思います。(以下iAdLayerと呼びます)
使い方のイメージは、iAdを表示したい画面でiAdLayerをaddChildするだけです。
iAdの消去はiAdLayerが解放されるタイミングで自動的に行なわれます。

[iAdLayer.h]

// iAd表示用のレイヤ

@interface iAdLayer : CCLayer 

<ADBannerViewDelegate>

{

    ADBannerView* m_AdView;

}


@property (nonatomic, retain) ADBannerView* AdView;


@end


ヘッダファイルにはiAdを表示する為のビュークラスを追加します。

またコールバックを受け取るため、ADBannerViewDelegateプロトコルを実装する必要があります。


[iAdLayer.m]

-(id) init

{

if (self = [super init]) {

// 通知センタのオブザーバ登録

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(NotifyFromNotificationCenter:) 

name:nil object:nil];

m_AdView = nil;

m_prevOrientMode = eOrientationMode_Full;

[self createIAd];

}

return self;

}


-(void) dealloc

{

// 通知センタのオブザーバ登録を削除する

[[NSNotificationCenter defaultCenter] removeObserver:self];

[self releaseIAd];

[super dealloc];

}


init中でiAdの生成処理「createIAd」をコールし、dealloc中でiAdの解放処理「releaseIAd」をコールしています。

後はこの2つのメソッドを実装すれば、iAdLayerを貼付けるだけで広告の実装完了という仕組みを実現できます。


// 広告ビューの生成

-(void) createIAd

{

// 広告ビューが生成済みの場合、一度解放する

[self releaseIAd];

RootViewController* rootVC = [CommonFunctions getRootViewController];

// 広告ビューを初期化

self.AdView = [[ADBannerView alloc] initWithFrame:CGRectZero];

self.AdView.delegate = self;

self.isBannerVisible = YES;

UIInterfaceOrientation orientation = rootVC.interfaceOrientation;

float h = 0;

if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown) {

self.AdView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierPortrait;

h = rootVC.view.frame.size.height;

}

else {

self.AdView.currentContentSizeIdentifier = ADBannerContentSizeIdentifierLandscape;

h = rootVC.view.frame.size.width;

}

// 画面の下部に表示

self.AdView.frame = CGRectOffset(m_AdView.frame, 0, h - m_AdView.frame.size.height);

[[[CCDirector sharedDirector] openGLView] addSubview:m_AdView];

}


// 広告ビューの解放

-(void) releaseIAd

{

if (m_AdView != nil) {

[m_AdView removeFromSuperview];

[m_AdView release];

self.AdView = nil;

}

}


createIAd内で紹介していないメソッドなどが登場しますが、これはデバイスの向きを調べ、それに合わせた広告の配置を行なう為のものです。

また、前述のinit内で通知センタへの登録を行なっていますが、これはデバイスの向きが変わった事を知る為の登録です。


// 通知センタからの通知イベント

-(void) NotifyFromNotificationCenter:(NSNotification*)notification

{

if (notification.object == nil) {

return;

}

if (notification.name == ROOTVIEWCONTROLLER_NOTIFY_MSG_ROTATE) {

// 画面回転通知

// 広告ビューの再生成

[self createIAd];

}

}


rootViewController内でデバイスの向きが変わった事を検知し、
ROOTVIEWCONTROLLER_NOTIFY_MSG_ROTATEメッセージを発行しています。

iAdLayerでそのメッセージを受け取った時に広告ビューを再生成する事で動的なデバイス回転に対応できるようになります。


少し1つの機能をCCLayerに盛り込むと汎用性が高くなるという話題から逸れてしまいましたが、CCLayerはとても便利なクラスです。何も目に見えるもの以外は実装に向いていない訳ではないと思います。


例えばDBにアクセスする為、色々な画面で用いられるSQL文(ユーザ認証当たりが該当するのではないでしょうか)の発行から処理までの一連の流れをCCLayerに実装し、使いたい場面でそのレイヤを貼付けるというのはどうでしょうか?

貼付けたタイミングでSQLが発行され、処理が終了したタイミングで自動的にremoveFromParentAndCleanupされる訳です。


1つ注意点として、CCLayerのフレームワークに従うという事は、シーンが変わるとレイヤが解放される事は基本的に避けられないという事です。

重要な処理を乗せたレイヤを動かしている場合、画面遷移をブロックする処理が必要となるでしょう。

これは今回の話に限りませんね。

こんにちは。開発担当のICTFです。

iPhoneで撮影した画像をそのまま画面に貼付ける処理を実装していたのですが、少し困った事がおこりました。
まず前提として、どのサイズの画像でも画面内に表示できるよう同じ縮尺で拡大縮小する機能を盛り込んでいます。

もちろんiPhoneカメラで撮影した場合も上記の処理を通過する訳ですが、そもそも同じ画面サイズで撮っているのであれば何の影響も無いと考えていました。
iPadだと確かに問題なかったのですが、iPhoneの場合問題がありました。
実機を縦にして撮影しているのですが、得られる画像は横長なんです。
iPhoneの撮影画面で見えている画像の両脇部分まで実は写真になっていたのですね。
そしてこの横長画像を画面に貼付けた場合、画像の拡大縮小機能により画面の上下に空白が生まれ、且つそもそも撮影した時とは別のイメージ(両脇の見えてなかった部分です)になってしまいます。

どうやら実機を縦にしても横長画像として取得されるのは仕様のようで、イメージ通りの画像として扱う為には加工する必要がありました。
加工の手順としては、
1.縦の画面サイズに合わせた縮尺で画像を縮小する
2.横の画面サイズに合わせて画像を切り取る
となります。
ソースは以下の通りです。

// 画像選択画面で画像が選択された

-(void)imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info

{

CGSize winSize = [[CCDirector sharedDirector] winSize];


// 画像を取得する

UIImage* image = [info objectForKey:UIImagePickerControllerEditedImage];

if (!image) {

image = [info objectForKey:UIImagePickerControllerOriginalImage];

}


// 取得した画像サイズを画面内に収まる大きさに調整する

CGImageRef imageRef = [image CGImage];

size_t w = CGImageGetWidth(imageRef);

size_t h = CGImageGetHeight(imageRef);

size_t resizeW, resizeH;


// iPhoneの撮影はかならず横長になる為、縦長基準で縮小後に横を切り取る

resizeH = winSize.height;

resizeW = w * resizeH / h;

size_t cutW = winSize.width

UIGraphicsBeginImageContext(CGSizeMake(cutW, resizeH));

[image drawInRect:CGRectMake(0, 0, cutW, resizeH)];

image = UIGraphicsGetImageFromCurrentImageContext();

UIGraphicsEndImageContext();

}


後はUIImageであるimageをCCSpriteで読み込んで画面に貼付ければ、無事完了ですね。

こんにちは。開発担当のICTFです。
今回は少しハマったので、iPad上でcocos2dからUIImagePickerControllerを
表示する為の方法を書こうと思います。

UIImagePickerControllerはUIViewControllerを継承するクラスです。
大抵のサンプルコードでcocos2d上からUIViewControllerの表示は

[[[Director sharedDirector] openGLView] addSubview:viewController.view];

とすれば良いとあるのですが、UIImagePickerControllerでこれを行なった場合、SIGBARTエラーで落ちてしまいます。

iPadは画面が広いので、UIViewControllerも全画面に表示するのは無く、必要な領域に表示するべき。という考え方があるらしく、どうやらポップアップで表示する為にUIPopverControllerにUIImagePickerControllerを配置した後、UIPopverControllerを画面に置く事で実現するようです。
以下実装コードになります。

-(void) showChooseMyPic

{

CGSize winSize = [[CCDirector sharedDirector] winSize];

if (m_ImagePickerController == nil) {

// 画像選択画面の初期化

UIImagePickerControllerSourceType sourceType = UIImagePickerControllerSourceTypePhotoLibrary;

if ([UIImagePickerController isSourceTypeAvailable:sourceType]) {

m_ImagePickerController = [[UIImagePickerController alloc] init];

m_ImagePickerController.delegate = self;

m_ImagePickerController.sourceType = sourceType;

m_ImagePickerController.wantsFullScreenLayout = YES;

m_UIPopoverController = [[UIPopoverController alloc] initWithContentViewController:m_ImagePickerController];

m_UIPopoverController.delegate = self;

[m_UIPopoverController setPopoverContentSize:winSize animated:NO];

}

}

// 表示

CGRect r = CGRectMake(20,20,10,10);

r.origin = [[CCDirector sharedDirector] convertToGL:r.origin];

[m_UIPopoverController presentPopoverFromRect:r inView:[[CCDirector sharedDirector] openGLView] permittedArrowDirections:UIPopoverArrowDirectionDown animated:YES];

}


// 画像選択キャンセル

- (void)imagePickerControllerDidCancel:(UIImagePickerController *)picker

{

// PickerControll周りの解放を行なう

[self releasePicker];

}


//画像選択ポップアップの外側をタップし、画像選択画面を抜けた場合

- (void)popoverControllerDidDismissPopover:(UIPopoverController *)popoverController

{

// PickerControll周りの解放を行なう

[self releasePicker];

}


// PickerController周りの解放

-(void) releasePicker

{

[m_ImagePickerController dismissModalViewControllerAnimated:YES];

[m_ImagePickerController.view removeFromSuperview];

[m_ImagePickerController release];

m_ImagePickerController = nil;

[m_UIPopoverController dismissPopoverAnimated:YES];

[m_UIPopoverController release];

m_UIPopoverController = nil;

}


Twitterボタン
Twitterブログパーツ