iOS StoreKit 2 新特性盘点解析

目录
  • 一、背景
  • 二、物料
  • 三、StoreKit 1 存在的问题
  • 四、StoreKit v2 新特性
  • 五、StoreKit 2 API
    • 5.1 只支持 Swift 开发
      • 原始获取商品方式
      • 新获取商品方式
    • 5.2 新 API
      • 5.2.1 Product
      • 5.2.2 Transaction History
      • 5.2.3 Subscription status
      • 5.2.4 show manager subscriptions
      • 5.2.5 request refund API
    • 小结:
  • 六、Server to Server
    • 6.1 Validate status with receipts
    • 6.2 Check status with APIs
    • 6.3 Track status with notifications
    • 6.4 购买流程变化
    • 6.5 服务器迁移升级到 JWS 格式
    • 6.6 Manager family sharing
    • 6.7 Sandbox test
    • 小结
  • 七、Customer Support and Handle refunds(客服支持和退款处理)
    • 7.1 How do I identify the in-app purchase made by this customer?
    • 7.2 How do I lookup this customer's past refunds?
    • 7.3 How do I compensate subscribers for a service issue?
    • 7.4 How do I appease customers for outages or canceled events?
    • 7.5 App 内如何管理订阅
    • 7.6 APP 内 如何申请退款
  • 八、API 购买流程
    • 原始 API 购买流程
    • 新 API 购买流程
  • 九、QA
  • WWDC 视频

一、背景

2021 年 WWDC,在 iOS 15 系统上推出了一个新的 StoreKit 2 库,该库采用了完全新的 API 来解决应用内购买问题。

  • Meet StoreKit 2 - WWDC21 - Videos - Apple Developer:重点内容:Storekit 2 API 介绍和代码演示,以及 appAccountToken
  • Manage in-app purchases on your server - WWDC21 - Videos - Apple Developer:重点内容:JWS 签名交易的服务器验证,新服务器 API,新服务器通知,沙盒测试的新功能
  • Support customers and handle refunds - WWDC21 - Videos - Apple Developer:重点内容:用来支持用户和处理退款的 Storekit 2 API 以及服务器 API

二、物料

名词 解释  
IAP In-App Purchase:应用内购买  
StoreKit 1 原始的应用内购买 API Choosing a StoreKit API for In-App Purchase
StoreKit 2 应用内购买 API Choosing a StoreKit API for In-App Purchase

三、StoreKit 1 存在的问题

  • 苹果后台能否查看到退款的订单详情?

不能。只能苹果处理退款后发通知给我们的服务器,告知发生了一笔退款

  • 消耗性、非消耗性、非续期订阅、自动续订能不能在沙盒环境测试退款?

不能。系统没提供这种测试方式。

  • 能够将用户反馈的苹果收据里的 orderID 与具体的交易进行关联吗?

不能。

  • 服务器端 Receipt 收据解析后,没有包含 orderID 信息,所以无法直接关联他们之间的联系。

不支持使用苹果收据里的 orderID 去苹果服务器查询交易信息,没有提供这个 API(StoreKit 2 出来后支持去查询 StoreKit1 的交易了,developer.apple.com/documentati… )。

  • 在开发过程中,无法直接关联 transaction 与 orderID 之间联系,虽然有一个 applicationUserName 字段,可以存储一个信息。但是这个字段是不是 100%靠谱,在某些情况下会丢失存储的数据。
  • 无法主动的去苹果服务器获取交易历史记录,退款信息。无法根据用户提供的苹果收据里的 orderID 主动关联上我们当前已知的订单。
  • 目前 sk1 的 skproduct 无法区分消耗品,非消耗品,订阅商品,非连续订阅商品。
  • sk1 存在队列监听,每次购买需要通过队列监听对应的购买状态的变更,所有的 transaction 的回调都在监听当中,不好区分哪些是补单的 transaction 和正常购买的 transaction。

四、StoreKit v2 新特性

StoreKit 2 新特性主要包含三部分:

  • StoreKit 2:关于在 App 里 API 的更新和变化,包含应用内更改订阅、退款等;
  • Server to Server:苹果服务器与开发者服务器之间的通讯,包括苹果通知、开发者主动请求苹果服务器、新的验证收据流程等;
  • Sandbox Test:关于沙盒测试环境相关的更新,还有一些注意事件等。

