スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

CocosBuilderでiOS独自の関数を呼び出したい

これは、実は僕もちゃんとした方法を使ってないのかもしれませんが、それでも一つの方法ということで。ネット上に情報が少ないですし。

まず、通常と同様にxcodeでcocos2d for javascriptのプロジェクトを作っているものとします。(1)

んで、普通にObjective-CでStoreKit周りの処理を描きます。(2)

最後に、他のcocos2d等と同じようにjsbindingsに入れ込みます。(3)

今回はこの内容をざっくりと。
とりあえず(1)は良いとして、(2)ですが、適当にクラスを作ります。

MyPayment.h、MyPayment.mを以下の感じで。

// .h
@interface MyPayment : NSObject <SKProductsRequestDelegate>
+ (MyPayment*) node;
- (void)startBuy:(int)product_idx;
@end

// .m
@implementation MyPayment
- (id) init {
 self = [super init];
 if (!self) return NULL;
 return self;
}
- (void) dealloc {
 [super dealloc];
}
+ (MyPayment*) node {
 return [[MyPayment alloc] init];
}
- (void)startBuy:(int)product_idx {
 // 購入処理
 SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:[NSSet setWithObject:product_id]];
 request.delegate = self;
 [request start];
}
@end

ちゃんとした購入処理は各自実装するとして、今回は流れだけ。
この2ファイルは、プロジェクトフォルダ内にあるlibsに「MyPayment」というフォルダを作り、そこに入れていると仮定して進めます。


そして、(3)の部分です。

「libs/jsbindings/configs」に「MyPayment」というフォルダを作り、中に以下のファイルを作ります。

MyPayment_jsb.ini
(CocosBuilderReader_jsb.iniをコピペして、以下項目を適当に修正)

[MyPayment]
obj_class_prefix_to_remove = My
classes_to_parse = MyPayment
classes_to_ignore = NS(.*), SK(.*)
import_files = jsb_NS_manual.h,
MyPayment.h
method_properties = MyPayment # node = name:"create",
bridge_support_file = MyPayment.bridgesupport
complement_file = MyPayment-complement.txt

gen_MyPayment.sh

#!/bin/sh

cd プロジェクトのパス/libs/MyPayment
gen_bridge_metadata -F complete --no-64-bit -c '-DNDEBUG -I.' *.h -o プロジェクトのパス/libs/jsbindings/configs/MyPayment/MyPayment.bridgesupport
プロジェクトのパス/libs/jsbindings/generate_complement.py -o プロジェクトのパス/libs/jsbindings/configs/MyPayment/MyPayment-complement.txt *.h
プロジェクトのパス/libs/jsbindings/generate_jsb.py -c プロジェクトのパス/libs/jsbindings/configs/MyPayment/MyPayment_jsb.ini

shファイルは今後のために作っておきます。要は、ObjectiveCのヘッダファイルや設定(ini)ファイルを参考に、Javascriptに組み込めるファイルを出力してくれます。ちょっと難しく言うと、Javascript側をタダのラッパーと考えて、内部的には高速に実行出来るObjective-Cが呼ばれるようにしてくれるライブラリがあって、それに必要なファイルを作るのです。

で、ターミナルでgen_MyPayment.shを実行してうまく行けば色々とファイルが出力されますので、それを全てxcodeに追加します。

もう少しです。

今度は、以下のファイルを作ります。作る場所は、自動で出力されたファイルと同じであり、最初にクラスファイルを作ったフォルダが良いと思います。

jsb_MyPayment_registration.h

#ifndef __JSB_MYPAYMENT_REGISTRATION
#define __JSB_MYPAYMENT_REGISTRATION

void jsb_register_MyPayment( JSContext *globalC, JSObject *globalO);

#endif // __JSB_MYPAYMENT_REGISTRATION

jsb_MyPayment_registration.mm

#import "jsb_config.h"
#import "jsb_core.h"
#import "jsb_MyPayment_registration.h"

