はじめに
アプリのレビューはSKStoreReviewControllerを使うと、OSの体裁に沿ったレビュー依頼ダイアログを表示してくれます。
そもそもアプリのレビュー依頼はこの方法以外でやってはいけないようです。
実際表示されるのはこんな感じのダイアログです。
どうやってSwiftUIで使うの?
Controllerという名前の通り、UIKitのクラスなのでUIViewControllerRepresentableでラップしてやる必要があります。
ほぼ公式サンプルの丸パクリですが、私はStoreReviewViewという名前のクラスでラップして使っています。
import Foundation
import UIKit
import SwiftUI
import StoreKit
struct StoreReviewView: UIViewControllerRepresentable {
typealias Callback = (_ activityType: UIActivity.ActivityType?, _ completed: Bool, _ returnedItems: [Any]?, _ error: Error?) -> Void
func makeUIViewController(context: UIViewControllerRepresentableContext<StoreReviewView>) -> UIViewController {
let controller = UIViewController()
return controller
}
func checkAndShowReview() {
// If the count has not yet been stored, this will return 0
var count = UserDefaults.standard.integer(forKey: UserDefaults.processCompletedCountKey)
count += 1
UserDefaults.standard.set(count, forKey: UserDefaults.processCompletedCountKey)
// Get the current bundle version for the app
let infoDictionaryKey = kCFBundleVersionKey as String
guard let currentVersion = Bundle.main.object(forInfoDictionaryKey: infoDictionaryKey) as? String
else { fatalError("Expected to find a bundle version in the info dictionary") }
let lastVersionPromptedForReview = UserDefaults.standard.string(forKey: UserDefaults.lastVersionPromptedForReviewKey)
// Has the process been completed several times and the user has not already been prompted for this version?
if count >= 4 && currentVersion != lastVersionPromptedForReview {
let twoSecondsFromNow = DispatchTime.now() + 2.0
DispatchQueue.main.asyncAfter(deadline: twoSecondsFromNow) {
SKStoreReviewController.requestReview()
UserDefaults.standard.set(currentVersion, forKey: UserDefaults.lastVersionPromptedForReviewKey)
}
}
}
func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<StoreReviewView>) {
}
}
extension UserDefaults {
class var processCompletedCountKey: String {
return "processCompletedCount"
}
class var lastVersionPromptedForReviewKey: String {
return "lastVersionPromptedForReview"
}
}
呼び出し方
ダイアログを表示したいViewのonAppearでcheckAndShowReview()を呼びます。
本当はUIKitで言うviewDidLoad()のタイミングで処理を行いたいところですが、SwiftUIなのでそれはできません。
苦肉の策ですが、onApperでPIDチェックを行うことで表示される度にカウントが増えることを防止します。
import SwiftUI
struct MainView: View {
@State private var pid : Int32 = 0
var body: some View {
VStack {
Text("Hello")
}.onAppear() {
if(pid != ProcessInfo.processInfo.processIdentifier) {
StoreReviewView().checkAndShowReview()
pid = ProcessInfo.processInfo.processIdentifier
}
}
}
}
struct MainView_Previews: PreviewProvider {
static var previews: some View {
MainView()
}
}