五、StoreKit 2 API

StoreKit 2 主要的更新有这几个:

  • 使用 swift 新特性开发
  • 更新收据和交易(数据格式和字段变更)
  • 更多订阅类型的接口
  • 相同的 StoreKit 框架

5.1 只支持 Swift 开发

StoreKit 2 使用了 Swift 5.5 的新特性进行开发,完全修改了获取商品、发起交易、管理交易信息等接口 API 的实现方式。swift.org/blog/

例如获取商品方式语法不同:

原始获取商品方式

// 1. 请求商品
  SKProductsRequest *request = [[SKProductsRequest alloc] initWithProductIdentifiers:identifiers];
  request.delegate = pipoRequest;
  [request start];
// 2. 实现 SKProductsRequestDelegate
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response
{
    // success
}
- (void)request:(SKRequest *)request didFailWithError:(NSError *)error API_AVAILABLE(ios(3.0), macos(10.7))
{
    // failed
}

新获取商品方式

// 获取商品
let products = try await Product.products(for: productIDs)
// 购买商品
func purchase(_ product: Product) async throws -> Transaction? {
    //Begin a purchase.
    let result = try await product.purchase()
    switch result {
    case .success(let verification):
      let transaction = try checkVerified(verification)
      //Deliver content to the user.
      await updatePurchasedIdentifiers(transaction)
      //Always finish a transaction.
      await transaction.finish()
      return transaction
    case .userCancelled, .pending:
      return nil
    default:
      return nil
    }
  }

5.2 新 API

  • 商品
  • 购买
  • 交易信息
  • 交易历史
  • 订阅状态

5.2.1 Product

  • 新增了一些商品类型,订阅信息,这些字段信息在 StoreKit 1 里是没有的。

方便我们利用的字段:

  • 通过新增的 product type 我们可以轻易的知道当前的商品是消耗品还是订阅商品
  • 针对于自动连续订阅的第一次购买优惠,我们可以直接感知到当前的商品是不是用户的 Apple ID 下的第一次购买

举个例子:

某些 APP 会有会员订阅服务,那些服务会有 1 个月,3 个月,12 个月等的自动续期,同时还会有一些第一次购买的优惠,这个第一次购买的优惠就是首购优惠,并且这个优惠跟 Apple ID 挂钩,跟 APP 内自己的账号体系无关,例如小马哥旗下产品,自有的账号体系是 QQ 号 + 微信号,那么我们在之前是无法简单得判断你这个 Apple ID 是否享受过首购优惠了,毕竟用户可以有多个 QQ 号,或者多个 微信号,在弹出苹果的购买页面前,我们是不知道这个 Apple ID 有没有享受过首购优惠的,会对用户产生误解,我在上一个页面还告诉我首个月只要 18 块钱,实际支付的时候为什么要 25 元了 ? 这个对用户的购买意愿肉眼可见是有下降的。

现在我们就可以通过 isEligibleForIntroOffer 这个属性,轻松又方便得提前拿到这些信息,对已经享受过的Apple ID账号不展示这个优惠。

  • 提供了新的获取商品接口
public static func products<Identifiers>(for identifiers: Identifiers) async throws -> [Product] where Identifiers : Collection, Identifiers.Element == String
  • 提供了新的购买商品接口。其中购买商品时增加了一些可选参数 PurchaseOption 结构体,该结构体里有新增的特别重要的字段appAccountToken, 类似 SKPayment.applicationUsername 字段,但是 appAccountToken 信息会永久保存在 Transaction 信息内。

appAccountToken 字段是由开发者创建的;关联到 App 里的用户账号;使用 UUID 格式;永久存储在 Transaction 信息里。

PS:这里的 appAccountToken 字段苹果的意思是用来存储用户账号信息的,但是应该也可以用来存储 orderID 相关的信息,需要将 orderID 转成 UUID 格式塞到 Transaction 信息内,方便处理补单、退款等操作。

