「iOS」一次惨痛的 APP 上架经历

文章关键词:dSYM、#if/#ifdef/#ifndef、IAP(In App Purchase)、Analyze
复制代码

前言与项目背景(废话)

6 月 12 日 - 20 日,一言难尽心酸泪/大哭——提交 5 次,被拒5次,还有谁?/摊手

项目从 5.2.0 接到手之后,到目前提审中的 6.0.4 之前,前前后后一共提交了 8 个版本,不论是新增功能还是优化升级,都能顺利上架。而这次,从 6.0.4.0 开始提 TestFlight(审核通过),6.0.4.3 开始提交审核,现在已经 6.0.4.8 第六次提审了(目前还在审核中,前五次全军覆没)/摊手

最关键的!这次是为了 618 而提交,影响心情不说,iOS 端的 618 活动受到耽误才是大事啊/大哭,希望领导不要罚钱钱/可怜。

「文章内包含未解决/未知问题,各位看官谨慎查看/摊手」

前三次被拒(关于dSYM)

前两次拒绝原因

Guideline 2.1 - Performance - App Completeness
We were unable to review your app as it crashed on launch. We have attached detailed crash logs to help troubleshoot this issue.
复制代码

第三次拒绝原因

Guideline 2.1 - Performance - App Completeness
We were unable to review your app as it still crashed on launch. We have attached detailed crash logs to help troubleshoot this issue.
复制代码

三次都在后面附上了 crash log 文件(看得出第三次审核团队也很无奈啊)

分析

还是头一回遇到审核启动不了的情况,日常开发和测试中也并没有出现过这个问题。

第一次被拒没注意看日志,以为是打包打错了,检查一遍选项,确定没问题便重新打包上传了,too young!

第二次被拒,分析日志可以看到启动时间过长触发 watchdog,程序被挂起(启动失败),按照日志中的 Termination Reason: Namespace SPRINGBOARD, Code 0x8badf00d 一番搜索,都是让符号化,可是并没有 dSYM 文件,因为着急提交,便将程序启动-引导页-登录页-首页流程捋了一遍,修改了几处疑似影响启动的地方,又打包重新提交,然而 too young!

第三次被拒,心态爆炸心态爆炸心态爆炸!和原来做这个项目的同事沟通一番无果,怎么办也得提交啊,索性让这位同事打包吧!

Exception Type:  EXC_CRASH (SIGKILL)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Exception Note:  EXC_CORPSE_NOTIFY
Termination Reason: Namespace SPRINGBOARD, Code 0x8badf00d
Termination Description: SPRINGBOARD, scene-create watchdog transgression: xxx.xxx.xxx exhausted real (wall clock) time allowance of 18.23 seconds | ProcessVisibility: Foreground | ProcessState: Running | WatchdogEvent: scene-create | WatchdogVisibility: Foreground | WatchdogCPUStatistics: ( | "Elapsed total CPU time (seconds): 27.760 (user 27.760, system 0.000), 46% CPU", | "Elapsed application CPU time (seconds): 1.037, 2% CPU" | )
Triggered by Thread:  0
复制代码

解决方案

这是在第四次被退回时才想到的方法,真的是脑子短路,被干懵了/摊手!

符号化 crash log 的方法不再赘述,我的问题是打包文件里 dSYMs 文件夹是空的,并没有 dSYM 文件/无奈。

看所有没有dSYM文件的文章上都是设置 Build Setting - Debug Information Format,即 Debug 下是 DWARFRelease 下是 DWARF with dSYM File,然而我的原本就是这个选项,Archive 仍旧没有生成 dSYM 文件/摊手。把 Debug 对应的 DWARF 改为 DWARF with dSYM File,从 DerivedData 倒是可以找到 dSYM 文件,然并卵,uuid 对不起来还是无法分析/无奈

因为项目比较久远,Build Setting 改动较大,并且不是对所有的设置选项都了解其根源,再加上上线紧迫,一个个去了解时间也不允许,索性新开一个 Demo 项目,默认设置下打包,打包是有 dSYM 文件的,接下来逐一对照项目去修改 DemoBuild Setting 并打包,直到没有 dSYM

最终定位到了相关设置选项:除了常规设置 Build Setting - Debug Information Format,同时要保证 Build Setting - Generate Debug SymbolsYES

