YMPromptKit 1.0.2

YMPromptKit 1.0.2

测试已测试
Lang语言 Obj-CObjective C
许可 Apache 2
发布上次发布2015年9月

Adam Kaplan 维护。




  • 作者:
  • adamkaplan

YMPromptKit 通过提供灵活的可扩展工具来简化您的应用程序代码,以实现软提示。等等,什么让提示变得 呢?

两种提示类型

  1. 硬提示 - 硬提示是 iOS 为获取用户访问受保护资源(如位置或联系人)的权限而提供的典型对话框。这是因为提示显示后,结果很难改变,所以被认为很“硬”。
  2. 软提示 - 当提示的结果没有被锁定时,提示就是软的。软提示可以显示多次,给应用程序第二次(或第三次或第四次)机会向用户展示其价值主张。

您为什么需要软提示

在 iOS 中最知名的硬提示是推送通知。这些通知的价值不容低估。应用程序的生存与否取决于其能够在您的移动设备屏幕上弹出高度相关且有即时操作性的警报的能力——或缺乏这种能力。不幸的是,一旦用户拒绝允许您向他们推送通知,您就没有多少选择了(很少有用户会费心手动重新启用该功能)。这一问题已经在 广泛讨论

安装

最简单的安装方式是使用 CocoaPods。Pod 的名称为 YMPromptKit。

pod 'YMPromptKit', '~> 1.0.0'

如果您不使用 CocoaPods,则需要将 YMPromptKit/ 目录中的所有类添加到项目中。

YMPromptKit 默认依赖于 SDCAlertView(参见下一节)。

在不使用 SDCAlertView 的情况下使用 iOS 本地警报

SDCAlertView 为 YMPromptKit 增加了功能价值及可靠性。但是,如果您无法使用 SDCAlertView 或其依赖项,或者遇到其他问题,您可以选择使用简单的 pod 引用来使用 iOS 本地提示

pod 'YMPromptKit/NativeAlerts', '~> 1.0.0`

请参阅 实现说明

支持

YMPromptKit 支持 iOS 7.0 及更高版本。

由于依赖在 iOS 8.0 中引入的 API,某些功能在 iOS 7.0 下的性能会有所降低。在适用的情况下,这些差异已在 API 注释中注明。

使用方法

对不急于求成的用户...

示例应用程序位于 示例 文件夹 中。请查看。

提供的软提示

一些 iOS 软提示已预装载,可直接使用。这些包括:

  1. 推送通知
  2. 位置服务
  3. 日历事件 & 提醒
  4. 录音 / 麦克风访问
  5. 照片库
  6. 通讯录 & 联系人

按照需要也可以添加额外的私有提示,例如请求用户登录或邀请朋友。

基本推送通知提示

basic prompt

首先需要包含 YMPromptKit 的头文件,并分配一个 YMPromptManager 实例的空间

#import <YMPromptKit/YMPromptKit.h>

@interface AppDelegate : NSObject <UIApplicationDelegate>
@property (nonatomic, readonly) YMPromptManager *promptManager;
@end

现在获取一个 YMPromptManager 的引用。最简单的方法是创建一个包含所有预配置提示处理程序的提示管理器

_promptManager = [YMPromptManager createPromptManager];

提示管理器需要一个数据源来告诉它要向用户显示什么。在这种情况下,让我们把自己作为数据源。

self.promptManager.dataSource = self;

要实现数据源,我们需要提供一个提供 YMPrompt 实例的方法。对于这个例子,让我们假装我们只关心推送通知。添加以下方法:

- (YMPrompt *)promptManager:(YMPromptManager *)manager
        promptForAccessType:(YMPromptAccessType)access
                      modes:(YMPromptAccessMode)modes {

  if (access == kYMPromptAccessTypeNotifications) {
    YMPrompt *prompt = [YMPrompt promptWithTitle:@"Stock Alerts"
                                         message:@"Allow Yahoo Finance to send you important alerts"
                                                 @"about stocks you follow?"
                                      grantTitle:@"Yes"
                                       denyTitle:nil
                                     contentView:nil];
    return prompt;
  }

  return nil;
}