public func purchase(options: Set<Product.PurchaseOption> = []) async throws -> Product.PurchaseResult
let uuid = Product.PurchaseOption.appAccountToken(UUID.init(uuidString: "uid")!)
// 发起一笔购买之后,直接等待苹果的返回结果,无需在paymenqueue中等待transaction状态的更新。
//使用sk2发起的购买的订单的信息,在sk1所有的回调接口都不会得到相应的transaction的更新状态
let result = try await product.purchase(options: [uuid])
// demo
func purchase(_ product: Product) async throws -> Transaction? {
    //Begin a purchase.
    let result = try await product.purchase()
    switch result {
    case .success(let verification):
      let transaction = try checkVerified(verification)
      //Deliver content to the user.
      await updatePurchasedIdentifiers(transaction)
      //Always finish a transaction.
      await transaction.finish()
      return transaction
    case .userCancelled, .pending:
      return nil
    default:
      return nil
    }
  }

  • 处理验证 Transaction。系统会验证是否是一个合法的 Transaction,此时系统不再提供 base64 的 receip string 信息,只需要上传 transaction.id 和 transaction.originalID,服务器端根据需要选择合适的 ID 进行验证。
func checkVerified<T>(_ result: VerificationResult<T>) throws -> T {
    //Check if the transaction passes StoreKit verification.
    switch result {
    case .unverified:
      //StoreKit has parsed the JWS but failed verification. Don't deliver content to the user.
      throw StoreError.failedVerification
    case .verified(let safe):
      //If the transaction is verified, unwrap and return it.
      return safe
    }
  }
  • 监听 Transaction 更新
func listenForTransactions() -> Task<Void, Error> {
    return Task.detached {
      //Iterate through any transactions which didn't come from a direct call to `purchase()`.
      for await result in Transaction.updates {
        do {
          let transaction = try self.checkVerified(result)
          //Deliver content to the user.
          await self.updatePurchasedIdentifiers(transaction)
          //Always finish a transaction.
          await transaction.finish()
        } catch {
          //StoreKit has a receipt it can read but it failed verification. Don't deliver content to the user.
          print("Transaction failed verification")
        }
      }
    }
  }

针对 transaction 的更新,这个监听是让我们监听:

  • 这笔订单用户开启了一笔购买,这笔订单在苹果那边还没有得到结果,用户杀死 app 或者用户卸载了 app 并重新安装 app,这个时候我们可以通过这个监听收到对应的 transaction 更新
  • 用户发起一笔购买,这笔购买可能因为网络状态不好的因素,在端上收到了失败的 transaction 回调,但是后续苹果发现这种 case,重新下发 transaction 到端上进行对应的验证。

5.2.2 Transaction History

提供了三个新的交易(Transcation)相关的 API:

  • All transactions:全部的购买交易订单,在 transaction 里面获取
  • Latest transactions:最新的购买交易订单。
  • Current entitlements:所有当前订阅的交易,以及所有购买(且未退还)的非消耗品。

根据可以购买的订阅商品、非消耗品可以过滤出已经购买过的商品。

extension Transaction {
  public static var all: Transaction.Transactions { get }
  public static var currentEntitlements: Transaction.Transactions { get }
  public static func currentEntitlement(for productID: String) async -> VerificationResult<Transaction>?
  public static func latest(for productID: String) async -> VerificationResult<Transaction>?
  public static var unfinished: Transaction.Transactions { get }
}
  • 同步不同设备的购买记录。这个 API 可以替换 StoreKit 1 里面的恢复购买 API,调用该方法后,系统会弹出提示框要求输入 AppleID 帐号密码信息。
extension AppStore {
  public static func sync() async throws
}

5.2.3 Subscription status

订阅类型项目的状态,比如主动获取最新的交易、获取更新订阅的状态,获取更新订阅的信息等。其中获取更新订阅的信息,可以获取更新的状态、品项 id、如果过期的话,可以知道过期的原因。(比如用户取消、扣费失败、订阅正常过期等。)获取的所有数据都是 JWS 格式验证。

5.2.4 show manager subscriptions

可以直接唤起 App Store 里的管理订阅页面。

extension AppStore {
  @available(iOS 15.0, *)
  @available(macOS, unavailable)
  @available(watchOS, unavailable)
  @available(tvOS, unavailable)
  public static func showManageSubscriptions(in scene: UIWindowScene) async throws
}

