【问题标题】:SKStore​Review​Controller, How to use it in a correct way?SKStore​Review​Controller,如何正确使用?
【发布时间】:2017-04-03 05:42:48
【问题描述】:

我已经看到了一些答案,但对它们不满意并得到了一些想法,但不知道如何正确使用它,以便它以正确的方式执行,尽管我认为它应该在 App 代表中使用 @987654322 @,但我想确定在 Live 应用程序中实施它之前没有任何喧嚣。 SKStore​Review​Controller 仅适用于我阅读的 ios 10.3,任何人都可以用 swift 和客观的 c 中的一点代码来解释。

更新:

其实我对调用request​Review()这个方法很困惑,我需要在哪里调用这个方法?在rootViewControllerviewDidLoadappDelegatedidFinishlaunching 中?

谢谢。

【问题讨论】:

标签: ios objective-c iphone ios10.3 skstorereviewcontroller


【解决方案1】:

SKStoreReviewController 在 iOS 10.3 及更高版本中可用。

根据 APPLE 的文件:

您可以要求用户在使用您的应用时对其进行评分或评价, 无需将它们发送到 App Store。您可以确定 调用 API 和系统有意义的用户体验 其余的会处理。

为了在应用内显示评分/评论,您必须添加StoreKitframework。

请找到两种语言的示例代码:

目标 C:

#import <StoreKit/StoreKit.h>

- (void)DisplayReviewController {
    if([SKStoreReviewController class]){
       [SKStoreReviewController requestReview] ;
    }
}

从 xCode 9 开始,您可以这样做:

#import <StoreKit/StoreKit.h>

- (void)DisplayReviewController {
    if (@available(iOS 10.3, *)) {
        [SKStoreReviewController requestReview];
    }
}

斯威夫特:

import StoreKit

func DisplayReviewController {
    if #available( iOS 10.3,*){
        SKStoreReviewController.requestReview()
    }
}

更新:Ask for a rating only after the user has demonstrated engagement with your app

【讨论】:

  • 这取决于你想在哪里显示它。
  • 另外,根据文档developer.apple.com/reference/storekit/skstorereviewcontroller/…,苹果声明是“此方法可能会或可能不会显示警报,不适合调用它来响应按钮点击或其他用户操作。”跨度>
  • 您可以要求您的客户在整个用户体验过程中的适当时间在 App Store 上对您的应用进行评分和评论。
  • 从Xcode 9开始,你可以使用if(@available(iOS 10.3, *))代替if ([SKStoreReviewController class])
  • @EmreGürses,如果您的应用处于测试阶段,即在模拟器或测试设备中,发送按钮将自动禁用,一旦您的应用上线,发送按钮将自动可见。
【解决方案2】:

添加到上面korat的好答案...

如果您支持旧的 Objective-C 应用,并且您想在打开几个应用后调用 DisplayReviewController,请执行以下操作:

在你的类 AppDelegate.m 中添加:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  int count = [[NSUserDefaults standardUserDefaults] integerForKey:@"LaunchCount"];
  if(count < 0) count = 0;
  [[NSUserDefaults standardUserDefaults] setInteger:count+1 forKey:@"LaunchCount"];
}

//The application was in background and become active
- (void)applicationWillEnterForeground:(UIApplication *)application {
  int count = [[NSUserDefaults standardUserDefaults] integerForKey:@"LaunchCount"];
  if(count < 0) count = 0;
  [[NSUserDefaults standardUserDefaults] setInteger:count+1 forKey:@"LaunchCount"];
}

在控制器中你要调用函数:

- (void)applicationDidBecomeActive {

  if ([[NSUserDefaults standardUserDefaults] integerForKey:@"LaunchCount"] == 5) {
     [self DisplayReviewController];
  }
}

