2012年9月アーカイブ

こんにちは。開発担当の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です。

iOS6になって、以前画面回転の制御に使っていたshouldAutorotateToInterfaceOrientationはコールされなくなりました。
新たに導入された仕組みを使って画面回転制御を行なう必要がありますが、その方法については既に様々なサイトで紹介されていますので、「紹介通りに実装したのに上手く回転しない!」場合にチェックすべき項目について書こうと思います。

チェックポイント1:
AppDelegateのself.windowにビューをaddSubViewしていませんか?
古いバージョンから存在するプロジェクトをiOS6対応する場合、このような作りになっている可能性があります。

[self.window addSubview:rootViewController.view];

一見画面は正常に表示されますが、この方法では画面回転制御の新しい仕組みが働きません。
もし上記の書き方をしている場合、次のように書き替えて下さい。

self.window.rootViewController = rootViewController;


チェックポイント2:
Info.plistで設定するSupported Interface Orientationsの設定は合っていますか?
以前はあって無いようなものだったこの設定値がiOS6から生きてきます。
ここでデバイスの向きを有効化していないと、いくらコードを弄っても画面は回転してくれませんので注意が必要です。
Info.plistのSupported Interface Orientationsは、プロジェクトマネージャ内でプロジェクトを選択し、Summaryタブを選択する事GUIでの入力が可能です。
スクリーンショット 2012-09-29 2.44.21.png
上の画像では横方向2種類が選択状態になっています。

チェックポイント3:
AppDelegateのself.window.rootViewControllerにUINavigationControllerを設定していませんか?
もちろんナビゲーションベースのアプリを作る場合にrootViewControllerにUINavigationControllerを設定する事は間違いではありません。
しかしiOS6の仕様として、「UINavigationControllerに追加された子UIViewControllerには画面回転制御のコールバックがされない」というものがあります。
つまり、いくらUIViewControllerに画面回転制御を実装してもコールバックされない為思ったように回転制御が出来ない訳です。
UINavigationControllerのサブクラスを作り、そこに画面回転制御を組み込んでも構いませんし、次のようにUINavigationControllerクラス自体を拡張しても良いかもしれません。

@implementation UINavigationController (Rotation)


- (NSUInteger)supportedInterfaceOrientations{

    return [self.viewControllers.lastObject supportedInterfaceOrientations];

}


- (BOOL)shouldAutorotate{

    return [self.viewControllers.lastObject shouldAutorotate];

}


- (UIInterfaceOrientation)preferredInterfaceOrientationForPresentation{

    return [self.viewControllers.lastObject preferredInterfaceOrientationForPresentation];

}


@end


上の例では、回転制御を現在表示中の子画面に渡しています。

こうする事で画面ごとに回転制御を行なう事が可能です。

アプリ内で回転制御を細かく分ける必要がない場合、UINavigationControllerから直接値を返すようにした方が楽かもしれません。

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

これまでiPhoneといえば画面の大きさは1種類でした。(Retinaか否かという差はありました)
画面の大きさが予め固定ですので、動的にUIを配置する際も座標の決定タイミングを余り気にする必要はありませんでした。
画面がロードされたタイミングにコールバックされるviewDidLoad内にUIの生成と配置を行なっている方も多いのではないでしょうか。

しかしiPhone5の登場により、2種類の画面サイズでUIが正しく配置されるように気をつける必要が出てきました。
画面の種類が増えた事により、UIの座標を設定するタイミングに気をつける必要が出てきました。
例えば、viewDidLoad内で画面の下部に広告ビューを表示するコードを書いてみる事にします。
xibはiPhone4の画面サイズを基準に設計しています。
スクリーンショット 2012-09-27 2.51.24.png
画面下部に50pxに余白を設けています。テーブルビューは、画面の大きさに関わらず、必ず画面下部に50pxの余白を作るように設定しています。
この余白に広告ビューを表示します。
viewDidLoad内に次のコードを記述します。
※サンプルでは実際の広告を表示するのではなく、広告に見立てたad.pngを表示しています。