5.2.5 request refund API

提供了新的发起退款 API,允许用户在开发者的 App 中直接进行退款申请。用户进行申请退款后,App 可以收到通知、另外苹果服务器也会通知开发者服务器。(沙盒环境也可进行退款测试了,但是 App Store 里还没开启这个功能。)

extension Transaction {
  public static func beginRefundRequest(for transactionID: UInt64, in scene: UIWindowScene) async throws -> Transaction.RefundRequestStatus
}

小结:

  • StoreKit 2 库采用 Swift 5.5 版本最新特性重写,只支持 Swift、iOS 15+,提供了一些新的 API 接口,导致新的支付流程会发生一些变化。
  • 提供了获取交易历史记录、可购买的商品列表(自动续期订阅以及非消耗品)信息
  • 提供了获取订阅状态、管理订阅状态接口
  • 支持在 App 内发起退款

六、Server to Server

构建开发者服务器可以实现以下几个功能:

  • 接收内购状态改变通知
  • 通过接口跟踪内购状态变化(获取订阅状态、获取所有的交易历史记录)
  • 随时验证用户的访问权限(是否已购买,是否已退款等信息)
  • 管理订阅状态
  • 跟踪退款信息

6.1 Validate status with receipts

服务器端在通过 /verifyReceipt 接口验证票据时,新 API 的数据结构也发生了变化。例如统一了购买时间、过期时间、原始购买时间格式,新增了 appAcountToken 字段、内购类型字段、退款时间、退款原因、促销优惠类型等。具体的可以参考 Manage in-app purchases on your server - WWDC21 - Videos - Apple Developer 视频,或者 Validating Receipts with the App Store | Apple Developer Documentation

6.2 Check status with APIs

新增了一些 API,可以主动去获取订阅状态、交易历史记录等等。具体可以参考这个文档:App Store Server API | Apple Developer Documentation

  • 获取订阅状态:get_all_subscription_statuses,只需要一个 originalTransactionId 参数,就可以获取用户订阅的各种状态
  • 获取交易历史记录:get_transaction_history,只需要用户任意一个交易里的 originalTransactionId 即可获取所有的历史记录
  • 在您的服务器收到消费请求通知后,将有关应用程序内消费品购买的消费信息发送到应用程序商店。(主要用于用户申请退款后,告知 App Store 购买的商品有没有被消费,用于评估是否需要退款)。send_consumption_information
  • App Store Server API standards:JSON Web Signature (JWS)

6.3 Track status with notifications

当订阅状态发生变化时,Apple server 会主动通知我们的服务器,告知发生了哪些变化。功能跟之前的版本一样,但是删除了一些状态,也新增了一些状态。

为了方便测试沙盒环境的退款通知,App Store 可以为沙盒环境单独设置一个 server URL 配置。

6.4 购买流程变化

例如第一次购买订阅类型商品时,购买成功后,Apple server 会主动通知 我们的 server,告知状态。此时我们的 server 可以不用再去 Apple server 那边验证了。及时以后想验证,也可通过 /inApps/v1/subscriptions 接口随时去验证。

续订、账单宽限期、用户退款等操作时除了可以接受苹果的通知外,也可以主动去请求苹果服务器,获取最新的状态。例如在自己服务器宕机或者因为某种原因导致没有接收到苹果的通知时,此时主动去请求苹果服务器获取交易历史记录,交易状态信息,就发挥出了巨大的作用。

6.5 服务器迁移升级到 JWS 格式

对于 StoreKit 2,苹果已经废弃了用 receipt 收据验证逻辑,只需要提供交易的 originalTransactionId 即可获取到完整的交易信息。那么如何从 StoreKit 1 升级到 StoreKit 2 呢?

  • 上传 receipt 到我们的服务器
  • 拿着 receipt 去苹果服务器验证,并获取 originalTransactionId 信息
  • 根据 originalTransactionId 去苹果服务器获取历史交易记录,找到特定 originalTransactionId,Transaction
  • 如果是订阅类型的商品,可以继续去获取订阅状态

6.6 Manager family sharing

管理家庭共享。目前苹果对 非消耗型 和 自动订阅 类型品项是支持 家庭共享(family sharing),另外,苹果会返回一个字段 inAppOwnershipType 表示当前用户是否为购买品项的主用户。更方便的追踪用户的状态

