SKStore Review Controller, как правильно его использовать?

Я видел какой-то ответ, но не удовлетворен им и получил некоторое представление, но не знаю, как правильно его использовать, чтобы он работал правильно, хотя я думаю, что его следует использовать в делегатах приложения didFinishLaunching, но я хотел быть уверен, прежде чем внедрить его в приложение Live без каких-либо суеты. SKStore​Review​Controller Это только работа для IOS 10.3, что я прочитал, кто-нибудь может объяснить с небольшим количеством кода в быстрой и объективной c.

ОБНОВИТЬ:

На самом деле я запутался в вызове метода request​Review()Где мне нужно вызвать этот метод? в rootViewController"s viewDidLoad или в appDelegate"s didFinishlaunching?

Благодарю.

6 ответов

SKStoreReviewController доступно в iOS 10.3 и более поздних версиях.

Согласно документам Apple:

Вы можете попросить пользователей оценить или проверить ваше приложение, пока они его используют, не отправляя их в App Store. Вы определяете точки взаимодействия с пользователем, при которых имеет смысл вызывать API, а система позаботится об остальном.,

Чтобы отобразить рейтинг / обзор внутри приложения, вы должны добавить StoreKitфреймворк.

Пожалуйста, найдите пример кода для обоих языков:

Цель 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];
    }
}

Swift:

import StoreKit

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

Обновление: запрашивайте рейтинг только после того, как пользователь продемонстрировал взаимодействие с вашим приложением

Для цели C,

1-) Добавлен фреймворк StoreKit из Link Binary With Library введите описание изображения здесь

2-) Добавлены рамки

#import <StoreKit/StoreKit.h>

3-) Добавлен код ниже, где вы хотите вызвать всплывающее окно App-Review. В этом случае я добавил в viewDidLoad.

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

4-) Вы должны знать ниже объяснить от Apple, когда вы тестируете в режиме отладки

Когда вы вызываете этот метод, когда ваше приложение все еще находится в режиме разработки, всегда отображается представление запроса оценки / обзора, чтобы вы могли протестировать пользовательский интерфейс и опыт. Однако этот метод не действует, когда вы вызываете его в приложении, которое вы распространяете с помощью TestFlight.

Я думаю, что прямой вызов ниже не очень хорошая идея

SKStoreReviewController.requestReview()

Это можно сделать так, как если бы пользователь открывал ваше приложение, кратное 10(10,20,30,...100), тогда вы можете показать его для просмотра.

поэтому прежде всего вам нужно создать файл, который будет отвечать за все, например, сохранение счета открытия вашего приложения в userdefaults, извлечение счета открытия приложения и отображение requestReview (). Пожалуйста, взгляните на следующий фрагмент кода

   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.
    }
}

}

Добавление на великий ответ Кората выше...

Если вы поддерживаете устаревшее приложение 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];
  }
}

Я думаю, что вы можете реализовать метод подсчета, когда они запускают приложение, и сохранить его в UserDefaults, а затем вызвать requestReview(), если число отсчетов равно 5 или 10 или что-то в этом роде (это зависит от вас), таким образом, у вас есть больше шанс получить хороший обзор.

Вот служебная функция, которую я разрабатываю для своего собственного варианта использования, которая может помочь многим другим людям. (Не стесняйтесь жарить и улучшать / исправлять мой код:D). Я работаю над приложением для речевой практики и хочу попросить оценку после того, как пользователь сделал несколько записей. Я добавлю основную функцию, а затем другие вспомогательные функции, используемые под ней. Краткая логика заключается в том, что вы можете запрашивать проверку 3 раза в год, поэтому, если прошел 1 год , я сбрасываю счетчик запросов на 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
}
Другие вопросы по тегам