InAppSettingsKit 3.7.2

InAppSettingsKit 3.7.2

测试已测试
语言语言 Obj-CObjective C
许可证 NOASSERTION
发布上次发布2024年7月

FutureTap 维护。



InAppSettingsKit

Build Status Version Swift Package Manager compatible Carthage compatible License Platform Sponsor Twitter

InAppSettingsKit (IASK) 是一个开源框架,可以轻松地将内联设置添加到您的 iOS 或 Catalyst 应用中。iOS 应用通常使用 Settings.bundle 资源来在设置应用中添加特定于应用的设置。InAppSettingsKit 利用相同的捆绑包,允许您在应用内展示相同的设置屏幕。因此,用户可以选择在哪里更改设置。

IASK 不仅复制了系统设置的特性集,还支持大量其他元素和配置选项。

从 IASK 2.x 升级? 请阅读 发布说明

它是如何工作的?

为了支持传统的 Settings.app 标签页,应用程序必须包含一个至少包含 Root.plistSettings.bundle,用于指定设置 UI 元素与 NSUserDefaults 键的连接。InAppSettingsKit基本上使用相同的 Settings.bundle 来完成其工作。这意味着当您想要包含一个新的设置参数时,无需额外的工作。只需将其添加到 Settings.bundle,它就会同时在应用程序和 Settings.app 中显示。支持所有类型的设置,如文本字段、滑块、切换元素、子视图等。

如何包含它?

源代码可在 github 上找到。有多种安装方式

使用 SPM

将其添加到您的 Package.swift 中

.package(name: "InAppSettingsKit", url: "https://github.com/futuretap/InAppSettingsKit.git", .branch("master"))

或者,前往 Xcodes 的 文件->Swift 包->添加包依赖... 菜单项,并添加 https://github.com/futuretap/InAppSettingsKit.git

使用 CocoaPods

将其添加到您的 Podfile 中

pod 'InAppSettingsKit'

使用 Carthage

将其添加到您的 Cartfile 中

github "futuretap/InAppSettingsKit" "master"

App 集成

为了开始使用 IASK,将 Settings.bundle 添加到您的项目中(文件 -> 添加文件 -> 设置捆绑包),并使用您的设置编辑 Root.plist(有关 Apple 关于 方案文件根内容 的说明)。继续阅读以了解更多高级用法。

要显示 InAppSettingsKit,实例化 IASKAppSettingsViewController 并将其推送到导航堆栈或嵌入导航控制器的根视图控制器。

使用 Swift 代码在代码中

let appSettingsViewController = IASKAppSettingsViewController()
navigationController.pushViewController(appSettingsViewController, animated: true)

使用 Objective-C 代码在代码中

IASKAppSettingsViewController *appSettingsViewController = [[IASKAppSettingsViewController alloc] init];
[self.navigationController pushViewController:appSettingsViewController animated:YES];

通过Storyboard

  • 将嵌入到导航控制器中的 Table View Controller 拖放到您的应用程序中,并通过Storyboard将其与您的应用程序UI连接
  • 将 Table View Controller 类设置为 IASKAppSettingsViewController
  • 将 Table View 设置为 "分组" 样式。
  • 如果您是以模态方式显示导航控制器
    • 在 Table View Controller 中,在“应用程序设置视图控制器”下将“显示完成按钮”设置为“开”
    • 设置符合 IASKAppSettingsViewControllerDelegate 的代理。
    • 实现代理方法 -settingsViewControllerDidEnd: 并关闭视图控制器。

示例应用程序显示了如何连接所有内容。

其他更改

为了自定义行为,实现 IASKSettingsDelegate 并将 IASKAppSettingsViewControllerdelegate 属性设置。对于更高级的自定义需求,支持对 IASKAppSettingsViewController 的子类化。

根据您的项目,可能需要在应用程序的启动代码中做出一些更改。您的应用程序必须在运行时能够根据用户的更改重新配置本身。这可以通过在 -applicationDidFinishLaunching 中调用的 -reconfigure 方法以及 IASKAppSettingsViewController 的代理方法 -settingsViewControllerDidEnd: 来完成。

附加功能

InAppSettingsKit 的目的是创建对 Settings.app 100% 的模仿(见Apple 设置应用架构参考)。在此基础上,我们还添加了大量附加功能,使 IASK 更加灵活和动态。

自定义 application 文件