void jsb_register_MyPayment( JSContext *_cx, JSObject *object)
{
 JSObject *myPayment = JS_NewObject(_cx, NULL, NULL, NULL);
 jsval myPaymentVal = OBJECT_TO_JSVAL(myPayment);
 JS_SetProperty(_cx, object, "myP", &myPaymentVal);

#import "jsb_MyPayment_classes_registration.h"
}

これで準備はほぼ整いましたので、ついに既存のファイルに組み込んで行きます。
「libs/jsbindings/src/manual」内の一部を変更します。

jsb_config.hに、以下の3行を追加。JSB_INCLUDE_COCOSBUILDERREADERの下辺りが良いでしょうか。

#ifndef JSB_INCLUDE_MYPAYMENT
#define JSB_INCLUDE_MYPAYMENT 1
#endif // JSB_INCLUDE_MYPAYMENT

jsb_core.mmの頭、importしてるそれらしき部分に以下を追加。

#import "jsb_MyPayment_registration.h"

同じファイルのJSB_NewGlobalObject関数内のそれっぽいところに、以下3行を追加。

#if JSB_INCLUDE_MYPAYMENT
 jsb_register_MyPayment(cx, glob);
#endif // JSB_INCLUDE_MYPAYMENT

最後の最後に、Javascriptを入れます。
「libs/jsbindings/src/js」内に、以下ファイルを追加。

jsb_mypayment.js

var myP = myP || {};

myP.Payment = function() {
 return myP.myPayment.create();
};

で、jsb.jsの最後に以下の1行を追加。
require('jsb_mypayment.js');

忘れてはならないのが、.jsファイルはコンパイル側に入ってしまうので、ビルドフェーズでコンパイル側から消し、リソース側に追加しとくことです。

なが~くなりましたが、これでCocosBuilder側のJavascriptで

myP.Payment().startBuy("プロダクトID");

を呼べば購入処理が行えます。

今回、自分が色々と作ったものを切り出した感じで書いてしまったため、要らないものも多々あると思います。ソースもほぼ手書きなので誤字脱字あったらごめんなさい。

この手順は最初だけで、次回からはクラスに関数を追加したらターミナルでshして終了です。JavascriptとObjective-C側でやり取りを行なったりしたい場合はiniファイル含めもうちょっと複雑になりますが、CocosBuilderやCocosDenshionが参考になります。

StoreKitを組み込んだ際、購入完了後にJavascript側で作ったコールバック関数を呼びたい!って事態になると思いますが、これこそ自分のやり方が間違ってる気がしてならない部分です。

以下は超メモ的に。

クラス側はこんな感じで
@interface MyPayment {
void (^block)(id sender);
}
- (void)setCompletedPaymentCallbackBlock:(void(^)(id sender))b;
@end

manual.mm側では登録用の関数用意して、処理内容を抜粋すると以下の感じ。
js_block js_func;
JSB_jsval_to_block_1( cx, argvp[1], js_this, &js_func );

MyPayment *real = (MyPayment*) [proxy realObj];
[real setCompletedPaymentCallbackBlock:(void(^)(id sender))js_func];

って感じで直接関数を保存しちゃって、StoreKitの購入完了後に
- (void)completePayment
{
 if (block) block(self);
}
という感じでコールバックを実行してます。

Javascript側は
payment.setComplateCallback(this, this.complate);//callback登録

function complete() {
cc.log("complate!!");
}
みたいな感じです。

これで良いのかわかりませんが、ちゃんと動いていて、しかもAppleの審査に通り今もAppStoreに並んでたりします。だから多分不正解では無いと思います。誰かの参考になれば幸いです。
関連記事

コメントの投稿

非公開コメント

プロフィール

エロぺんぎん

管理人:エロぺんぎん
不純な動機でプログラマーになった男、エロぺんぎんです。ブラザー達を猛烈に応援したい気持ちと、自分もプログラマーとして成長したい思いで、当ブログを立ち上げました。
エロぺん動画を運営しております。

検索フォーム
Twitter
最新記事
最新コメント
カテゴリ
リンク
RSSリンク
エロぺん動画で人気の動画
人気の記事