【讨论】:

    【解决方案3】:

    这是我正在为自己的用例开发的实用功能,它可能会帮助很多其他人。 (请随意烘烤和改进/更正我的代码:D)。我正在开发一个语音练习应用程序,我想在用户完成一些录音后要求评分。我将添加主要功能,然后在其下方使用其他辅助功能。简单的逻辑是,您一年可以请求审查 3 次,所以如果 1 year has passed,我将请求计数重置为 0。此外,不会针对每个请求提出审查请求。因此,在我不再允许该应用程序尝试审查请求之前,我有 30 个请求的上限。如果应用版本已更改,则不会考虑这一点,因为您可以再次要求对新应用版本进行审核。

    /// Requests review from user based on certain conditions.
    /// 1. Should have recorderd at least 3 recordings (if you want to force attept a review ask don't pass any parameter)
    /// 2. Has not already asked for a review today
    /// 3. A probabitly of 50% if will ask today
    /// 4. If review has not been asked more than 30 times in the same year for the current version
    /// - Parameter numberOfRecordings: If the number of recordings is greater than 3 then a review will be asked.
    func askForReview(numberOfRecordings: Int = 5) {
        let defaults = UserDefaults.standard
        let lastAskedReviewAt = defaults.double(forKey: lastAskedReviewAtKey)
        let dateStringForLastReviewAsk = getDateString(from: lastAskedReviewAt)
        let dateForLastReviewAsk = getDate(from: dateStringForLastReviewAsk) ?? Date(timeIntervalSince1970: 0)
        let askedReviewToday = Calendar.current.isDateInToday(dateForLastReviewAsk)
        var appReviewRequestsCount = defaults.integer(forKey: appReviewRequestsCountKey)
        
        if Date().localDate().years(from: dateForLastReviewAsk) >= 1 {
            defaults.setValue(0, forKey: appReviewRequestsCountKey)
            appReviewRequestsCount = 0
        }
        
        var isAskingReviewForSameVersion = false
        
        if let currentlyInstalledVersion = getInstalledVersionNumber(), let lastReviewAskedForVersion = defaults.string(forKey: lastReviewAskedForVersionKey) {
            if currentlyInstalledVersion == lastReviewAskedForVersion {
                isAskingReviewForSameVersion = true
            } else {
                appReviewRequestsCount = 0
                defaults.setValue(0, forKey: appReviewRequestsCountKey)
            }
        }
        
        let askingReviewTooManyTimes = appReviewRequestsCount >= 30 && isAskingReviewForSameVersion
        
        let totalRecordingsTillDateCount = defaults.integer(forKey: totalRecordingsTillDateCountKey)
        let localNumberOfRecordings = max(numberOfRecordings, totalRecordingsTillDateCount)
        
        if localNumberOfRecordings > 3 && Bool.random() && !askedReviewToday && !askingReviewTooManyTimes {
            SKStoreReviewController.requestReview()
            defaults.setValue(Date().timeIntervalSince1970, forKey: lastAskedReviewAtKey)
            if let versionNumber = getInstalledVersionNumber() {
                defaults.setValue(versionNumber, forKey: lastReviewAskedForVersionKey)
            }
            defaults.setValue(appReviewRequestsCount + 1, forKey: appReviewRequestsCountKey)
        }
    }
    

    字典键:

    let lastAskedReviewAtKey = "LastAskedReviewAt"
    let appReviewRequestsCountKey = "AppReviewRequestsCount"
    let lastReviewAskedForVersionKey = "AskedReviewForVersion"
    let appVersionNumberKey = "CFBundleShortVersionString"
    

    辅助函数:

    /// Get a string representation in current local time for a timestamp
    /// - Parameter timestamp: Timestamp to be converted to date string
    /// - Returns: A date string from passed timestamp in dd MMM yyy format
    func getDateString(from timestamp: Double) -> String {
        let dateFormatter = getDateFormatter()
        let date = Date(timeIntervalSince1970: timestamp)
        let dateString = dateFormatter.string(from: date)
        return dateString
    }
    
    /// Get a date from a string of date format dd MMM yyyy.
    /// - Parameter dateString: Date string formated as dd MMM yyyy
    /// - Returns: A date object by parsing date in dd MMM yyy format
    func getDate(from dateString: String) -> Date? {
        //        print("Date String: ", dateString)
        let dateFormatter = getDateFormatter()
        return dateFormatter.date(from: dateString) ?? nil
    }
    
    
    //Ref: https://stackoverflow.com/questions/27182023/getting-the-difference-between-two-dates-months-days-hours-minutes-seconds-in
    extension Date {
        /// Returns the amount of years from another date
        func years(from date: Date) -> Int {
            return Calendar.current.dateComponents([.year], from: date, to: self).year ?? 0
        }
        /// Returns the amount of months from another date
        func months(from date: Date) -> Int {
            return Calendar.current.dateComponents([.month], from: date, to: self).month ?? 0
        }
        /// Returns the amount of weeks from another date
        func weeks(from date: Date) -> Int {
            return Calendar.current.dateComponents([.weekOfMonth], from: date, to: self).weekOfMonth ?? 0
        }
        /// Returns the amount of days from another date
        func days(from date: Date) -> Int {
            return Calendar.current.dateComponents([.day], from: date, to: self).day ?? 0
        }
        /// Returns the amount of hours from another date
        func hours(from date: Date) -> Int {
            return Calendar.current.dateComponents([.hour], from: date, to: self).hour ?? 0
        }
        /// Returns the amount of minutes from another date
        func minutes(from date: Date) -> Int {
            return Calendar.current.dateComponents([.minute], from: date, to: self).minute ?? 0
        }
        /// Returns the amount of seconds from another date
        func seconds(from date: Date) -> Int {
            return Calendar.current.dateComponents([.second], from: date, to: self).second ?? 0
        }
        /// Returns the a custom time interval description from another date
        func offset(from date: Date) -> String {
            if years(from: date)   > 0 { return "\(years(from: date))y"   }
            if months(from: date)  > 0 { return "\(months(from: date))M"  }
            if weeks(from: date)   > 0 { return "\(weeks(from: date))w"   }
            if days(from: date)    > 0 { return "\(days(from: date))d"    }
            if hours(from: date)   > 0 { return "\(hours(from: date))h"   }
            if minutes(from: date) > 0 { return "\(minutes(from: date))m" }
            if seconds(from: date) > 0 { return "\(seconds(from: date))s" }
            return ""
        }
    }
    
    //Ref: https://stackoverflow.com/questions/28404154/swift-get-local-date-and-time
    extension Date {
        func localDate() -> Date {
            let nowUTC = Date()
            let timeZoneOffset = Double(TimeZone.current.secondsFromGMT(for: nowUTC))
            guard let localDate = Calendar.current.date(byAdding: .second, value: Int(timeZoneOffset), to: nowUTC) else {return Date()}
    
            return localDate
        }
    }
    
    func getInstalledVersionNumber() -> String? {
        guard let infoDictionary = Bundle.main.infoDictionary, let currentVersionNumber = infoDictionary[appVersionNumberKey] as? String else { return nil}
        return currentVersionNumber
    }
    

    【讨论】:

      【解决方案4】:

      对于斯威夫特,

      import StoreKit
      

      当你想询问时,添加下面的代码来请求。

      if #available(iOS 10.3, *) {
              SKStoreReviewController.requestReview()
          }
      

      对于目标 C,

      1-) 从 Link Binary With Library 添加了 StoreKit 框架

      2-) 添加框架

      #import <StoreKit/StoreKit.h>
      

      3-) 在下面添加了您要调用 App-Review 弹出窗口的代码。在这种情况下,我在 viewDidLoad 中添加了。

        - (void)viewDidLoad {
              [super viewDidLoad];
              [SKStoreReviewController requestReview];
          }
      

      4-) 当您在调试模式下进行测试时,您应该了解 Apple 的以下说明

      当您在应用仍处于开发模式时调用此方法时,将始终显示评分/评论请求视图,以便您可以测试用户界面和体验。但是,当您在使用 TestFlight 分发的应用程序中调用此方法时,该方法无效。

      【讨论】:

      • 生产中的“无效果”是什么意思?
      • App Store 不会显示您的汇率和 cmets。
      • 这就是为什么“发送”按钮是灰色的?此外,这要求用户对应用程序进行评分(从 1 星到 5 星),但我不知道如何要求用户也写评论?
      • @Balanced 评论按钮将在点击星级后显示给您。因此,当您处于开发模式时,您永远不会测试此功能。
      【解决方案5】:

      我认为直接调用下面的不是一个好主意

      SKStoreReviewController.requestReview()

      它可以像每当用户打开你的应用程序 10(10,20,30,...100) 的倍数然后你可以显示以供审查一样这样做

      所以首先您需要创建一个文件,该文件将负责所有事情,例如将应用程序打开计数保存在用户默认值中、检索应用程序打开计数以及显示 requestReview() 请看下面的代码sn-p

      import Foundation
      import StoreKit
      class  SpsRateManager {
          
          
          private static let instance = SpsRateManager()
          
          var shareinstance: SpsRateManager{
              return .instance
          }
          static func incrementAppOpenedCount() { // called from appdelegate didfinishLaunchingWithOptions:
              let userdefault = UserDefaults.standard
              
              
              let savedvalue = userdefault.integer(forKey: Configuration.APPLICATIONOPENCOUNTSTATUS)
              if savedvalue == 0 {
                  print("Not saved ")
                  userdefault.set(1, forKey: Configuration.APPLICATIONOPENCOUNTSTATUS)
              }
              else{
                  userdefault.set(savedvalue+1, forKey: Configuration.APPLICATIONOPENCOUNTSTATUS)
                  
              }
              
          }
          
          static func checkAppopencountandProvideReview(){
              let userdefault = UserDefaults.standard
              
              
              let appopencountvalue  = userdefault.integer(forKey: Configuration.APPLICATIONOPENCOUNTSTATUS)
              if appopencountvalue % 10 == 0 {
                  print("its been 10 times so ask for review ")
                  SpsRateManager().requestReview()
              }
              else{
                  print("not enough open count dont show ")
              }
              
          }
          
          
          
          
          fileprivate func requestReview() {
              if #available(iOS 10.3, *) {
                  SKStoreReviewController.requestReview()
              } else {
                  // Fallback on earlier versions
                  // Try any other 3rd party or manual method here.
              }
          }
          
      }
      

      【讨论】:

        【解决方案6】:

        我认为您可以实现一种方法来在他们运行应用程序时进行计数并将其存储在 UserDefaults 中,然后如果计数为 5 或 10 或类似的值(这取决于您),则通过这种方式调用 requestReview()您有更多机会获得好评。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2015-10-13
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多