设置 application 文件可能依赖于设备:iPad 上使用 Root~ipad.plist,iPhone 上使用 Root~iphone.plist。如果不存在,则使用 Root.plist

InAppSettingsKit 允许您使用 .inApp.plist 而不是 .plist 来覆盖这些标准文件。或者,您可以创建一个名为 InAppSettings.bundle 的单独的包,而不是通常的 Settings.bundle。后者适用于您想抑制 Settings.app 中的设置。

这是完全的搜索顺序

  • InAppSettings.bundle/FILE~DEVICE.inApp.plist
  • InAppSettings.bundle/FILE.inApp.plist
  • InAppSettings.bundle/FILE~DEVICE.plist
  • InAppSettings.bundle/FILE.plist
  • Settings.bundle/FILE~DEVICE.inApp.plist
  • Settings.bundle/FILE.inApp.plist
  • Settings.bundle/FILE~DEVICE.plist
  • Settings.bundle/FILE.plist

隐私链接

如果应用在Info.plist中包含了对相机或位置访问等隐私功能的使用密钥,IASK将在设置页面的顶部显示一个“隐私”单元格。此单元格将打开系统设置应用并显示应用的设置面板,用户可以在此指定应用的隐私设置。

如果不想显示隐私单元格,请将属性neverShowPrivacySettings设置为YES

示例应用定义了NSMicrophoneUsageDescription以使单元格显示出来。请注意,设置页面还没有显示任何隐私设置,因为应用实际上并没有访问麦克风。隐私设置只在使用受保护的隐私API之后在设置应用中显示。

打开URL

InAppSettingsKit添加了一个新元素IASKOpenURLSpecifier,允许使用外部应用(例如Safari或Mail)打开指定的URL。启动的URL在File参数中指定。有关详细信息,请参阅示例Root.inApp.plist

邮件编辑器

自定义的IASKMailComposeSpecifier元素允许通过打开邮件编辑视图在应用内发送邮件。您可以使用设置plist设置以下(可选)参数:IASKMailComposeToRecipentsIASKMailComposeCcRecipentsIASKMailComposeBccRecipentsIASKMailComposeSubjectIASKMailComposeBodyIASKMailComposeBodyIsHTML

- (BOOL)settingsViewController:(id<IASKViewController>)settingsViewController shouldPresentMailComposeViewController:(MFMailComposeViewController*)mailComposeViewController forSpecifier:(IASKSpecifier*)specifier;

在您的代理中实现以下代码以自定义邮件(例如,使用动态内容预填充正文、添加附件)修改编辑视图的外观,甚至阻塞标准呈现。如果设备上未配置电子邮件,将显示一个警告。

  • IASKSpecifier是定义单个设置单元格的内部模型对象。重要的IASKSpecifier属性
  • key:对应于设置plist中的Key
  • title:设置键的本地化标题
  • type:对应于设置plist中的Type

defaultValue:对应于设置plist中的DefaultValue

InAppSettingsKit 添加了一个 IASKButtonSpecifier 元素,允许调用自定义操作。只需添加以下代理方法:

- (void)settingsViewController:(IASKAppSettingsViewController*)sender buttonTappedForSpecifier:(IASKSpecifier*)specifier;

发送者始终是 IASKAppSettingsViewController 的一个实例,它是 UIViewController 的子类。因此,您可以访问其视图属性(可能用于显示操作表)或推送另一个视图控制器。另一个便捷的特性是,IASK按钮的标题可以由来自 NSUserDefaults(或任何其他设置存储 - see below)的可本地化值覆盖。这对于切换按钮(例如,登录/注销)很有用。请参阅示例应用程序以获取详细信息。

默认情况下,按钮居中对齐,除非指定了图像(默认:左对齐)。默认对齐方式可以被覆盖。

多行文本视图

类似于标准文本字段,IASKTextViewSpecifier 显示一个全宽多行文本视图,根据输入的文本进行大小调整。它还支持 KeyboardTypeAutocapitalizationTypeAutocorrectionType

日期选择器

IASKDatePickerSpecifier 显示一个 UIDatePicker 来设置日期和时间。它支持以下选项:

  • DatePickerMode:以下是《Date》、《Time》或《DateAndTime》之一(请参阅 UIDatePickerMode)。默认是《DateAndTime》。
  • DatePickerStyle:以下之一为《Compact》、《Wheels》或《Inline》(请参阅 UIDatePickerStyle)。默认是《Wheels》。此功能需要 iOS 14 或更高版本。如果不支持此操作系统,IASK 将回退到《Wheels》。
  • MinuteInterval:日期选择器显示分钟的间隔。默认:1。

