【问题标题】:Cocos2dx InApp Purchase for iosCocos2dx InApp 购买 for ios
【发布时间】:2014-06-07 08:43:27
【问题描述】:

我正在尝试将应用内购买集成到我使用 cocos2d x c++ 制作的应用中。我正在使用 easyNdk Helper 进行应用内购买。我的应用内购买非常适合我的 Objective C 应用。但是对于 cocos2d x 它会抛出以下行的错误

if ([[RageIAPHelper sharedInstance] productPurchased:productP.productIdentifier])

实际上值以参数的形式完美地来自 CPP 文件,并在 NSLog 中正确显示它们的值,但它总是将对象显示为 nil,甚至 objetcs 在 NSLog 中打印它们的存储值

@try catch 条件也不起作用

最后抛出如下错误

请帮我做什么? 谢谢

我的 .CPP 代码是

 NDKHelper::AddSelector("HelloWorldSelectors",
                           "SampleSelector",
                           callfuncND_selector(Main::cameFromObjC),
                           this);

            CCDictionary* prms = CCDictionary::create();
            prms->setObject(CCString::create("SampleSelector"), "to_be_called");
            prms->setObject(CCString::create(result), "BirdNameKey");
SendMessageWithParams(string("SampleSelector"), prms);

和.mm代码是

- (void) SampleSelector:(NSObject *)prms
{
    NSLog(@"purchase something called");
    NSDictionary *parameters =   [[NSDictionary alloc]init];// (NSDictionary*)prms;
    parameters = (NSDictionary*)prms;
    NSLog(@"Passed params are : %@", parameters);

    // Fetching the name of the method to be called from Native to C++
    // For a ease of use, i have passed the name of method from C++
    NSString* CPPFunctionToBeCalled = (NSString*)[parameters objectForKey:@"to_be_called"];
    //NSString *str = [NSString stringWithFormat:@"%@",[parameters valueForKey:@"BirdNameKey"]];
    NSString *BirdName =  [parameters valueForKey:@"BirdNameKey"];
    NSString *str = [[NSString alloc]initWithFormat:@"%@",[parameters objectForKey:@"BirdNameKey"]];
    NSUserDefaults *d2 = [NSUserDefaults standardUserDefaults];
    NSLog(@"%@ , %@ , %@", str,BirdName,[d2 objectForKey:@"product"]); // output is ok for all
    SKProduct * product = (SKProduct *) [ APPDELEGATE.productDictionary objectForKey:[d2 objectForKey:@"product"]];
    [ APPDELEGATE.priceFormatter setLocale:product.priceLocale];
    APPDELEGATE.currentProduct =product;

if ([[RageIAPHelper sharedInstance] productPurchased:product.productIdentifier])
        {
           // check the product purchased or not but app crash at this if statement
        }
   [IOSNDKHelper SendMessage:CPPFunctionToBeCalled WithParameters:nil];
}