- (void)viewDidLoad

{

    [super viewDidLoad];

// 広告ビューを画面下部に生成する

UIImageView* adView = [[[UIImageView alloc] initWithFrame:CGRectMake(0, self.view.frame.size.height - 50, 320, 50)] autorelease];

[adView setImage:[UIImage imageNamed:@"ad.png"]];

[self.view addSubview:adView];

}


まずiPhone4で実行してみます。
2012-09-27 03.13.23.png
期待通りに表示されました。もともとxibをiPhon4の大きさで設計していますし、これまで通りの結果です。
次にiPhone5で実行してみます。
2012-09-27 03.16.23.png
広告が最下部に表示されていないどころか、広告の下からテーブルビューがはみ出す程上部に表示されてしまっています。
なぜviewDidLoadで上手く座標の設定が出来ないのかを追ってみましょう。
viewDidLoad内に次のログを仕込んでみて下さい。

NSLog(@"ViewHeight: %f", self.view.frame.size.height);


iPhone5で次のログ出力結果を見てみると、次のようになっています。

ViewHeight: 460.000000

iPhone5の縦サイズは548ですので正しい結果が得られていません。460はiPhone4の大きさになりますので、広告はiPhone4の画面サイズから計算して配置していた事になります。
viewDidLoadがコールされるタイミングではまだ画面がデバイスに合わせて拡張されておらず、期待通りのサイズが得られないようです。

iPhone5でも期待通りの位置にUIを配置するには、次のように記述します。

@interface ViewController ()

{

UIImageView* _adView;

}

@end


@implementation ViewController


- (void)viewDidLoad

{

    [super viewDidLoad];

// viewDidLoadでは、広告の生成のみ行なう。座標は気にしない。

_adView = [[[UIImageView alloc] initWithFrame:CGRectMake(0, 0, 320, 50)] autorelease];

[_adView setImage:[UIImage imageNamed:@"ad.png"]];

[self.view addSubview:_adView];

}


- (void)viewWillAppear:(BOOL)animated

{

[super viewWillAppear:animated];

// 広告の座標を設定する

CGRect adViewFrame = _adView.frame;

adViewFrame.origin = CGPointMake(0, self.view.frame.size.height - adViewFrame.size.height);

_adView.frame = adViewFrame;

}

これでiPhone5でも正しい位置に広告が表示されるようになりました。
2012-09-27 03.30.05.png
ポイントはviewDidLoadではUIの生成処理のみ行ない、viewWillAppearでは座標の設定のみ行なうという事です。
viewWillAppear内で生成処理を行なうと、画面を表示する度に広告が生成されてしまい、メモリが足りなくなる可能性があるので注意して下さい。
こんにちは。開発担当のICTFです。

UINavigationControllに複数のUIViewControllを追加すると、2画面目からナビゲーションバーの左側に自動的に戻るボタンが追加されますよね。
今回はこの自動的に追加された戻るボタンを「動的に」非表示にする方法をご紹介しようと思います。
スマートな方法ではないので、もし良い方法をご存知の方がいらっしゃいましたら是非ご教示くださいませ。

navigationItem.leftBarButtonItemにUIBarButtonItemを設定すると、自動追加の戻るボタンを上書きできるという仕様を利用します。
透明で操作ができないボタンを用意して、それをleftBarButtonItemに設定するだけですね。
コードは次のようになります。

ーーー 自動追加の戻るボタンを隠す ーーー

UIView* tempView = [[[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 10)] autorelease];