有3个可选的委托方法可以自定义日期和时间的存储和显示方式

- (NSDate*)settingsViewController:(IASKAppSettingsViewController*)sender dateForSpecifier:(IASKSpecifier*)specifier;

实现此方法,如果日期/时间的存储格式不是NSDate对象。当用户通过选择日期/时间选择器上方的标题单元格开始编辑日期/时间时调用。

- (NSString*)settingsViewController:(IASKAppSettingsViewController*)sender datePickerTitleForSpecifier:(IASKSpecifier*)specifier;

实现此方法来自定义日期/时间选择器上方标题单元格中显示的值。

- (void)settingsViewController:(IASKAppSettingsViewController*)sender setDate:(NSDate*)date forSpecifier:(IASKSpecifier*)specifier;

实现此方法,如果日期/时间的存储格式不是NSDate对象。当用户使用选择器更改日期/时间值时调用。

列表组

列表组(IASKListGroupSpecifier)是仅适用于IASK的特性,允许您管理变量数量的事项,包括添加和删除。标签、账户、名称数组是典型应用场景。列表组包含多个ItemSpecifier事项。这些事项的数量由您在NSUserDefaults(或您的自定义设置存储)中的实际内容确定。换句话说,ItemSpecifier定义了单元格类型,而单元格数量和内容则来自NSUserDefaults或您的存储。如果将Deletable参数设置为YES,则可以通过滑动删除单元格。

可选的,列表组还有一个AddSpecifier来控制列表组部分的最后一个项目。它用于添加事项,可以是文本框、切换按钮、滑块或子面板。前三个在编辑完成后创建新项目,而子面板则显示模态子视图控制器来配置复杂项,作为字典保存。这些子面板与正常子面板非常类似,只有一些不同:它们不是通过推送方式显示,而是通过模态显示,在导航栏中有一个取消和完成按钮。通过点击完成按钮创建新项目。

您可能希望指定一些需要在启用完成按钮之前满足的验证规则。这可以通过代理方法实现:

- (BOOL)settingsViewController:childPaneIsValidForSpecifier:contentDictionary:

当从这个方法返回false时,完成按钮将被禁用。请注意,contentDictionary是一个可变字典。如果您更改某些值,UI将反映这些更改。这允许您自动纠正无效设置。

自定义视图

您可以在InAppSettingsKit中使用类型IASKCustomViewSpecifier指定自己的UITableViewCell。在这种情况下,必需的字段是Key属性。此外,您必须支持IASKSettingsDelegate协议并实现这些方法

- (CGFloat)settingsViewController:(UITableViewController<IASKViewController> *)settingsViewController heightForSpecifier:(IASKSpecifier *)specifier;
- (UITableViewCell*)settingsViewController:(UITableViewController<IASKViewController> *)settingsViewController cellForSpecifier:(IASKSpecifier*)specifier;

这两个方法都会为您的所有IASKCustomViewSpecifier条目调用。为了区分它们,您可以使用specifier.key访问Key属性。在第一个方法中,您返回单元格的高度,在第二个方法中,您返回单元格本身。您应像在常规表格视图编程中一样使用可重复使用的UITableViewCell对象。Demo应用中有一个示例。

可选您可实现:

- (void)settingsViewController:(IASKAppSettingsViewController*)settingsViewController

didSelectCustomViewSpecifier:(IASKSpecifier*)specifier;

来捕获自定义视图的点击事件。

如果您指定了FileIASKViewControllerClassIASKViewControllerStoryBoardIdIASKSegueIdentifier(见下文),则自定义视图的选择行为与子面板相同,并且在选择时不会调用代理。

节标题和页脚

系统设置中提供了组元素FooterText键。它在InAppSettingsKit中也被支持。此外,我们还支持多值元素的这个键。页脚文本显示在多值选项表下方。

通过添加KEY属性并在您的IASKSettingsDelegate中实现以下方法,可以为PSGroupSpecifier段定义自定义标题视图:

- (UIView *)settingsViewController:(id<IASKViewController>)settingsViewController tableView:(UITableView *)tableView viewForHeaderForSection:(NSInteger)section;

通过实现以下方法调整标题的高度:

- (CGFloat)settingsViewController:(id<IASKViewController>)settingsViewController tableView:(UITableView*)tableView heightForHeaderForSection:(NSInteger)section;

如果您旨在不使用自定义视图来简化标题的定制,且未实现-settingsViewController:tableView:viewForHeaderForSection:方法或该方法返回对应节的nil值,则可实现以下方法:

- (NSString *)settingsViewController:(id<IASKViewController>)settingsViewController tableView:(UITableView*)tableView titleForHeaderForSection:(NSInteger)section;

如果方法返回nil或一个长度为0的字符串,则使用在.plist中定义的标题。

该行为类似于自定义表格视图单元。在实现一个方法时,如果需要,可以方便地从其索引获取节键,如下所示:

NSString *key = [settingsViewController.settingsReader keyForSection:section];

查看示例应用程序以获取具体示例。

对于页脚定制,可以从IASKSettingsDelegate协议中实现三个类似的方法。

扩展子窗格

自定义视图控制器

对于子窗格元素(PSChildPaneSpecifier),Apple要求一个file键,该键指定子plist。InAppSettingsKit允许您选择性地指定IASKViewControllerClassIASKViewControllerSelector。在这种情况下,通过实例化指定类的UIViewController子类并使用在IASKViewControllerSelector中指定的初始化方法初始化它来显示子窗格。选择器必须有两个参数:一个用于设置包中文件名的NSString参数和IASKSpecifier。然后,自定义视图控制器被推送到导航堆栈上。请参阅示例应用程序以获取更多详细信息。

使用从Storyboard中自定义ViewController

或者指定 IASKViewControllerStoryBoardId主Storyboard 中启动ViewController。指定 IASKViewControllerStoryBoardFile 以使用应用的 Info.plist 中除主Storyboard之外的其他Storyboard。

执行跳转

作为 IASKViewControllerClassIASKViewControllerSelector 对于子面板元素(PSChildPaneSpecifier)的替代,InAppSettingsKit能够通过执行您Storyboard中定义的任何跳转来导航到另一个ViewController。为此,在 IASKSegueIdentifier 中指定跳转标识符。

扩展各种指定器

字幕

IASKSubtitle 键允许为以下元素定义字幕:切换、子面板、打开URL、邮件编辑、按钮。使用字幕意味着左对齐。如果指定了子面板的值,则子面板将显示为字幕,如果没有指定 IASKSubtitle。字幕可以是一个可本地化的字符串或一个根据当前值包含可本地化字幕的字典。YESNO 用作布尔切换值的键。字典可能包含一个 __default__ 键,用于在没有匹配键时定义字幕。

图标

所有元素类型(除非滑块已经具有 MinimumValueImage)都支持在单元左側添加图标圖像。您可以在可选的 IASKCellImage 属性中指定图像名称。“.png”或“@2x.png”后缀将自动追加,并将在项目中搜索。您还可以将后缀为“Highlighted.png”或“[email protected]”的图像添加到项目中,并且在选择单元时( Buttons 和 ChildPanes)它将自动用作高亮图像。

内容类型

为了支持基于内容类型的自动填充,请添加接受(前缀性的)常量名称的键 IASKTextContentType,例如:(a href="https://developer.apple.com/documentation/uikit/uitextcontenttype" rel="nofollow">UITextContentType)。示例:要配置具有 UITextContentTypeEmailAddress 的文本框,请使用 IASKTextContentType: EmailAddress

验证

可以使用代理回调验证文本字段

- (IASKValidationResult)settingsViewController:(IASKAppSettingsViewController*)settingsViewController validateSpecifier:(IASKSpecifier*)specifier textField:(IASKTextField*)textField previousValue:(nullable NSString*)previousValue replacement:(NSString* _Nonnull __autoreleasing *_Nullable)replacement;

回调接收的是 IASKTextField,它是 UITextField 的子类,允许在验证错误的情况下对文本字段进行样式设置(例如,红色文本)。它包含一个参数用于替换无效文本。返回 IASKValidationResultFailedWithShake 使得文本框震动以视觉上表示验证错误。

自定义切换

PSToggleSwitchSpecifier 开关默认使用 UISwitch。通过指定选项 IASKToggleStyle: Checkmark,将显示所选键的勾选标记。

动态多值列表

多值列表(PSMultiValueSpecifier)可以从委托那里动态获取其值和标题,而不是从静态的 Plist 获取。在你的 IASKSettingsDelegate 中实现这两个方法。