【问题讨论】:

  • 你发送到这个MM文件的这个值,是char*吗?另外,您是否在 MM 文件中记录了此值?另外,您正在使用的这个对象的 retaincount 是多少?
  • @Al-mo 嗨亲爱的,我将参数作为 CCDictionary 从 .cpp 文件传递​​到 .mm 文件,然后将其转换为 NSDictionary 我没有在我的项目中使用任何保留关键字,因为它是弧项目。恐怕我现在不必在哪里设置retaincount :(,我不知道“您是否在MM文件中记录了这个值”是什么意思我还尝试使用CCUserDefault设置该值,然后尝试通过 NSUserDefault 获取技术,但存在同样的问题 :(
  • 在发送之前,您能否检查一下您的字典的 RETAINCOUNT 是多少,并且,当您收到这本字典时,您是接受它作为 NSDICTIONARY(参数)还是创建一个 NSDictionary对象使用您从 CPP 文件发送的字典?
  • 另外,请确保您在传递之前保留了这本词典。当您尝试访问它时,它可能会自动释放。我需要查看代码才能更好地理解。
  • @Al-mo 我已将代码包含在我的问题中,您可以检查一下

标签: c++ ios objective-c in-app-purchase cocos2d-x


【解决方案1】:

我也遇到过这个问题,我已经解决了。 在你的 IAPhelper.mm 中

只做这个替换这一行

_purchasedProductIdentifiers = [NSMutableSet set];

下面一行

_purchasedProductIdentifiers = [[NSMutableSet alloc] init];

如下图

 - (id)initWithProductIdentifiers:(NSSet *)productIdentifiers {

    if ((self = [super init])) {

        // Store product identifiers
        _productIdentifiers = productIdentifiers;

        // Check for previously purchased products
//        _purchasedProductIdentifiers = [NSMutableSet set];
        _purchasedProductIdentifiers = [[NSMutableSet alloc] init];
        for (NSString * productIdentifier in _productIdentifiers) {
            BOOL productPurchased = [[NSUserDefaults standardUserDefaults] boolForKey:productIdentifier];
            if (productPurchased) {
                [_purchasedProductIdentifiers addObject:productIdentifier];
                // NSLog(@"Previously purchased: %@", productIdentifier);
            } else {
                // NSLog(@"Not purchased: %@", productIdentifier);
            }
        }

        // Add self as transaction observer
        [[SKPaymentQueue defaultQueue] addTransactionObserver:self];

    }
    return self;

}

【讨论】:

    【解决方案2】:

    我发现您的代码存在两个(潜在)问题,

    首先

    CCDictionary* prms = CCDictionary::create();
    

    请注意,以这种方式初始化数据对象并不能保证当您稍后在代码中(特别是在其他函数中)尝试访问它时它不会被释放

    所以,试试这个吧,

    CCDictionary* prms = new CCDictionary();
    prms->init ... (the initialization)
    

    但请注意,通过这样做,您现在有责任在完成此对象后删除它。另外,我不确定“setObject”方法的实现,如果是保留对象那么我相信这一步是没有必要的,但我不确定所以你必须检查它!

    其次

    NSDictionary *parameters =   [[NSDictionary alloc]init];// (NSDictionary*)prms;
    parameters = (NSDictionary*)prms;
    NSLog(@"Passed params are : %@", parameters);
    

    我认为那个选角有问题(或者我可能错了)

    我建议你做这样的事情

    (NSDictionary *)nsDictionaryFromCCDictionary:(cocos2d::CCDictionary *)ccDictionary {
    if (ccDictionary == NULL) {
        return NULL;
    } else if (ccDictionary->allKeys() == NULL) {
        return NULL;
    } else if (ccDictionary->allKeys()->count() <= 0) {
        return NULL;
    }
    
    cocos2d::CCLog("1");
    
    NSMutableDictionary *nsDict = [NSMutableDictionary dictionaryWithCapacity:ccDictionary->allKeys()->count()];
    
    cocos2d::CCLog("2");
    
    for (int i = 0; i < ccDictionary->allKeys()->count(); i++) {
        cocos2d::CCLog("3");
    
        cocos2d::CCObject* obj = ccDictionary->objectForKey(((cocos2d::CCString *)ccDictionary->allKeys()->objectAtIndex(i))->getCString());
        NSObject* nsObject;
        if(isKindOfClass(obj, cocos2d::CCDictionary))
        {
            nsObject = @"Dictionary";
        }
        else if(isKindOfClass(obj, cocos2d::CCArray))
        {
            nsObject = @"Array";
        }
        else if (isKindOfClass(obj, cocos2d::CCString))
        {
            const char* cstring = ((cocos2d::CCString*)obj)->getCString();
            nsObject = [[[NSString alloc] initWithBytes:cstring length:strlen(cstring) encoding:NSUTF8StringEncoding] autorelease];
        }
        else if (isKindOfClass(obj, cocos2d::CCInteger))
        {
            nsObject = [NSString stringWithFormat:@"%d", ((cocos2d::CCInteger*)obj)->getValue()];
        }
        else
        {
            nsObject = @"Unknown Object";
        }
        [nsDict setValue:nsObject forKey:[AnalyticXStringUtil nsstringFromCString:((cocos2d::CCString *)ccDictionary->allKeys()->objectAtIndex(i))->getCString()]];
    }
    
    return nsDict;
    

    }

    我已经从 >>> https://github.com/diwu/AnalyticX/blob/master/Add-To-Your-Own-Project/AnalyticXStringUtil.mm 粘贴了上面的代码

    尝试将字典作为 CCDictionary 接收并检查此对象是否有效(因为 mm 可以具有 c++ 和目标 c 代码,所以这不会成为问题)然后在创建 NSDictionary 后,尝试打印它。希望这次不会给你报错。

    【讨论】:

    • 亲爱的 Al-mo 我已经尝试过您建议的技术,但没有成功。即使我提供 HardCoded In App 购买密钥,但它仍然抛出相同的错误,我认为这可能是一些编译器问题
    • 我很想调试它...因为它看起来很奇怪!
    • 你能给我提供任何在 cocos2d-x 中运行的示例 ios In App Purchase 代码
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-07
    相关资源
    最近更新 更多