Full SDK (iOS)


👍

推荐的 SDK

我们建议使用iOSSeamless SDK,以获得流畅的集成体验。该选项提供了灵活的支付解决方案,预置了用户界面组件和自定义选项。

本页面提供了在项目中添加、配置和使用 Full iOS SDK 的所有步骤。

要求

要实施 Yuno iOS SDK,您需要满足以下要求:

第 1 步:在项目中加入程序库

您可以使用 CocoaPods 或 Swift 软件包管理器添加该库。

CocoaPods

要在 iOS 项目中添加 Yuno SDK,您需要安装 Yuno SDK。如果您没有 Podfile,请按照CocoaPods 指南创建一个。创建 Podfile 后,在 Podfile 中添加以下一行,即可将 Yuno SDK 与 Cocoapods 整合。

pod "YunoSDK","~> 1.1.22

之后,您需要运行安装程序:

吊舱安装

Swift 软件包管理器

要在 iOS 项目中添加 Yuno SDK,您需要安装 Swift 软件包管理器.设置好 Swift 软件包后,添加 YunoSDK 作为依赖关系,如下代码块所示:

依赖项:[
    .package(url:"https://github.com/yuno-payments/yuno-sdk-ios.git", .upToNextMajor(from: "1.1.17"))
]

步骤 2:使用公钥Initialize SDK

要开始运行 Yuno iOS 完全检出,首先要获取 Yuno 应用 ID 和公共 API 密钥。然后,如下图所示导入并initialize Yuno:

import YunoSDK

Yuno.initialize(
    apiKey: "PUBLIC_API_KEY",
    config: YunoConfig(),
    callback: { (value: Bool) in }
)
📘

证书

更多信息,请参阅全权证书页面: https://docs.y.uno/reference/authentication

🚧

UISceneDelegate 的用法

如果您的应用程序使用 UISceneDelegate,请确保将 Yuno 初始化代码放在 SceneDelegate 中。

完全结账可让您配置外观和流程。这是一个可选步骤,您可以通过类 YunoConfig.如果您想设置配置,下面的代码块显示了可以配置的元素:

final class YunoConfig {
    let cardFormType: CardFormType,
    let appearance: Yuno.Appearance,
    let saveCardEnabled: Bool,
    let keepLoader: Bool
}

使用以下选项配置 SDK:

参数说明
cardFormType此字段可用于选择付款和注册卡流程。它是一个可选属性,并考虑 .oneStep 默认情况下。
appearance这个可选字段定义了结账的外观。默认情况下,它使用 Yuno 风格。
saveCardEnabled这个可选字段可用于选择是否在卡片流中显示 "保存卡片"复选框。默认为假。
keepLoader该可选字段可控制何时隐藏加载器。如果设置为 true,"...... hideLoader() 函数才能隐藏加载器。默认情况下,它被设置为 false.
hideCardholderName此可选字段允许您在卡片表单中隐藏持卡人姓名字段。当设置为 true持卡人姓名字段未显示。当未指定或设置为 false持卡人姓名字段将显示(默认行为)。隐藏该字段不会影响主卡号、有效期、CVV验证码收集、BIN逻辑或3DS/支付机构验证。当支付机构要求提供持卡人姓名时,商户有责任确保该信息被提交。
📘

访问您的 API 密钥

从 Yuno 控制面板的 "开发人员 "部分获取您的 API 密钥。

步骤 3:开始结账

ViewController 类被定义为 UIViewController 还通过了 YunoPaymentDelegate 协议。

❗️

停用

"(《世界人权宣言》) startCheckout 方法在最近的 iOS SDK 版本中已被弃用。

protocol YunoPaymentDelegate: AnyObject {

    var checkoutSession: String { get }
    var countryCode: String { get }
    var language: String? { get }
    var viewController: UIViewController? { get }

    func yunoCreatePayment(with token: String)
    func yunoCreatePayment(with token: String, information: [String: Any])
    func yunoPaymentResult(_ result: Yuno.Result)
}


class ViewController: YunoPaymentDelegate {