- (NSArray*)settingsViewController:(IASKAppSettingsViewController*)sender valuesForSpecifier:(IASKSpecifier*)specifier;
- (NSArray*)settingsViewController:(IASKAppSettingsViewController*)sender titlesForSpecifier:(IASKSpecifier*)specifier;

示例应用程序返回所有国家代码的列表作为值和本地化国家名称作为标题。

可以通过在 Plist 中添加一个布尔 DisplaySortedByTitle 键来按字母顺序排序多值列表。可以为多值列表条目分配一个图像。使用 IconNames 属性(位于值/标题/简称等旁边)指定图像。

设置存储

IASK默认将设置存储在[NSUserDefaults standardUserDefaults]中。但是,可以通过在IASKAppSettingsViewController上设置settingsStore属性来改变此行为。IASK提供了两个存储实现:IASKSettingsStoreUserDefaults(默认实现)和IASKSettingsStoreFile,后者在您选择的路径的文件中读取和写入设置。如果您需要更具体的内容,您也可以选择创建自己的存储。创建自己的存储的最简单方法是创建IASKAbstractSettingsStore的子类。只需覆盖3个方法。有关更多信息,请参阅IASKSettingsStore.{h,m}

通知

有一个IASKSettingChangedNotification通知,每当有设置键变更时都会发送它。通知的object是发送视图控制器,而userInfo字典包含受影响键的键和新的值。

动态单元格隐藏

有时候,选项之间相互依赖。例如,您可能想要有一个“自动连接”开关,当开启时允许用户设置用户名和密码。要针对特定设置的更改做出反应,请使用上文所述的 IASKSettingChangedNotification 通知。

要隐藏一组单元格,使用

- (void)[IASKAppSettingsViewController setHiddenKeys:(NSSet*)hiddenKeys animated:(BOOL)animated];

或者非动画版本

@property (nonatomic, strong) NSSet *hiddenKeys;

请参阅样本应用以了解更多细节。在 hiddenKeys 中包含 PSGroupSpecifier 键可以隐藏整个部分。

注册默认值

设置属性列表支持 DefaultValue 参数,在 NSUserDefaults 中没有存储值的情况下显示默认值。然而,当应用程序查询 NSUserDefaults 的值时,默认值不会被传播。这是有意义的,因为 NSUserDefaults 不知道设置属性列表。

为了为各种设置键初始化值,NSUserDefaults 提供了 registerDefaults: 方法,该方法接受一个字典,该字典包含了“回退”值,当没有存储值时,由 NSUserDefaults 返回。这通常在应用程序启动时调用。

然而,创建和维护该字典可能会变得繁琐,并且存在这种字典和设置默认值不一致的风险。

为了解决这个问题,IASKSettingsReader 提供了一个方法,通过遍历 Root.plist 和所有子 plists 来生成这个字典,并收集所有键的 DefaultValue

NSDictionary *defaultDict = [appSettingsViewController.settingsReader gatherDefaultsLimitedToEditableFields:YES];
[NSUserDefaults.standardUserDefaults registerDefaults:defaultDict];

icloud 同步

要将 NSUserDefaults 与 iCloud 同步,还有一个名为 FTiCloudSync 的项目,它作为一个分类在 NSUserDefaults 上实现:所有写和删除请求都会自动转发到 iCloud,所有来自 iCloud 的更新都会自动存储在 NSUserDefaults 中。如果使用基于标准 NSUserDefaults 的存储,InAppSettingsKit 会自动更新 UI。

支持

请不要用 Github issues 提交支持请求,我们将关闭它们。相反,请在 StackOverflow 上发布带有标签 inappsettingskit 的问题。

授权

我们将代码以自由的 BSD 许可证发布,以便将其包含在任何项目中,无论是免费还是付费应用。我们唯一的要求是给予原始开发者一些认可。包含认可的最简单方法是保留“由 InAppSettingsKit 驱动”的通知。如果您决定删除此通知,在 App Store 描述页或主页上做出明显的提及也是可以的。

作者

最初由我的朋友 Lucas Vandal 开发,我接管了开发并继续更新该框架。如果您想支持我的开源工作,请考虑作为 赞助商 加入我!💪️您的赞助使我能够有更多时间投入到 InAppSettingsKit 和其他社区项目中。谢谢!

Ortwin Gentz