Swift App请求用户为应用评分
Swift App请求用户为应用评分

Swift App请求用户为应用评分

在 Swift 应用中,SKStoreReviewController 提供了 requestReview(in:) 方法,用于在 App 内部请求用户为应用评分。此功能通常在特定的用户行为或使用场景下触发。例如,在完成订单、解锁成就或达到特定使用时间后请求用户进行评分。

特殊环境键 requestReview

在 SwiftUI 中,可以通过 Environment(\.requestReview) 来访问 requestReview 环境键。该键与 SKStoreReviewController.requestReview(in:) 方法相连,使得在 SwiftUI 的视图中也能轻松触发评分请求。

使用方法

1、确保项目已导入 StoreKit 框架。

import StoreKit

2、在 SwiftUI 视图中使用 Environment(\.requestReview) 键。

@Environment(\.requestReview) var requestReview

3、通过按钮调取requestReview

Button("Leave a review") {
    requestReview()
}

代码示例

import SwiftUI
import StoreKit

struct ContentView: View {
    @Environment(\.requestReview) private var requestReview  // 引入 requestReview 环境键

    var body: some View {
        VStack {
            Text("Welcome to our app!")
                .font(.title)
                .padding()

            Button("Rate Our App") {
                // 触发评分请求
                requestReview()
            }
            .padding()
            .background(Color.blue)
            .foregroundColor(.white)
            .cornerRadius(8)
        }
    }
}

#Preview {
    ContentView()
}

功能说明

1、@Environment(\.requestReview)

将评分请求的触发方法绑定到视图环境。

按需调用 requestReview() 即可触发评分弹窗。

2、限制

苹果对评分弹窗的频率有严格限制。调用 requestReview() 不一定会每次显示评分弹窗。

苹果会根据用户行为和应用历史评分决定是否显示。

3、用户体验

应避免频繁调用评分弹窗。最佳实践是根据特定的用户交互,例如完成某项任务后,调用评分请求。

注意事项

调用频率限制:苹果强烈建议只在适当时机调用 requestReview(),并保证不会打扰用户。

测试时的行为:在开发环境中,requestReview() 不会每次都显示评分弹窗。可以在 TestFlight 或实际发布后测试。

替代方法:如果需要更灵活的评分策略,可以通过跳转到 App Store 的页面完成评分:

if let url = URL(string: "itms-apps://itunes.apple.com/app/id<YOUR_APP_ID>?action=write-review") {
    UIApplication.shared.open(url)
}

代码示例

Button("Rate Our App") {
    // 触发评分请求
    if let url = URL(string: "itms-apps://itunes.apple.com/app/id6503047096?action=write-review") {
        UIApplication.shared.open(url)
    }
}

通过将评分请求嵌入到用户操作的自然流中,可以提升用户参与感,同时不会打扰他们的体验。

运行在主线程

@Environment(\.requestReview) 是一个与主线程(主Actor)关联的环境值。在实际应用中,调用 requestReview() 时,它需要在主线程上执行。

如果调用的方法并没有被标记为运行在主线程(主Actor)上,编译器会提示该调用是从非主线程上下文发出的。

例如:

func setFilter(_ filter: CIFilter) {
    currentFilter = filter
    loadImage()
    filterCount += 1

    if filterCount >= 5 {
        requestReview() // 报错
    }
}

在上面的方法中,因为该方法没有运行在主线程上,Xcode会报错:

Call to main actor-isolated instance method 'callAsFunction()' in a synchronous nonisolated context

解决方案

为了确保 requestReview() 在主线程上运行,可以将 setFilter 方法标记为在主Actor上运行,方法是使用 @MainActor 属性修饰。

@MainActor
func setFilter(_ filter: CIFilter) {
    currentFilter = filter
    loadImage()
    filterCount += 1

    if filterCount >= 20 {
        requestReview()
    }
}

1、@MainActor 的作用

主Actor是用来保证UI更新和与系统UI相关的操作(如请求评论窗口、动画、导航等)在主线程上执行的。

标记方法为 @MainActor 会告诉Swift运行时,确保此方法的调用在主线程上进行。

2、为什么需要主线程

requestReview() 是与UI交互相关的操作,必须在主线程上调用。

Swift 通过静态检查保证这种调用的安全性,因此给出了这个错误提示。

3、添加 @MainActor 的影响

修饰了 setFilter 方法后,所有调用它的代码都会自动切换到主线程,即使它们原本可能运行在后台线程。

如果您认为这篇文章给您带来了帮助,您可以在此通过支付宝或者微信打赏网站开放者。

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注