    func viewDidLoad() {
        super.viewDidLoad()
    }
}

参数

参数说明
checkoutSession指当前付款的结账会话。
countryCode该参数决定了正在配置支付流程的国家。支持国家及其国家代码的完整列表可在 "国家覆盖范围"页面查看。
language定义付款表单中使用的语言。您可以将其设置为可用语言选项之一:
  • es (西班牙文)
  • en (英语)
  • pt (葡萄牙语)
  • 菲力
  • id(印尼语)
  • 马来文
  • th(泰语)
  • zh-TW(繁体中文,台湾
  • zh-CN (简体中文,中国
  • vi(越南语)
  • 法文
  • pl (波兰语)
  • it(意大利语)
  • 德文
  • ru(俄文)
  • tr (土耳其语)
  • nl(荷兰语)
  • sv(瑞典语)
  • 韩语
  • ja (日语)
viewController该属性表示 UIViewController 用于显示支付流程。尽管为了实现向后兼容性,该属性仍然是可选的,但您必须提供一个可见控制器,以便 SDK 能正确显示其用户界面。
yunoCreatePayment(with token: String)该方法负责使用提供的token创建付款。它接受一个名为 token表示支付token。
yunoCreatePayment(with token: String, information: [String: Any])该方法负责使用提供的token创建付款。它接受一个名为 token表示支付token。此外,它还以字典形式返回所有token 响应信息。
yunoPaymentResult(_ result: Yuno.Result)付款过程完成后,该方法将被调用,并将付款结果作为类型为 Yuno.Result.
❗️

关于 yunoCreatePayment 的重要说明

您可以拨打 yunoCreatePayment 有或没有 information 参数。不过,在代码中只使用一个版本,因为调用两个版本都不是必需的,而且可能会导致问题。

🚧

Swift 6 并发要求

如果使用 Swift 6,则需要执行 YunoPaymentDelegate 协议的具体并发考虑因素。Swift 6 引入了更严格的线程安全要求,这将影响您实现委托的方式。请参见 实施 YunoPaymentDelegate 使用 Swift 6 并发 部分,了解详细的实施方案和最佳做法。

第 4 步:在结账中添加 SDK 视图

您的观点需要采用 YunoPaymentFullDelegate 协议。这样,您的应用程序就能响应与支付相关的操作,例如当用户选择支付方式时。

下面介绍如何定义委托:

protocol YunoPaymentFullDelegate: YunoPaymentDelegate {
    func yunoDidSelect(paymentMethod: YunoSDK.PaymentMethodSelected)
    func yunoDidUnenrollSuccessfully(_ success: Bool)
    func yunoUpdatePaymentMethodsViewHeight(_ height: CGFloat)
}

参数

功能说明
yunoDidSelect(paymentMethod: YunoSDK.PaymentMethodSelected)当用户选择付款方式时调用。
- paymentMethod:用户选择的方法。
yunoDidUnenrollSuccessfully(_ success: Bool)当取消注册操作完成时调用。
- success: true 如果成功的话 false 如果没有
yunoUpdatePaymentMethodsViewHeight(_ height: CGFloat)调用时 getPaymentMethodViewAsync() 以及视图高度发生变化时调用。

要显示付款方式,请调用以下方法,并将视图模型或控制器作为委托传递。

await Yuno.getPaymentMethodViewAsync(delegate:)

该方法将根据您使用的用户界面框架自动返回正确的视图类型:

  • 如果您使用 UIKit会返回一个 UIView.
  • 如果您使用 SwiftUI会返回一个 some View.

这样,无论使用哪种 UI 框架,都能轻松将 SDK 集成到任何 iOS 项目中。

步骤 5:启动payment 程序

要在显示付款方式后开始付款,请调用 startPayment 方法:

Yuno.startPaymentshowPaymentStatus:Bool)

步骤 6:获取 OTT(一次性token

在此过程结束时,您可以获取一次性token 来创建背对背付款。您将在函数 yunoCreatePayment() 在采用 YunoPaymentDelegate.检索一次性token 的示例如下:

func yunoCreatePayment(with token: String) { ... }

第 7 步:创建付款

完成上述步骤后,就可以创建付款。必须使用 "创建付款"(Create Payment endpoint来创建背对背付款。商家应调用自己的后台,使用一次性token 和结账会话在 Yuno 中创建付款。

📘

继续Payment 方式

为确保无缝的支付体验,将以下功能整合在一起至关重要 continuePayment 方法。这一步对于需要客户额外操作的异步支付方式尤为重要。以下是您需要了解的内容:

  • 异步支付处理:应用程序接口将发出需要采取进一步行动的信号,即 sdk_action_required 字段设置为 true。
  • 功能性:""""""""""""等字样。 yuno.continuePayment() 该功能旨在管理和显示客户完成付款所需的任何附加屏幕。
  • 简化流程:使用这种方法,您可以简化付款流程,因为它会自动为您处理各种情况。
YunocontinuePayment()

步骤8:处理支付状态(可选)

🚧

深度链接和 Mercado Pago Checkout Pro

只有在使用依赖深度链接的支付方式或 Mercado Pago Checkout Pro 时,才需要执行此步骤。如果您的付款方式不使用深度链接,您可以跳过这一步。

有些支付方法会让用户离开您的应用程序来完成交易。支付完成后,用户会通过深层链接重定向回到您的应用程序。SDK 会使用此深度链接检查发生了什么,检查支付是否成功、失败或取消,并向用户显示状态屏幕。

为此,您需要更新您的 AppDelegate 将输入的 URL 传回 Yuno SDK。这样,SDK 就能读取结果并显示支付状态。下面的代码片段展示了如何将其添加到您的应用程序中:

func application(_ app: UIApplication,
                 open url: URL,
                 options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {

  guard url.scheme == "yunoexample" else { return false }

  return Yuno.receiveDeeplink(url)
}

这段代码会侦听打开应用程序的深度链接。当收到 URL 时,它会检查该方案是否与您在 callback_url 在结账会话设置期间。如果匹配,URL 将通过以下方式传递给 Yuno SDK Yuno.receiveDeeplink(...).然后,SDK 会读取支付结果,并向用户显示相应的状态屏幕。

确保 url.scheme 代码中的 callback_url 时提供的 checkout_session.

回调

支付完成后,SDK 可以返回不同的交易状态: success, fail, processing, reject, internalErroruserCancell.各交易状态的说明如下表所示。

交易状态说明
succeeded表示交易或payment 流程已成功完成。
fail这种状态表示交易或支付流程失败。这意味着在支付过程中出现了错误或问题,导致支付无法成功完成。
processing表示交易或付款流程正在处理中。通常在付款处理出现延迟时使用,如等待第三方服务或金融机构的批准。
reject这种状态表示交易被拒绝。拒绝的原因有多种,如资金不足、欺诈活动或违反特定规则或政策的请求。
internalError这意味着处理支付流程的系统或基础设施出现了意外错误。这种状态表明服务器或后台出现了问题,而不是用户的输入或请求出现了问题。
userCancell该状态表示用户已自愿取消或放弃交易或支付流程。当用户可以选择取消或放弃付款流程时,通常会使用这种状态。

付款状态验证

本节说明当用户取消或退出支付流程时,SDK如何处理支付状态,以及在这些场景中SDK状态与后端支付状态之间的关联关系。

同步支付方式(Apple Pay)

对于Apple Pay等同步支付方式,当用户在收到支付服务提供商(PSP)响应前取消或关闭钱包界面时:

  • SDK状态: 返回 userCancell (CANCELLED)
  • 后端支付状态:遗骸 PENDING 直至PSP超时或商户取消
  • 重要SDK 将不返回 rejectprocessing 在此情境下

这确保后端支付保持待处理状态,并能由商户系统妥善处理。

异步支付方式(PIX及基于二维码的支付方式)

对于PIX等异步支付方式,当用户在完成支付前关闭二维码窗口(点击X)时:

  • SDK状态: 返回 PENDING,可选地带有子状态,例如 CLOSED_BY_USER
  • 后端支付状态:遗骸 PENDING 且二维码在到期前始终有效
  • 结账会话复用:重新打开相同的结账会话可显示相同的有效二维码
  • 不自动取消:当用户关闭二维码窗口时,PIX支付不会自动取消

此功能允许用户在二维码失效前返回支付流程,使用同一二维码完成交易。

已过期的异步支付

如果PIX二维码自然过期:

  • 后端状态更新至 EXPIRED
  • SDK状态SDK 回调和轮询endpoints 点返回 EXPIRED 始终如一地

这确保了当支付方式过期时,商户能够收到准确的状态信息。

要获取事务状态,必须实现下面代码中的委托:

enum Result {
    case reject, success, fail, processing, internalError, userCancell
}

func yunoPaymentResult(_ result: Yuno.Result) { ... }
func yunoEnrollmentResult(_ result: Yuno.Result) { ... }

补充功能

Yuno iOS SDK 提供额外的服务和配置,您可以用来改善客户体验。使用SDK 定制功能可更改 SDK 外观,使其与您的品牌相匹配,或配置加载器。

  • 加载器通过 SDK 配置选项控制加载器的使用。
  • 为未来付款保存银行卡:此外,您还可以使用复选框来保存或注册卡片。 cardSaveEnable: true.下面是两种卡片表单复选框的示例。
  • 你还可以为卡片形式选择其中一种渲染选项。下面的截图展示了 cardFormType ONE_STEPSTEP_BY_STEP.
  • SDK 定制:更改 SDK 外观,使其与您的品牌相匹配。

渲染模式集成

Yuno SDK 中的呈现模式增强了用户界面的灵活性,使开发人员能够集成支付流程,完全控制用户界面,同时保留full SDK 功能。该模式提供的 SwiftUI 视图可无缝集成到现有的用户界面中。

主要功能 startPaymentRenderFlow

"(《世界人权宣言》) startPaymentRender 功能是 Yuno SDK 的一项功能,允许商家以更详细、更可定制的方式整合支付流程。该功能可完全控制支付表单的显示时间和方式,便于与商家现有的应用程序用户界面更顺畅地集成。

该功能旨在加强对支付流程的控制,使商家能够

  • 在自己的用户界面中以定制方式集成支付表单。
  • 精确控制支付数据表格的显示时间。
  • 对付款确认流程进行详细控制。
  • 在商户应用程序中提供更流畅、更一致的用户体验。

语法

语法部分提供了 startPaymentRender 功能。该功能是在应用程序中集成支付流程的核心,可提供可定制的详细方法来处理支付表单和流程。

@MainActor static func startPaymentRenderFlow(
    PaymentMethodSelected:PaymentMethodSelected、
    with delegate:支付委托
) async -> 某 YunoPaymentRenderFlowProtocol

参数

"(《世界人权宣言》) startPaymentRender 功能需要特定参数才能有效运行。这些参数对于定义付款方式和处理付款流程响应至关重要。

参数类型说明
paymentMethodSelectedPaymentMethodSelected用户选择的付款方式。必须包括 vaultedToken (如果存在)和 paymentMethodType
delegateYunoPaymentDelegate将处理支付流程响应(包括token 创建和最终结果)的委托

返回值

返回一个符合 YunoPaymentRenderFlowProtocol提供了处理支付渲染流程的方法。

YunoPaymentRenderFlowProtocol 协议

返回的实例 startPaymentRender 该协议包括以下方法:

formView(paymentMethodSelected:with:)

func formView(
    PaymentMethodSelected:PaymentMethodSelected、
    with delegate:YunoPaymentDelegate
) async -> AnyView?
  • 目的: 获取表单视图以获取付款数据
  • 行为:
    • 如果付款方式要求显示表单,则返回一个 AnyView 相应的形式为
    • 如果付款方式不需要显示任何表单(如已配置的方式),则返回 nil
  • 何时使用:创建支付流程实例后立即调用

提交表单

func submitForm()
  • 目的: 提交表单数据以进行验证
  • 行为执行所有必要的验证,如果成功,则继续生成新的一次性token
  • 何时使用用户在商家应用程序中执行 "支付 "操作时

continuePayment()

funccontinuePayment() async -> AnyView?
  • 用途: 生成一次性token 后继续付款流程
  • 行为:
    • 如果需要显示其他视图(如 3DS 验证),则返回一个 AnyView
    • 如果不需要其他视图,则返回 nil
  • 何时使用通过委托接收一次性token 并创建付款后

实施流程

本节概述了使用 Yuno SDK 实现支付渲染流程所需的步骤顺序。

步骤 1:初始设置

开始使用 startPaymentRender请确保 SDK 已正确初始化,并且您拥有有效的 checkoutSession.请按照以下步骤设置您的环境:

await Yunoinitialize(apiKey: "your_api_key")

第 2 步:创建支付流程实例

创建支付流程实例,使用所选方法管理和呈现支付流程。

let paymentFlow = awaitYuno.startPaymentRenderFlow(
    paymentMethodSelected: selectedPaymentMethod、
    with: self
)

步骤 3:获取并显示表单

检索并显示付款表单,有效收集用户付款信息。

let formView = await paymentFlow.formView(
    paymentMethodSelected: selectedPaymentMethod,
    with: self
)

if let formView = formView {
    VStack {
        Text("Payment Information")

        formView

        Button("Pay") {
            paymentFlow.submitForm()
        }
    }
} else {
    paymentFlow.submitForm()
}

步骤 4:处理一次性token

执行委托方法以接收token:

extension MyViewController: YunoPaymentDelegate {
    var checkoutSession: String {
        return "your_checkout_session"
    }

    var countryCode: String {
        return "CO"
    }

    var viewController: UIViewController? {
        return self
    }

    func yunoCreatePayment(with token: String, information: [String: Any]) {
        createPaymentInBackend(token: token) { [weak self] success in
            if success {
                Task {
                    let additionalView = await self?.paymentFlow?.continuePayment()
                    if let additionalView = additionalView {
                        self?.showAdditionalView(additionalView)
                    }
                }
            }
        }
    }

    func yunoPaymentResult(_ result: Yuno.Result) {
        switch result {
        case .succeeded:
            showSuccessMessage()
        case .reject:
            showRejectionMessage()
        case .fail:
            showErrorMessage()
        case .processing:
            showProcessingMessage()
        case .userCancell:
            handleCancellation()
        case .internalError:
            showInternalErrorMessage()
        }
    }
}

完整示例

import SwiftUI
import YunoSDK

struct PaymentRenderView: View {
    @State private var paymentFlow: YunoPaymentRenderFlowProtocol?
    @State private var formView: AnyView?
    @State private var additionalView: AnyView?

    let selectedPaymentMethod: PaymentMethodSelected
    let delegate: YunoPaymentDelegate

    var body: some View {
        VStack(spacing: 20) {
            Text("Complete Purchase")
                .font(.title2)
                .fontWeight(.bold)

            OrderSummaryView()

            if let formView = formView {
                VStack(alignment: .leading) {
                    Text("Payment Information")
                        .font(.headline)

                    formView
                }
            }

            if let additionalView = additionalView {
                additionalView
            }

            Spacer()

            Button(action: {
                paymentFlow?.submitForm()
            }) {
                Text("Confirm Payment")
                    .font(.headline)
                    .foregroundColor(.white)
                    .frame(maxWidth: .infinity)
                    .padding()
                    .background(Color.blue)
                    .cornerRadius(10)
            }
        }
        .padding()
        .onAppear {
            setupPaymentFlow()
        }
    }

    private func setupPaymentFlow() {
paymentFlow = await Yuno.startPaymentRenderFlow(
    paymentMethodSelected: selectedPaymentMethod,
    with: delegate
)

        Task {
            formView = await paymentFlow?.formView(
                paymentMethodSelected: selectedPaymentMethod,
                with: delegate
            )
        }
    }
}

class PaymentDelegate: YunoPaymentDelegate {
    let checkoutSession: String
    let countryCode: String
    weak var viewController: UIViewController?

    init(checkoutSession: String, countryCode: String, viewController: UIViewController?) {
        self.checkoutSession = checkoutSession
        self.countryCode = countryCode
        self.viewController = viewController
    }

    func yunoCreatePayment(with token: String, information: [String: Any]) {
        PaymentService.createPayment(token: token) { [weak self] result in
            switch result {
            case .success:
                Task {
                    await self?.continuePaymentProcess()
                }
            case .failure(let error):
                print("Error creating payment: \(error)")
            }
        }
    }

    func yunoPaymentResult(_ result: Yuno.Result) {
        DispatchQueue.main.async {
            switch result {
            case .succeeded:
                NotificationCenter.default.post(name: .paymentSucceeded, object: nil)
            case .reject:
                NotificationCenter.default.post(name: .paymentRejected, object: nil)
            }
        }
    }

    private func continuePaymentProcess() async {
    }
}

常见用例

本节概述了 Yuno SDK 可用于处理各种支付方式的典型场景,提供了灵活性和集成的便利性。

1.信用卡付款

在本使用案例中,我们演示了如何使用新的信用卡信息处理付款,要求用户填写表格以获取必要的信用卡详细信息。

let cardPayment =paymentMethodType: "CARD")
let flow =Yuno.startPaymentRender(paymentMethodSelected: cardPayment, with: delegate)

let form = await flow.formView(paymentMethodSelected: cardPayment, with: delegate)

2.使用保存的方法付款

该场景演示了使用保存的支付方法,通过使用保险库token,用户无需重新输入详细信息即可进行支付。

让 savedCard = SavedCardPayment(
   paymentMethodType:"CARD"、
   vaultedToken: "saved_token_123"
)
let flow =Yuno.startPaymentRender(paymentMethodSelected: savedCard, with: delegate)

let form = await flow.formView(paymentMethodSelected: savedCard, with: delegate)

3.使用 3DS 验证付款

3D Secure (3DS) 增加了一个额外的验证步骤,以提高安全性。Yuno SDK 可将此流程无缝集成到您的支付流程中。

func yunoCreatePayment(with token: String, information: [String: Any]) {
    createPayment(token: token) { [weak self] success in
        if success {
            Task {
                let authView = await self?.paymentFlow?.continuePayment()
                if let authView = authView {
                    self?.show3DSView(authView)
                }
            }
        }
    }
}

重要考虑因素

本节重点介绍如何有效集成 Yuno SDK,确保无缝、安全的支付流程。

先决条件

  • 使用前确保 SDK 已初始化 startPaymentRender
  • 委托必须实现 YunoPaymentDelegate
  • "(《世界人权宣言》) checkoutSession 必须有效并处于活动状态

国家管理

  • 经常检查是否 formView() 回报 nil 在显示视图之前
  • 妥善处理以下情况 continuePayment() 回报 nil
  • 在异步操作过程中实现加载状态

安全

  • 切勿存储一次性tokens ,应立即使用
  • 始终在后台验证付款结果
  • 为网络运行实施适当的超时

性能

  • 致电 formView()continuePayment() 是异步的
  • 考虑在这些操作过程中显示装载指示器
  • 尽可能重复使用支付流程实例

故障排除

本节提供 Yuno SDK 集成过程中遇到的常见问题的快速解决方案,确保支付过程更加顺畅。

常见问题

  1. formView()总是返回nil

    • 确认所选付款方式需要填写表格
    • 确保正确初始化 SDK
  2. 代表没有收到yunoCreatePayment

    • 验证 submitForm() 被正确调用
    • 确认表单数据有效
  3. continuePayment()没有按预期返回视图

    • 某些付款方式无需额外查看
    • 在 Yuno 面板中检查付款方式配置

调试日志

Yuno.config.environment = .staging

从其他方法迁移

如果您要从 startPayment()startPaymentLite():

Yuno.startPaymentshowPaymentStatus: true)

let flow =Yuno.startPaymentRender(paymentMethodSelected: method, with: delegate)
let form = await flow.formView(paymentMethodSelected: method, with: delegate)

使用新方法的主要好处是可以对用户界面和支付过程进行详细控制。

📘

演示应用程序

除提供的代码示例外,您还可以访问Yuno 存储库,获取 Yuno iOS SDK 的完整实现。

实施 YunoPaymentDelegate 使用 Swift 6 并发

Swift 6 引入了更严格的并发性要求,这会影响您如何实现 YunoPaymentDelegate 协议。本节将解释这些挑战,并针对不同的实施方案提供解决方案。

📘

了解 Swift 6 中的并发性

并发性是指应用程序同时管理多个任务的能力。在 Swift 6 中,并发规则变得更加严格,以增强应用程序的稳定性并防止崩溃。这意味着您的代码结构必须更加严谨,以确保线程安全和适当的任务管理。

问题

在 Swift 6 中,继承自 Sendable 要求其所有实现都是线程安全的。当在标记为 @MainActor.

线程安全意味着你的代码可以被多个线程安全调用,而不会导致崩溃或意外行为。 @MainActor 确保代码在主线程(UI 线程)上运行。

我们的设计决定

我们不会将协议标记为 @MainActor 因为

  • 这将迫使所有实现 MainActor-兼容
  • 这将降低不使用以下功能的商家的灵活性 MainActor
  • 每种执行方式都有不同的并发需求

商家的责任

商家有责任根据自己的实施情况处理并发问题。以下是三种不同的方法,您可以根据自己的具体需求加以使用。

方案 1:不可变属性

这种方法使用不可变属性,可自动保证线程安全,是简单配置的理想选择。它最适用于具有固定配置值且在运行时不会改变的简单应用程序。

@MainActor
class MyViewController: UIViewController, YunoPaymentDelegate {

    private let _countryCode = "CO"
    private let _language = "EN"

    nonisolated var countryCode: String { _countryCode }
    nonisolated var language: String? { _language }
    nonisolated var checkoutSession: String { _checkoutSession }

    nonisolated func yunoPaymentResult(_ result: Yuno.Result) {
        Task { @MainActor in
        }
    }
}

方案 2:可变属性 MainActor.assumeIsolated

这种方法最适用于配置值可能在运行时发生变化的应用程序(如用户偏好设置),通过使用 MainActor.assumeIsolated.

@MainActor
class MyViewController: UIViewController, YunoPaymentDelegate {

    @Published var configLanguage: String = "EN"
    @Published var configCountryCode: String = "CO"

    nonisolated var language: String? {
        MainActor.assumeIsolated { configLanguage }
    }

    nonisolated var countryCode: String {
        MainActor.assumeIsolated { configCountryCode }
    }
}

方案 3:对于非MainActor 班级

这种方法适用于不需要 MainActor 隔离,因此最适合不与用户界面交互的后台服务或实用程序类。

class MyService: YunoPaymentDelegate {

    let countryCode: String
    let language: String?
    let checkoutSession: String
    let viewController: UIViewController?

    init(countryCode: String, language: String?, checkoutSession: String, viewController: UIViewController?) {
        self.countryCode = countryCode
        self.language = language
        self.checkoutSession = checkoutSession
        self.viewController = viewController
    }

    func yunoPaymentResult(_ result: Yuno.Result) {
    }
}

⚠️ 重要考虑因素

在委托中实现并发时,请牢记以下要点:

  • MainActor.assumeIsolated:仅在保证从 MainActor.这是一种安全机制,它告诉 Swift "相信我,我知道这是在主线程上运行的"。
  • nonisolated:表示可以从任何线程访问,因此必须是线程安全的。当您的属性或方法不依赖于用户界面状态时,请使用此属性或方法。
  • viewController:仍为 @MainActor 因为它应始终由主线程访问。用户界面组件必须始终在主线程上运行,以防止崩溃。