UIBarButtonItem* tempButton = [[[UIBarButtonItem allocinitWithCustomView:tempView] autorelease];

tempButton.enabled = NO;

self.navigationItem.leftBarButtonItem = tempButton;


ーーー 自動追加の戻るボタンを再表示する ーーー

self.navigationItem.leftBarButtonItem = nil;


少し時間のかかる処理をしている最中、画面を戻られたら困る時などに如何でしょうか。
Icon-72@2x.png

ビジュアライザーシリーズ第4弾 「Visualizer series Vol.4 c」が本日発売開始です!
あなたの好きな音楽と共に、宇宙旅行をお楽しみ下さい。
mzl.nsyinxuv.png
mzl.vkynlktb.png

Visualizer series 公式サイト

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


今回は、iPhoneアプリにEvernote連携機能を組み込み、新規ノートをアップロードするまでの手順を紹介します。


まず、Evernoteデベロッパーサイトを表示します。

http://dev.evernote.com/intl/jp/documentation/cloud/


サイトが表示されたら、最初の手順である「APIキーの取得」を行ないます。

スクリーンショット 2012-09-19 0.18.33.png
「API キーの取得>」リンクをクリックするとアプリ情報の入力画面が開くので、入力を完了して「申請する」ボタンをクリックして下さい。
申請が完了すると、「Consumer Key」と「Consumer Secret」を取得できます。
この2項目はアプリに機能を実装する上で重要な項目となりますので、紛失しないようにしてください。

APIキーの取得が終わったら、手順2であるSDKのダウンロードに移ります。
リンクをクリックするとGitHubに移動しますので、iOS用SDKのリンクをクリックします。
スクリーンショット 2012-09-19 0.54.21.png
リンクを飛んだ先のページ上部にある「↓ZIP」ボタンをクリックすると、iOS用SDKのダウンロードが開始するはずです。
スクリーンショット 2012-09-19 0.55.31.png
次に手順3であるサンドボックス環境でのアプリ開発に移ります。
XCodeプロジェクトに先ほどダウンロードしたSDKの「evernote-sdk-ios」フォルダを丸ごと追加して下さい。
※EvernoteSDKはARCに対応していません。MRCプロジェクトであれば問題ありませんが、ARCプロジェクトの場合はSDKのすべてのソースにMRCコンパイルオプションを適用する必要がありますので注意して下さい。

さらに「Security.framework」を追加します。
スクリーンショット 2012-09-19 1.03.26.png
これで準備は完了です。
ソースコードの追加に移ります。
まず、先ほど取得したキー情報でEvernoteSessionを初期化します。
アプリ起動後1回初期化できれば問題無いので、AppDelegate内で問題無いでしょう。
AppDelegate.mにEvernoteSDK.hをインポートします。

#import "EvernoteSDK.h"


- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptionsに次の記述を追加します。

    // リリース前に@"www.evernote.com"に変更すること!

    NSString *EVERNOTE_HOST = @"sandbox.evernote.com";

    NSString *CONSUMER_KEY = @"取得したConsumer Keyを記述します";

    NSString *CONSUMER_SECRET = @"取得したConsumer Secretを記述します";

    // set up Evernote session singleton

    [EvernoteSession setSharedSessionHost:EVERNOTE_HOST

                              consumerKey:CONSUMER_KEY

                           consumerSecret:CONSUMER_SECRET];


初期化処理はこれで完了です。
最後にログイン処理を実装します。
Evernoteへのログインは、アップロードしようとするタイミングや、あるいはログインボタンを追加する事などが考えられます。開発するアプリに適したIFを実装してください。
サンプルではアップロードしようとするタイミングにログイン処理を実装します。

// 計算結果をEvernoteに新規メモ登録する

-(void) addEvernote

{

EvernoteSession* session = [EvernoteSession sharedSession];

if (session.isAuthenticated == NO) {

// 未ログインであれば、ログイン処理を行なう

[session authenticateWithViewController:self completionHandler:^(NSError *error) {

if (error || !session.isAuthenticated) {

// ログインエラー処理を記述します(メッセージ表示など)

} else {

// ログイン完了

NSLog(@"Evernoteにログイン完了 noteStoreUrl:%@ webApiUrlPrefix:%@", session.noteStoreUrl, session.webApiUrlPrefix);

[self addEvernote];

}

}];

return;

}

// プレーンテキストを得る

NSString* text = [self getText];

// プレーンテキストをENML形式に変換する

NSMutableString* enml = [NSMutableString string];

[enml setString:@"<?xml version=\"1.0\" encoding=\"UTF-8\"?>"];

    [enml appendString:@"<!DOCTYPE en-note SYSTEM \"http://xml.evernote.com/pub/enml.dtd\">"];

[enml appendString:@"<en-note>"];

NSRange range = NSMakeRange(0, text.length);

NSRange lineRange;

NSString* lineString;

while (range.length > 0) {

// 改行コードかあるいは文字列の終端までを読み込み、ENML形式に変換する

lineRange = [text lineRangeForRange:NSMakeRange(range.location, 0)];

lineString = [text substringWithRange:lineRange];

NSLog(@"line: %@", lineString);

range.location = NSMaxRange(lineRange);

range.length -= lineRange.length;

if ([lineString isEqualToString:@"\n"]) {

// 改行のみの場合、<br />に変換する

lineString = @"<br />";

}

else {

// 改行以外の文字が含まれる場合、改行コードを削除する

lineString = [lineString stringByReplacingOccurrencesOfString:@"\n" withString:@""];

}

// 文字列の両端に<div> </div>を連結する

[enml appendFormat:@"<div>%@</div>", lineString];

}

[enml appendString:@"</en-note>\n"];

// tag情報の作成

NSArray* tagList = [NSArray arrayWithObjects:@"好きなタグを記述して下さい", nil];

// noteオブジェクトの生成

    EDAMNoteAttributes *newNoteAttributes = [[[EDAMNoteAttributes alloc] init] autorelease];

    EDAMNote *newNote = [[[EDAMNote alloc] init] autorelease];

    [newNote setTitle:_template.title];

    [newNote setContent:enml];

    [newNote setTagNames:tagList];

    [newNote setAttributes:newNoteAttributes];

    [newNote setCreated:(long long)[[NSDate date] timeIntervalSince1970] * 1000];

    // noteを追加する

    EvernoteNoteStore *noteStore = [EvernoteNoteStore noteStore];

    [noteStore createNote:newNote

                  success:^(EDAMNote *note) {

// アップロード成功時処理(メッセージ表示など)

                  }

                  failure:^(NSError *error) {

        // アップロード失敗時処理(メッセージ表示など)

NSLog(@"createNote error %@", error);

                  }];

// アップロードファイルのサイズによっては、ここで「アップロード中」表示を行なった方がよいかもしれません。

}


addEvernoteメソッドは、Evernoteへアップロードする為のIFが操作された際にコールされます。(addEvernoteはサンプルで使用している独自のメソッドなので、各自実装する必要があります。)
まずログイン状態であるかをチェックし、未ログインであればauthenticateWithControllerメソッドをコールしてログインを誘導します。
このメソッドはGCDで動作し、ログイン結果はブロックで受け取ります。
ログイン処理自体は非同期で行なわれますので、ここで一旦addEvernoteメソッドを終了します。
ログイン処理が終了するとブロック内の処理が動作しますので、もう一度ログイン状態を確認し、ログイン状態であるならば再度addEvernoteメソッドをコールしています。

getTextメソッドコールしている箇所から新規ノートをアップロードする為の処理になります。
getTextメソッドは、アップロードしたいメモ情報をプレーンテキストで取得する為のメソッドです。(getTextメソッドはサンプルで使用している独自メソッドですので、各自実装する必要があります。)
取得したプレーンテキストはそのままではEvernoteのドキュメントとして認められません。
Evernote独自の書式であるENML形式(ほぼHTML)に変換する必要があります。
プレーンテキストを1行ずつ読み取り、whileループでENML形式への変換を行っています。

tag情報はNSArrayで作成します。

Evernoteのnoteオブジェクトを生成します。
noteの属性はEDAMNoteAttributes、noteはEDAMNoteクラスを用います。
noteオブジェクトに各プロパティと属性クラスを追加した後、EvernoteNoteStoreのcreateNoteメソッドをコールします。
このメソッドもGCDであり、非同期にアップロードが行なわれます。
アップロード処理が終了するとブロック内が処理されます。
回線の状況やアプロードファイルのサイズによっては時間がかかる処理となりますので、createNoteメソッドをコールした後に「アップロード中」である旨の表示処理を行なった方が良いかもしれません。

アプリの開発とサンドボックスでの試験が完了したら、手順4であるAPIキーのアクティベートを行ないます。
リンクをクリックすると必要事項の入力画面に移りますので、入力を完了して申請して下さい。
私の経験ですが、APIキーの作成2日後にアクティベート申請を出したところ、
お使いのAPIキーは今週発行したばかりのものです。お手数ですが、サンドボックス上でのテストにもう少し時間をお使い頂き、その上でプロダクションへの移行のためのご依頼を頂けますと幸いです。」
という返信を頂き、アクティベートを認められませんでした。
APIの作成から1週間程時間を置いて申請した方が無難かもしれません。

アクティベートが無事終了したら、EVERNOTE_HOSTの値を忘れずに書き換えて下さい。
折角Evernote連携機能を追加したアプリが市場に出たのに、アップロード先がサンドボックスなのでは悲しすぎますからね。
こんにちは。開発担当のICTFです。

cocos2d version2.0に対応した解説書「cocos2dで作るiPhoneゲーム」が本日発売です!


現時点でversion2.0に対応している和書はこの1冊です。
内容はこれからcocos2dを始めたい方向けとなっています。
既に使い込まれている方には物足りないかもしれませんが、version2.0で追加された新機能についても解説していますので、宜しければ手に取ってみて下さい。

本書を最後まで読む事で、15パズルゲームを作る事ができるようになります。
初めてcocos2dを触れる方でもスムーズに理解できるよう、cocos2dの各機能についてできる限り丁寧に解説していますので、是非々々読んでみて下さい!
こんにちは。開発担当のICTFです。

数日前の記事ですが、日経BP様のサイトで弊社の「RelationalVoiceRecorder」が取り上げられました。

http://pc.nikkeibp.co.jp/article/column/20120827/1060986/?rt=nocnt

スクリーンショット 2012-09-08 16.12.59.png

「これで決まりの録音アプリ」とまで評価して頂きました!

RelationalVoiceRecorderはこれからも継続してバージョンアップを重ねていく予定です。
今後さらに使いやすく高機能を目指して参りますので、どうぞご期待下さいませ。

記事にもありますが、無料で使える「RelationalVoiceRecorder Lite」がございますので、まずはお試し下さい。
こんにちは。開発担当のICTFです。
iOS3までアニメーションの記述はbeginAnimations:context:で始まり、commitAnimationsで終えていました。
仕組み自体は難しい訳ではなかったのですが、単純なアニメーションでも結構な量の行数が必要であったりとスマートさがありませんでした。

iOS4からanimateWithDuration:animations:というメソッドが追加され、非常に分かりやすい記述が可能になっています。

[UIView animateWithDuration:アニメーションさせる秒数を設定します

    animations:^{

        アニメーションの内容を記述します

    } 

    completion:^(BOOL finished){

        アニメーション終了後の処理を記述します

    }];


ブロック構文で処理を記述できるようになり、セレクタで指定する為だけにメソッドを用意する必要がなくなったのは大きいのではないでしょうか。


尚、beginAnimations:context:とcommitAnimationsを用いた記述はiOS4以降非推奨とされていますので、できるだけ早く新しい構文に慣れた方が良いかもしれません。

Twitterボタン
Twitterブログパーツ