3

我创建了一个带有游戏商店视图和视图控制器的游戏。可以在菜单 (ViewController.m) 和游戏结束屏幕 (GameViewController.m) 中访问商店。

我的问题是,如果我在菜单中显示了商店一次,然后玩游戏并在游戏中通过屏幕访问商店并尝试购买东西,则应用程序崩溃并出现 EXC_BAD_ACCESS 错误而没有太多信息。(打破在

[[SKPaymentQueue defaultQueue] addPayment:lPayment];

尝试购买 IAP 时,在我的 ShopViewController 中的 ButtonPressed 操作中添加一行。

我的视图是这样设置的:

菜单视图 -> 梯形视图 -> 游戏视图 -> 商店视图

菜单视图 -> 商店视图

希望你能帮我找出错误,

编辑 - - - - - -

看来我可以在不使用游戏视图的情况下从菜单-> Shopview 重现错误。我可以通过按“购买按钮”、按取消、导航回菜单、返回商店并重复来做到这一点。在第 3-4 次尝试时,它在同一行崩溃。这是整个按钮按下方法:

- (void)buyButtonPressed:(UIButton *)pButton {
    NSInteger lTag = [pButton tag];
    //////NSLog(@"Button tag: %i"), lTag;

    Reachability *lReachability = [Reachability reachabilityForInternetConnection];
    NetworkStatus lCurrentNetworkStatus = [lReachability currentReachabilityStatus];
    if (lCurrentNetworkStatus != NotReachable) {
        if ([SKPaymentQueue canMakePayments]) {
            SKPayment *lPayment = [SKPayment paymentWithProduct:[mPriceArray objectAtIndex:lTag]];
            [[SKPaymentQueue defaultQueue] addPayment:lPayment];
            [[SKPaymentQueue defaultQueue] addTransactionObserver:self];

        } else {
            [self showAlertViewWithText:@"Purchases are disabled. Please check your settings for General -> Restrictions -> In-App Purchases and try again." andTitle:@"Warning"];
        }
    } else {
        [self showAlertViewWithText:@"No network connection!" andTitle:@"Warning"];
    }
}

所以看起来 lPayment 正在被解除分配。我什至试图设置

mProductIds = nil;
mPriceArray = nil;

当我删除商店视图时,试图在我重新加载商店时强制它再次分配它,但没有任何运气。

谢谢

4

3 回答 3

3

你的问题是一个悬空指针。EXC_BAD_ACCESS 是 CPU 抱怨您正在处理不存在的内存或访问权限区域之外的内存。原因是缺少对象保留,导致提前释放,然后被覆盖。在那个时候(可能会延迟),指针将指向其取消引用(类检查)导致抛出 EXC_BAD_ACCESS 的垃圾。使用@try 无法捕获此错误。这里假设堆栈本身已损坏,导致无法继续(尽管很可能不是这种情况),这将使调试器陷入困境,其当前状态输出在许多领域已经缺乏。当 CPU 重置重要寄存器并执行长跳转时,这就像无法控制的无政府状态。

考虑自动引用计数。如果您已经在那里,请考虑宿主对象不保留类似委托的属性。任何可以在逻辑上包含 self 的属性都不会保留存储在其中的任何值。ARC 不会帮助你。

在您的情况下: defaultQueue 可能很好。lPayment 可能已被解除分配。

于 2013-01-24T22:48:00.990 回答
1

从提供的信息中很难判断,但可能是以下内容: 您的陈述

SKPayment *lPayment = [SKPayment paymentWithProduct:[mPriceArray objectAtIndex:lTag]];  

实例化一个 SKPayment 对象,并将其交给当前的自动释放池。如果此池不存在(如果代码在没有明确设置自动释放池的单独线程中运行,则可能是这种情况),该对象将立即再次释放,并且您的语句

[[SKPaymentQueue defaultQueue] addPayment:lPayment];  

访问无效内存。

于 2013-01-30T19:14:31.603 回答
1

尝试首先启用 NSZombie 来跟踪问题。如果出现 EXC_BAD_Access 问题,有时它(NSZombie)对于跟踪已释放对象比简单猜测问题所在更有用。

于 2013-01-29T11:21:03.220 回答