6.7 Sandbox test

  • 清楚沙盒账号购买记录
  • 新增沙盒环境的回调 URL 配置
  • 改变沙盒账号国家/地区
  • 调整沙盒续订频率
  • 安全性改良:testFlight 版本验证票据将失败

小结

  • 以前只支持 Apple server 单向发送状态变化的通知给我们自己的服务器,现在支持主动去请求 Apple server 获取历史交易记录,订阅状态信息
  • StoreKit 2 服务器端接口支持了新的格式(JWS 格式)。
  • 沙盒环境测试优化

七、Customer Support and Handle refunds(客服支持和退款处理)

Support customers and handle refunds - WWDC21 - Videos - Apple Developer

7.1 How do I identify the in-app purchase made by this customer?

如何识别用户的购买项目。当用户扣款了,但是没有收到商品时,用户会过来返回问题并提供了苹果邮箱里的扣款信息截图。

那么我们的服务器端可以使用截图里的 invoice order ID 去请求 /inApps/v1/lookup/{customer_order_id} 这个接口查找到对应的 Transaction 信息。然后我们再去验证是否购买成功、是否已申请退款、是否需要补发商品等等。

https://developer.apple.com/documentation/appstoreserverapi/look_up_order_id
/inApps/v1/lookup/{customer_order_id}

7.2 How do I lookup this customer's past refunds?

如何查询该用户过去的退款信息?

目前的情况是,如果我们服务器宕机了或者没有收到退款通知,那么我们是不知道用户是有没有进行退款的。虽然 StoreKit 2 提供了一个获取交易记录的 API,但是如果通过该 API 来自己过滤退款的交易,不是一个最好的实现方式。所以 Apple 新提供了一个 API 可以查到这个用户的所有退款记录订单,只需要任意的一个 original_transaction_id。

https://developer.apple.com/documentation/appstoreserverapi/get_refund_history
/inApps/v1/refund/lookup/{original_transaction_id}

7.3 How do I compensate subscribers for a service issue?

如何补偿订阅者的服务问题?

比如说当服务器出问题了,为了挽留用户/吸引更多用户,计划如何给用户发补偿。开发者可以提供一个内购对兑码(所有的内购类型都可以),在苹果后台那里生成。然后让用户在 App Store 进行兑换,也可以在 App 里通过 presentCodeRedemptionSheet() 接口调用,弹出系统的兑换界面:

7.4 How do I appease customers for outages or canceled events?

如何安抚客户中断或取消的活动?

主要还是想给用户一些福利,安抚用户。类似其他 App 里的签到一个月,可以赠送用户 1 个月会员等活动。但这种方式的过期时间是由自己的服务器后端决定的。

这里 Apple 也提供了一个接口,允许开发者一年有 2 次机会给订阅内购用户每次加 90 天免费补偿。也就是有自动订阅类型的 App,可以开发者主动在服务器给用户补偿(免费延长)用户的订单时间,每次最多是 90 天。

https://developer.apple.com/documentation/appstoreserverapi/extend_a_subscription_renewal_date
/inApps/v1/subscription/extend/{original_transaction_id}

7.5 App 内如何管理订阅

同上面 5.2.4,提供了一个 showManageSubscriptions 接口,可以直接唤起管理订阅页面。

extension AppStore {
  @available(iOS 15.0, *)
  @available(macOS, unavailable)
  @available(watchOS, unavailable)
  @available(tvOS, unavailable)
  public static func showManageSubscriptions(in scene: UIWindowScene) async throws
}

7.6 APP 内 如何申请退款

同上面 5.2.5 request refund API

八、API 购买流程

原始 API 购买流程

  • 请求 Product
  • 发起购买
  • 接收回调,成功后上传 receipt
  • 服务器验证 receipt 并发货

新 API 购买流程

整个支付购买流程与原始 API 购买流程一样,区别是 3.1 步上传交易信息时,不再上传 receipt/token 信息,上传 transaction_id 就可以了。服务器端可以通过 transaction_id 去苹果服务器获取交易结果,不再需要使用 receipt/token 验证票据。

九、QA

