实现 SwiftUI 中的用户评价请求功能

了解如何在 SwiftUI 应用中实现请求用户评价的功能,并添加适当的触发机制。

实现 SwiftUI 中的用户评价请求功能

SwiftUI 提供了原生的方法,在 App 中请求用户对你的应用进行 App Store 评价和评分。

注意:在 iOS 16 及以上版本中,SwiftUI 弃用了旧的 requestReview() 方法,并引入了新的方法—— RequestReviewAction

添加请求评分功能

触发基础的用户评价弹窗

RequestReviewAction 是 StoreKit 提供的一个结构体,用于请求用户对您的应用进行评分或评价。通过读取 requestReview 环境值,可以获取 RequestReviewAction 的实例。

要在 SwiftUI 中请求用户评价,首先需要导入 StoreKit 框架:

import SwiftUI
import StoreKit

在 View 视图中,通过 @Environment 属性包装器获取requestReview 环境值中:

@Environment(\.requestReview) var requestReview

在适当的时机调用 requestReview()(例如用户完成某项任务后),即可弹出评价提示:

requestReview()

示例代码:

import SwiftUI
import StoreKit

private struct ContentView: View {
    @Environment(\.requestReview) private var requestReview

    var body: some View {
        Button("Review") {
            Task { @MainActor in
                requestReview()
            }
        }
    }
}
0:00
/0:07

请求评分限制

虽然你可以在应用的任意位置调用requestReview(),但并不是每次都会显示。

  • 未评分用户:系统最多每年显示三次评分请求。
  • 已评分用户:如果应用版本更新且超过一年,系统可能再次显示评分请求。
  • 系统控制:即使满足条件,系统可能基于内部算法决定是否显示提示。

在开发模式下调用 requestReview() 时,系统总是会显示评分和评价请求视图,以便测试用户界面和体验。但在 TestFlight 分发的应用中,该方法不会生效。

添加弹窗触发条件

由于 Apple 对请求评价的频率进行了限制,因此选择合适的时机非常重要

  • 用户满意度高时:例如用户完成了游戏的一个关卡,或成功完成了某项任务,这时用户对应用的体验较好,愿意给予积极评价。
  • 频繁使用应用时:用户多次返回使用您的应用,表明他们对应用有较高的依赖性和满意度。
  • 重大事件后:应用进行重大更新或添加了重要功能后,请求用户反馈评价。

通过使用UserDefaults 存储用户访问次数和重要事件次数,然后可以根据这些数据决定是否请求评价:

//
//  MainView.swift
//  requestReviewDemo
//
//  Created by Ivens Liao on 2024/12/12.
//

import StoreKit
import SwiftUI

struct ContentView: View {
    // 获取 requestReview 动作
    @Environment(\.requestReview) var requestReview
    
    // 获取当前计数值
    @State private var numberOfVisits = UserDefaults.standard.integer(forKey: "numberOfVisits")
    @State private var numberOfSignificantEvents = UserDefaults.standard.integer(forKey: "numberOfSignificantEvents")
    
    var body: some View {
        VStack(spacing: 20) {
            Text("欢迎访问 Code with Ivens!")
                .font(.title)
                .padding()
            
            Text("当前访问次数: \(numberOfVisits)")
            Text("当前重要事件次数: \(numberOfSignificantEvents)")
            
            Button("添加访问次数") {
                incrementVisits()
                checkIfReviewNeeded()
            }
            
            Button("添加重要事件次数") {
                incrementSignificantEvents()
                checkIfReviewNeeded()
            }
        }
        .onAppear {
            // 更新显示的计数值
            updateCounts()
            // 自动检查是否需要触发评价
            checkIfReviewNeeded()
        }
    }
    
    // 增加访问次数
    private func incrementVisits() {
        let currentVisits = UserDefaults.standard.integer(forKey: "numberOfVisits")
        UserDefaults.standard.set(currentVisits + 1, forKey: "numberOfVisits")
        updateCounts()
    }
    
    // 增加重要事件次数
    private func incrementSignificantEvents() {
        let currentEvents = UserDefaults.standard.integer(forKey: "numberOfSignificantEvents")
        UserDefaults.standard.set(currentEvents + 1, forKey: "numberOfSignificantEvents")
        updateCounts()
    }
    
    // 更新计数值
    private func updateCounts() {
        numberOfVisits = UserDefaults.standard.integer(forKey: "numberOfVisits")
        numberOfSignificantEvents = UserDefaults.standard.integer(forKey: "numberOfSignificantEvents")
    }
    
    // 自动检查是否需要触发评价
    private func checkIfReviewNeeded() {
        Task { @MainActor in
            requestReviewIfAppropriate()
        }
    }
    
    // 根据条件请求评价
    @MainActor
    private func requestReviewIfAppropriate() {
        if numberOfVisits > 3 || numberOfSignificantEvents > 3 {
            requestReview()
            // 清零计数,避免重复请求
            resetCounts()
        }
    }
    
    // 重置计数
    private func resetCounts() {
        UserDefaults.standard.set(0, forKey: "numberOfVisits")
        UserDefaults.standard.set(0, forKey: "numberOfSignificantEvents")
        updateCounts()
    }
}

#Preview {
    ContentView()
}
0:00
/0:08

在 App 中添加持久链接(可选)

由于苹果对 requestReview() 的限制,一种常见的做法是,在在应用的设置页面中,再格外提供一个指向 App Store 产品页面的持久链接,以便用户随时前往 App Store 进行评价。

func openAppStoreForReview() {
    guard let writeReviewURL = URL(string: "https://apps.apple.com/app/idYOUR_APP_ID?action=write-review") else {
        return
    }
    if UIApplication.shared.canOpenURL(writeReviewURL) {
        UIApplication.shared.open(writeReviewURL, options: [:], completionHandler: nil)
    }
}

不要滥用评价请求

避免在应用启动时立即请求评价,也不要在用户进行其他操作时频繁弹出评价提示。这可能导致用户体验下降,甚至被 Apple 认为是滥用行为。

提供替代反馈渠道

除了请求 App Store 评价,还应在应用内提供反馈选项,让用户在遇到问题时能够直接联系开发者,而不是直接给出差评。这有助于提升用户满意度,并及时解决用户问题。