这个方法解决了没有生成 dSYM 的问题,然而之后提交被拒却不是因为无法启动了/无奈。由于每次打包 uuid 都会变化,没有相对应的 uuidcrash log,无法符号化,所以之前无法启动的原因现在也无从得知/摊手

特别提醒:如果不是特殊情况,不要为了缩小一点 .ipa 体积修改 Build Setting 中 Symbols 相关的设置,一旦审核出现了平时无法复现的问题,符号化 Log 解决起来会有迹可循。

TODO

何不对 Build Setting 来一次大扫除?

第四次被拒(关于 #if/#ifdef/#ifndef)

拒绝原因

Guideline 2.1 - Performance - App Completeness
We discovered one or more bugs in your app when reviewed on iPad running iOS 12.3.1 on Wi-Fi.
App fails to connect to its server.
复制代码

分析

越有事越不能慌乱,你看,慌乱中忘记修改服务器地址就打包提交了,所以,这次还有脸分析吗?

没脸。

解决方案

虽然很没脸提,还是给自己提了个醒:为什么没有将服务器分开 DebugRelease? 不只是服务器地址,还有一些逻辑或者日志打印区分开很有必要!这也是开发中的小技巧了。

这里引入 #ifdef / #ifndef / #if / #elif / #else / #endif 的知识点,具体参考:#if 和 #ifdef的区别 或者 #if 和 #ifdef的区别(转载),不再赘述。

第五次被拒(关于 IAP)

拒绝原因

Guideline 2.3 - Performance - Accurate Metadata
We noticed that your app's metadata includes the following information, which is not relevant to the app's content and functionality:
Price of IAP is not matching the price of IAP batch.
复制代码

分析

WTF?内购商品价格显示不一致?这块是在接手之前的逻辑基础上新增了商品,新增之后也提交了几个版本了,突然提出这个问题我也很懵?。通过查看代码,之前的逻辑是在我们自己的服务器获取商品列表,而我们数据库中只保存了人民币的价格。看来还是不够了解 Apple 审核规则/逃

解决方案

解决起来倒是简单,在这里只是提醒大家别犯和我一样的错误/大笑。商品列表修改为从 Apple 服务器(Apple 服务器会根据设备登录的 AppleID 所属的区域自动返回相应的价格)获取即可:

#import <StoreKit/StoreKit.h>

@interface XXXViewController () <SKProductsRequestDelegate>

- (void)productsRequestFromApple
{
    // appstoreconnect 商品 ids
    NSArray *ids = @[@"id", @"id", ...];
    // 根据商品 Ids 请求 appstore 的信息
    if ([SKPaymentQueue canMakePayments]) {
        NSSet *IDSet = [NSSet setWithArray:ids];
        SKProductsRequest *productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:IDSet];
        productsRequest.delegate = self;
        [productsRequest start];
    } else {
        NSLog(@"您已禁止应用内付费");
    }
}

#pragma mark - SKProductsRequestDelegate
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
    // 产品信息
    NSArray *products = response.products;
    if (products.count == 0) {
        NSLog(@"未能获取产品信息");
    } else {
        for (SKProduct *product in products) {
            NSLog(@"localizedDescription: %@", product.localizedDescription);
            NSLog(@"localizedTitle: %@", product.localizedTitle);
            NSLog(@"price: %.2f", ([product.price floatValue]));
            NSLog(@"NSLocaleCurrencySymbol: %@", [product.priceLocale objectForKey:NSLocaleCurrencySymbol]);
            NSLog(@"NSLocaleCurrencyCode: %@", [product.priceLocale objectForKey:NSLocaleCurrencyCode]);
            NSLog(@"productIdentifier: %@", [product productIdentifier]);
        }
    }
}
复制代码

后面的付费流程不再赘述。

其他(关于 Analyze)

记得每次关键节点如打包等,shift + cmd + B 进行代码静态分析(Analyze)并处理,可以解决相当一部分潜在隐患。

后记

虽然程序里设置的活动结束时间 2019.06.20 23:59:59,但还是希望 21 日审核能顺利通过/无所谓

「完」

转载于:https://juejin.im/post/5d09d7a6e51d4556da53d0c6

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值