9.1 如何选择新 API(StoreKit 2) 还是原始 API(StoreKit 1)

Choosing a StoreKit API for In-App Purchase | Apple Developer Documentation

如果您的应用程序依赖于以下任何功能,您可能需要使用原始的应用程序内购买 API:

  • 为批量采购计划(VPP)提供支持。有关更多信息,请参阅设备管理。
  • 提供应用程序预购。有关更多信息,请参阅为预购提供应用程序。
  • 您的应用程序从高级版更改为免费版,反之亦然。

对现有和旧应用程序使用原始 API。

  • 如果是一个全新的 App,只支持 iOS 15+系统且支持 Swift5 开发成本不大,推荐使用 StoreKit 2,但是使用 StoreKit 1 也没有问题;

老 App:

  • 从 SDK 角度来看,可以单独新增一个子仓支持 StoreKit 2。即使目前不支持,以后迟早也会支持。
  • 从宿主角度来看,要不要激进的引入新功能。引入新功能后会不会带来 OC 与 Swift 混编的问题,以及引入新功能后需要做好相应的 backup 方案。

9.2 客户端使用 StoreKit 1,服务器端升级到 StoreKit 2 的 API,能否这样使用?

可以。

对于后端来说,Apple Server API V1 和 Apple Server API V2 都可以使用,与客户端是否升级到 StoreKit 2 无关。

9.3 Native SDK 使用 StoreKit 2 后,交互流程会不会有什么变化?以及与服务器通信流程会不会发生什么变化?

可以参考上面新 API 购买流程图。

9.4 StoreKit 2 会不会出现丢单的情况,以及怎么解决丢单问题?

还是有可能出现丢单的情况,例如购买成功了,Apple 返回结果时由于网络的原因导致失败了,但是此时会更容易解决。

解决办法:

  • 冷启动时,可监听 Transaction 变化,收到成功的 Transaction 后重新上传,与 StoreKit 1 类似。
  • 在购买时向 product 内 appAccountToken 字段里塞入业务方 orderID 相关的信息,当用户反馈扣款了但是没发货时,可以让用户提供 Apple 的 orderID,通过它可以直接去苹果服务器获取对应的 Transaction 信息,找到 Transaction.appAccountToken ,再给用户发货。(这里可以做成一个自动化处理工具,只需要用户提供苹果的 orderID,就可以去查找对应的业务方 orderID 进行发货。)

9.5 购买成功但是未 finishTransaction,下次冷启动后还会重新下发 Transaction 吗?

会,与 StoreKit 1 功能一样,只是调用的接口不同。

9.6 从 StoreKit 1 升级到 StoreKit 2 后,能否看到之前使用 StoreKit 1 购买的商品?

能看到,互相兼容了。

9.7 针对使用 StoreKit1 的 app,是否可以放弃读取本地 receipt 的方式传给服务端来验证,直接采用 StoreKit2 的 transaction_id 传递给苹果服务端进行验证票据?

可以。

9.8 针对于苹果返回的 transaction 信息,我们是否能判断这个 transaction 的状态信息对应的商品类型是哪种?

可以,storekit2 针对于 transaction 的返回信息当中,明确的告诉了我们当前的商品类型是什么。针对于服务端对于消耗品和订阅商品的两套不同逻辑,我们通过这个字段,就可以轻易的区分是否是订阅商品再请求对应的接口

WWDC 视频

  • Meet StoreKit 2 - WWDC21 - Videos - Apple Developer:重点内容:Storekit 2 API 介绍和代码演示,以及 appAccountToken
  • Manage in-app purchases on your server - WWDC21 - Videos - Apple Developer:重点内容:JWS 签名交易的服务器验证,新服务器 API,新服务器通知,沙盒测试的新功能
  • Support customers and handle refunds - WWDC21 - Videos - Apple Developer:重点内容:用来支持用户和处理退款的 Storekit 2 API 以及服务器 API
  • What’s new with in-app purchase - WWDC20 - Videos - Apple Developer:重点内容:退款通知,家人共享和 SKAdNetwork
  • In-App Purchases and Using Server-to-Server Notifications - WWDC19 - Videos - Apple Developer:重点内容:App Store 服务器通知详解
  • What's New in StoreKit - WWDC17 - Videos - Apple Developer:重点内容:标准 IAP 支付流程,applicationUserName,promoted IAP