现在,当您的应用程序中的某些代码请求 YMPromptManager 请求推送通知的权限时,提示管理器将从我们这里获取一个 YMPrompt 实例。我们将提供的提示将有一个自定义标题、消息和授权权限按钮标签。不允许按钮标题将不会指定;它将默认为 "稍后再说"。

在您的应用程序的任何位置触发提示,如下所示

[delegate.promptManager requestAccess:kYMPromptAccessTypeNotifications
                                modes:YMPromptNotificationOptionTypeAlert
                    completionHandler:^(BOOL softPromptAccepted, BOOL osPromptAccepted, YMPromptAuthorizationStatus status) {
                        if (softPromptAccepted) {
                            if (osPromptAccepted) {
                                // User accepted the soft prompt and the OS prompt. Win!
                            } else {
                                // User accepted the soft prompt, but denied the OS prompt. Lose :(
                            }
                        } else {
                            if (status == YMPromptAuthorizationStatusNotDetermined) {
                                // The user declined your soft prompt. Not a win, not a loss.
                            } else if (status == YMPromptAuthorizationStatusDenied) {
                                // Already denied access by the OS
                            } else if (status == YMPromptAuthorizationStatusRestricted) {
                                // Already authorized, but there is some OS restriction
                            } else if (status == YMPromptAuthorizationStatusAuthorized) {
                                // Already authorized by the OS
                            }
                        }
                    }];

对于 iOS 8,您必须手动使用提示管理器记录注册结果。在您的应用程序代理中,在 -application: didRegisterUserNotificationSettings: 中记录通知注册结果。这也是您注册远程通知的时机。

- (void)application:(UIApplication *)application didRegisterUserNotificationSettings:(UIUserNotificationSettings *)notificationSettings {
    BOOL success = (notificationSettings.types != UIUserNotificationTypeNone);
    [delegate.promptManager recordNotificationRegistrationResult:success];

    // Permission was granted, register for remote notifications
    [application registerForRemoteNotifications];
}

使用 YMPromptManagerDelegate 强制执行节奏

软提示非常棒,但确保避免过于频繁地打扰用户的请求是一个提高用户退出率的方法。YMPromptKit 可以帮您实现合适的提示节奏。让我们确保我们的示例应用程序在 48 小时内不会要求推送通知权限超过一次,或者不超过 3 次。

添加一个代理方法,为提示管理器提供一些特定于应用程序的指导

- (BOOL)promptManager:(YMPromptManager *)manager shouldRequestAccessType:(YMPromptAccessType)accessType
                modes:(YMPromptAccessMode)modes {

    NSArray *promptLog = [manager.log promptHistory:accessType];

    if (promptLog.count > 3) {
        return NO;                              // enforce the request limit
    } else if (promptLog.count) {
        NSDictionary *dict = promptLog[0];     // data for the most recent history entry
        NSDate *lastPromptDate = dict[kYMPromptLogDateKey];
        NSTimeInterval interval = -3600 * 48;   // 2 days, in seconds

        if ([lastPromptDate timeIntervalSinceNow] > interval) {
            return NO;                          // enforce the quiet period
        }
    }

    return YES;                                 // OK to display prompt!
}

上述代码使用提示日志来访问指定访问类型的提示历史记录。每个 YMPromptManager 都可以通过其 log 属性访问 YMPromptLog。默认的提示管理器——那些由 [YMPromptManager createPromptManager] 返回的——始终使用可在 [YMPromptLog mainLog] 中获取的主提示日志。

在显示提示之前,一个 YMPromptManager 将向其 YMPromptLog 实例添加一个日期项。因此,提示日志代表了软提示的近期历史记录(默认情况下,每种类型的最后 15 次)。历史记录定期刷新到磁盘,并在会话之间持久化。

YMPromptLog 中跟踪自定义参数

尽管软提示发生日期足以提供对节奏的粗略控制,但可以想象出无法通过此类有限数据满足的业务要求。为了解决这个问题,YMPromptLog 可以接受任意 NSPropertyListSerialization 兼容的元数据,并将其存储在每个事件条目中。

让我们为示例添加一个要求:五个会话必须在中按推送通知软提示之间进行。为此,实现YMPromptManagerDelegate方法。

- (NSDictionary *)promptManager:(YMPromptManager *)manager
          willRequestAccessType:(YMPromptAccessType)accessType
                          modes:(YMPromptAccessMode)modes {

    NSNumber *sessionNum = self.sessionNumber;

    return @{ @"session_number":  sessionNum };
}

现在,每个事件都将有一个关联的字典,其中包含它在其中显示的会话编号。我们可以访问此信息,并使用它从-promptManager:shouldRequestAccessType:modes:代理方法中应用特定于应用程序的逻辑。扩展上面的代理方法示例:

- (BOOL)promptManager:(YMPromptManager *)manager shouldRequestAccessType:(YMPromptAccessType)accessType
                modes:(YMPromptAccessMode)modes {

    NSArray *promptLog = [manager.log promptHistory:accessType];

    if (promptLog.count > 3) {
        return NO;                              // enforce the request limit
    } else if (promptLog.count) {
        NSDictionary *dict = promptLog[0];     // data for the most recent history entry
        NSDate *lastPromptDate = dict[kYMPromptLogDateKey];
        NSTimeInterval interval = -3600 * 48;   // 2 days, in seconds

        if ([lastPromptDate timeIntervalSinceNow] > interval) {
            return NO;                          // enforce the quiet period
        } else {

#pragma  >>> New example code starts here >>>

            NSDictionary *appData = dict[kYMPromptLogUserInfoKey];
            NSNumber *lastSessionNum = appData[@"session_number"];
            NSNumber *sessionNum = self.sessionNumber;

            if ([sessionNum integerValue] < [lastSessionNum integerValue] + 5) {
                return NO;                      // enforce minimum sessions betwen prompting
            }
        }
    }

    return YES;                                 // OK to display prompt!
}

在提示中嵌入自定义视图

YMPromptKit利用SDCAlertView提供灵活的、类似于iOS的原生警报。这种设计带来的一个主要优势是软提示可以包括嵌入的自定义视图——即使在iOS 7上。

image in prompt

让我们在上面的运行示例中使用类似的图像进行添加。

- (YMPrompt *)promptManager:(YMPromptManager *)manager
        promptForAccessType:(YMPromptAccessType)access 
                      modes:(YMPromptAccessMode)modes {

    UIImage *image = [UIImage imageNamed:@"push-notification.png"];
    UIImageView *imageView = [[UIImageView alloc] initWithImage:image];
    imageView.frame = CGRectMake(0, 0, 150, 150);
    imageView.contentMode = UIViewContentModeScaleAspectFit;

    if (access == kYMPromptAccessTypeNotifications) {

    YMPrompt *prompt = [YMPrompt promptWithTitle:@"Stock Alerts"
                                         message:@"Allow Yahoo Finance to send you important alerts"
                                                 @"about stocks you follow?"
                                      grantTitle:@"Yes"
                                       denyTitle:nil
                                     contentView:imageView];
    }
    return prompt;

实现说明

手动关闭警报

为YMPromptKit提供动力的SDCAlertView是通过呈现模态视图控制器来工作的。当关闭警报时(即通过其按钮),SDCAlertView调用YMPromptKit完成块,然后调用本地应用的完成块。注意:如果手动调用-dismissModalViewController,则不会触发完成块。

使用原生(非SDC)警报时的权衡

  • 不支持自定义警报子视图。如果指定了,它们将被静默忽略。
  • iOS7不支持基于块的警报,这要求在显示软提示时保持内部状态。如果客户端在收到完成回调之前尝试呈现additional软提示,该内部状态可能会被破坏,导致未定义的行为。

支持 & 贡献

将任何错误报告或发送功能请求到GitHub问题。 Pull requests非常受欢迎。有关详细信息,请参阅CONTRIBUTING

许可

Apache 2.0许可证。有关详细信息,请参阅LICENSE文件。