以上就是iOS StoreKit 2 新特性盘点解析的详细内容,更多关于iOS StoreKit 2 新特性的资料请关注我们其它相关文章!

(0)

相关推荐

  • IOS 应用内显示 AppStore 某个应用的详情

    前言 应用内跳转到 AppStore 的文章很多,一般都是用 SKStoreProductViewController 来实现的,不知道有没有在意一个问题:打开很慢!!怎么忍?!  正文 一般网上的文章的代码: func openAppStore(url: String){ if let number = url.rangeOfString("[0-9]{9}", options: NSStringCompareOptions.RegularExpressionSearch) { le

  • iOS实现APP程序内部打开APP的AppStore页面

    前言 最近在做内购用到了StoreKit.framework库,偶然间发现中SKStoreProductViewController这个类,查看文档后发现一个妙用,解决了我一个痛点:APP每次更新或者跳转至某个APP的App Store页面时,都要跳转至App Store,然后再跳转回应用,用户体验很不好,以前都是直接给产品说不能解决,现在呵呵呵

  • iOS WKWebView无法处理URL Scheme和App Store链接的问题解决

    WKWebView简介 UIWebView自iOS2就有,WKWebView从iOS8才有,毫无疑问WKWebView将逐步取代笨重的UIWebView.通过简单的测试即可发现UIWebView占用过多内存,且内存峰值更是夸张.WKWebView网页加载速度也有提升,但是并不像内存那样提升那么多. 下面列举一些其它的优势: 1.更多的支持HTML5的特性 2.官方宣称的高达60fps的滚动刷新率以及内置手势 3.Safari相同的JavaScript引擎,且允许JavaScript的Nitro库

  • iOS中在APP内加入AppStore评分功能的实现方法

    iOS应用内部实现App Store评分功能,笔着整理总结有三种方式,各位可根据自己需求自己选择.先介绍下评分功能实现的三种方式. 1,通用方式通过App内部打开网页形式,跳转到AppStore编辑评论,可评分,可评论. 优点:方便,快捷,不受系统版本限制,目前最常用的方式. 缺点:内部网页形式加载缓慢,等待时间长,加载失败概率大. 2,iOS 6.0以后 在app内部加载AppStore 展示app信息 优点:展示速度比方法三块快 缺点:不能直接跳转到评论编辑页面,需要手动点击评论+编辑评论

  • iOS如何跳转到App Store下载评分页面示例代码

    前言 目前很多应用是要求点击事件直接跳转到App Store,最近工作中就遇到了一个跳转 App Store 评分或者下载更新的功能,网上查到很多跳转方法,这里记录一下,下面话不多说了,来一起看看详细的介绍吧. 主要跳转方法有两种 使用官方 StoreKit.framework 框架 应用间跳转直接跳到 App Store 应用,并携带自己 App 的 AppID. 使用官方框架 苹果提供了StoreKit.framework框架,工程中可以导入这个框架的主头文件 #import <StoreK

  • iOS StoreKit 2 新特性盘点解析

    目录 一.背景 二.物料 三.StoreKit 1 存在的问题 四.StoreKit v2 新特性 五.StoreKit 2 API 5.1 只支持 Swift 开发 原始获取商品方式 新获取商品方式 5.2 新 API 5.2.1 Product 5.2.2 Transaction History 5.2.3 Subscription status 5.2.4 show manager subscriptions 5.2.5 request refund API 小结: 六.Server to

  • 2022发布ECMAScript新特性盘点

    目录 1. Top-level Await 2. Object.hasOwn() 3. at() 4. error.cause 5. 正则表达式匹配索引 6. 类的实例成员 (1)公共实例字段 (2)私有实例字段.方法和访问器 (3)静态公共字段 (4)静态私有字段和方法 (5)类静态初始化块 2022 年 6 月 22 日,第 123 届 ECMA 大会批准了 ECMAScript 2022 语言规范,这意味着它现在正式成为标准.下面就来看看 ECMAScript 2022 新增了哪些特性!

  • Swift 4最全的新特性详细解析(推荐)

    引言 Swift,苹果于2014年WWDC(苹果开发者大会)发布的新开发语言,可与Objective-C共同运行于Mac OS和iOS平台,用于搭建基于苹果平台的应用程序.Swift吸收了众多现代编程语言的优点,尽力的提供简洁的编程语言和强大的功能. WWDC 2017 给大家带来了很多惊喜.Swift 4 也伴随着 Xcode 9 测试版来到了我们的面前,很多强大的新特性非常值得我们期待在正式项目中去使用它.因为 Swift 4 是开源的,如果你关注 swift-evolution 这个项目的

  • 结合C++11的新特性来解析C++中的枚举与联合

    枚举 枚举是用户定义的类型,其中包含一组称为枚举器的命名的整型常数. 语法 // unscoped enum: enum [identifier] [: type] {enum-list}; // scoped enum: enum [class|struct] [identifier] [: type] {enum-list}; // Forward declaration of enumerations (C++11): enum A : int; // non-scoped enum mu

  • 关于iOS 11的一些新特性适配实践总结

    前言 iOS 11 已经发布了一段时间了,随手记团队也早早的完成了适配.在这里,我们做了点总结,与大家一起分享一下关于 iOS 11 一些新特性的适配. UIView & UIViewController Layout Margins iOS 11 中,官方提供了一种新的布局方法--通过 layout margins 进行布局.官方文档 Positioning Content Within Layout Margins 称,使用这种布局可以保证各个 content 之间不会相互覆盖. 总的来说,

  • iOS11新特性之在你的APP中使用LargeTitle

    随着WWDC17以及Apple 2017秋季新品发布会的召开,Apple也在9月20日正式推送了iOS 11的正式版.在iOS 11中,Apple也推出了全新的UI风格. UI风格 在iOS 11中,系统APP使用了这种UI风格.这种风格最明显的变化就是使用了iOS 11的新特性--Large Title和新的SearchController. Demo GitHub: LargerTitleDemo Large Title & Table View 设置Lager Title APP全局使用L

  • iOS10开发和Xcode 8新特性及常见问题解析

    iOS 10 开发这次更新主要表现在以下这几个方面. 1.语音识别 苹果官方在文档中新增了API Speech,那么在以前我们处理语音识别非常的繁琐甚至很多时候可能需要借助于第三方框架处理,那么苹果推出了这个后,我们以后处理起来就非常的方便了,speech具有以下特点: 可以实现连续的语音识别 可以对语 音文件或者语音流进行识别 最佳化自由格式的听写(可理解为多语言支持)和搜索式的字符串 核心代码: #import <Speech/Speech.h> /** 语音识别同样的需要真机进行测试 ,

  • 110.iOS10新特性适配教程XCode8新特性解析

    iOS10 新特性 SiriKit SiriKit的功能非常强大,支持音频.视频.消息发送接收.搜索照片.预订行程.管理锻炼等等.在用到此服务时,siri会发送Intent对象,里面包括用户的请求和各种数据,可以对这个intent处理选择适当的响应. 这个功能主要是看这两个头文件(#import Proactive Suggestions 系统预先建议 背景就是iOS9的时候系统给予的主动建议会通过:Spolight搜索,Safari搜索,Handoff,或者siri建议. 在iOS10之后新增

  • iOS开发之路--微博新特性页面

    BeyondAppDelegate.m // // BeyondAppDelegate.m // 20_帅哥no微博 // // Created by beyond on 14-8-3. // Copyright (c) 2014年 com.beyond. All rights reserved. // #import "BeyondAppDelegate.h" #import "BeyondViewController.h" #import "NewFe

  • PHP 5.3新特性命名空间规则解析及高级功能

    日前发布的PHP 5.3中,最重要的一个新特性就是命名空间的加入.本文介绍了PHP命名空间的一些术语,其解析规则,以及一些高级功能的应用,希望能够帮助读者在项目中真正使用命名空间. 在这里中我们介绍了PHP命名空间的用途和namespace关键字,在这篇文章中我们将介绍一下use命令的使用以及PHP如何解析命名空间的名字的. 为了便于对比,我定义了两个几乎一样的代码块,只有命名空间的名字不同. < ?php   // application library 1   namespace App\L

随机推荐