CSD 设置
用于展示和编辑您 iOS 应用设置的简单直接基于 Swift 的框架
概述
通常您希望允许用户在应用和 iOS 设置应用中设置和编辑应用设置。通过设置包公开应用设置是正确的方式,因为它允许您的应用与 MDM(移动设备管理)系统兼容,这些系统使用户能够跨企业管理应用设置。同时,允许用户在应用中本身编辑应用设置也是一个不错的选择,但这通常需要大量的额外编码 - 不仅包括在应用中读取和修改设置,还包括在表视图中以不同于应用程序的方式展示并允许用户进行修改。这个框架解决了所有这些问题。它允许您在一个地方存储所有应用设置 - 在应用的设置包中。并且,只需实现一个协议属性和几行代码来实例化应用设置视图控制器,即可将设置以类似 iOS 设置应用的方式展示给用户,允许完全编辑每个设置项。
要求
- iOS 10.0+
- Xcode 10.2+
- Swift 5.0+
安装
CocoaPods
或者,您可以将它作为 Cocoapod 进行安装
CocoaPods 是一个 Cocoa 项目的依赖项管理器。您可以使用以下命令安装它
$ gem install cocoapods
构建 CRDSettings 需要至少 CocoaPods 1.7.0+
要使用 CocoaPods 将 CRDSettings 集成到您的 Xcode 项目中,请在您的 Podfile
中指定它
target 'MyApp' do
use_frameworks!
# Pods for MyApp
pod 'CRDSettings'
end
然后,运行以下命令
$ pod install
Carthage
您可以使用 Carthage 将此框架添加到您的项目中
-
将
Cartfile
添加到您的 xcodeproj 文件所在的目录。 -
编辑此文件,指定 1.0.6 版本或更高版本的此框架
github "cdisdero/CRDSettings" >= 1.0.6
-
运行 Carthage 以添加框架源文件并构建此框架
carthage update
-
在您的 Xcode 项目应用的 General 标签中,将针对您的目标类型构建的 Carthage 框架拖放到底部 Linked Frameworks and Libraries 列表。您可以在项目文件夹中的 Carthage/Build/[target]/CRDSettings.framework 子目录找到构建的框架,其中 [target] 类似于 'iOS' 等。
-
为了确保框架正确去除了用于发布应用程序的废物 CPU 类型,请将以下 Run Script 构建阶段添加到您的应用程序目标中
/usr/local/bin/carthage copy-frameworks
这假设 Carthage 已安装在系统中的
/usr/local/bin
。同一 Run Script 构建阶段中也要指定以下输入文件$(SRCROOT)/Carthage/Build/iOS/CRDSettings.framework
使用
此框架非常易于使用。只需三步即可将其加入到您的应用中
- 在您的应用程序的 storyboard 中,在想要显示应用程序设置的视图控制器中添加一个 UI 元素。例如,您可能在主视图控制器中有一个按钮,希望从中显示设置。在视图控制器代码中添加一个
IBAction
,该动作响应于 UI 元素以获取 CRDSettings 插件并将其实例化为 CRDSettings 视图控制器,以显示应用程序设置
@IBAction func onSettings(_ sender: UIBarButtonItem) {
// Get the bundle corresponding to the CRDSettings framework.
let storyboardBundle = Bundle(for: CRDSettings.self)
// Get the storyboard from the framework labelled 'CRDSettings'.
let storyboard = UIStoryboard(name: "CRDSettings", bundle: storyboardBundle)
// Try to instantiate the settings view controller from the framework and present it as a slide-up form sheet.
guard let settingsController = storyboard.instantiateInitialViewController() else { return }
settingsController.modalTransitionStyle = .coverVertical
settingsController.modalPresentationStyle = .formSheet
present(settingsController, animated: true) {
// Do nothing here.
}
}
-
在您的 AppDelegate 类中实现
CRDSettingsAppProtocol
的一个属性。导入 CRDSettings 框架,并添加该属性import CRDSettings ... @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate, CRDSettingsAppProtocol { // MARK: - CRDSettingsAppProtocol var settings: CRDSettings? ...
-
最后,创建一个CRDSettings类的实例,并将其分配给您刚刚实现的settings属性。修改您的
application:didFinishLaunchingWithOptions
方法。... func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { // Create a new SRSettings instance for the app. settings = CRDSettings() ...
在此示例中,我们从框架创建一个CRDSettings类的新实例,并将其分配给之前定义的settings属性。有关更多信息,请参阅包含在框架Xcode项目代码中的示例CRDSettingsTestApp项目目标中是如何实现这点的。
自定义
在创建此CRDSettings类的实例之后,您可以进一步自定义设置。
您可能想做的另一件事是许多应用程序中的常见需求,就是添加一个放在开关后面的按钮,并根据开关状态来决定按钮的存在或启用状态。例如
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Create a new SRSettings instance for the app.
settings = CRDSettings()
if let settings = settings {
// Put a button in the "MyGroup" group after the "myswitch1_preference" switch.
if let groups = settings.groups, groups.count > 0 {
if let supportGroup = settings.findGroup(title: "MyGroup1") {
// Create a new button called 'My Button' and set an action for it.
let entry = CRDSettingsActionButton(identifier: "mybutton1_preference", title: "My Button", action: { (settingEntry) in
// Show an alert that the button was pressed.
let alertController = UIAlertController(title: "My Button", message:
"My Button was pressed.", preferredStyle: UIAlertControllerStyle.alert)
alertController.addAction(UIAlertAction(title: "OK", style: UIAlertActionStyle.default,handler: nil))
self.window?.rootViewController?.presentedViewController?.present(alertController, animated: true, completion: nil)
})
// Set this button to depend on the switch setting so that when it is off, this button is disabled.
entry.dependsOn = "myswitch1_preference"
entry.disableOnDepends = true
// Add the button to the group.
supportGroup.add(entry, afterIdentifier: "myswitch1_preference")
}
}
}
...
return true
}
在此示例中,我们使用CRDSettings实例上的findGroup
方法来找到标题为MyGroup1
的设置组。
然后,我们使用CRDSettingsActionButton的初始化器创建一个名为My Button
的新动作按钮,其标识符为mybutton1_preference
,并具有一个动作代码块,当按下按钮时将显示一个警告框。
然后,我们使用我们创建的设置按钮的dependsOn
属性来设置对另一个设置的应用依赖,其标识符为myswitch1_preference
,这是我们希望用来启用/禁用此按钮的开关。按钮设置上的disableOnDepends
属性设置为true,因此当开关关闭时,我们创建的按钮将显示为禁用,而不是从设置列表中消失。
最后,我们在开关后面将按钮添加到我们找到的组中supportGroup
。
通知
每当设置值改变时,无论是应用程序内部还是iOS设置应用中,您都希望得到通知,告知已发生更改以及设置当前值。这可以通过添加对通知名称CRDSettings.NotificationSettingsChanged
的观察者来实现。例如
/// The list of notification observers.
private var observers: [NSObjectProtocol] = []
...
// Setup an observer for the *CRDSettings.NotificationSettingsChanged* notification so that whenever setting values change, we are notified and handed the current value.
observers.append(NotificationCenter.default.addObserver(forName: CRDSettings.NotificationSettingsChanged, object: nil, queue: OperationQueue.main) { (notification) in
// Get the *CRDSettingsEntry* out of the notification by looking for the value with the key *CRDSettings.NotificationSettingsChangedSettingKey*
guard let userInfo = notification.userInfo, let settingsEntry = userInfo[CRDSettings.NotificationSettingsChangedSettingKey] as? CRDSettingsEntry else { return }
// Print out the changed settings entry to the console.
print("Changed: \(settingsEntry)")
})
在上面的示例中,添加了一个对通知名称CRDSettings.NotificationSettingsChanged
的观察者,并在该观察者触发时,我们尝试使用键名CRDSettings.NotificationSettingsChangedSettingKey
获取相应于更改的设置值的CRDSettingsEntry,并将其设置值打印到控制台。
您可能会使用这些通知来监控某些设置值,并在收到CRDSettings.NotificationSettingsChanged
通知时更改应用程序行为和/或更新视图控制器中的视图控件。
如果您的应用程序处于后台,并且iOS设置应用中更改了您的应用程序设置,当您激活应用程序时,此通知将触发,然后您可以更新UI元素和处理应用程序中的行为变化。
引用
CRDSettings
概述
此类表示读取并与应用设置捆绑包同步的app设置集合。
通知
-
CRDSettings.NotificationSettingsChanged
每次设置值更改时发布的通知的名称。
-
CRDSettings.NotificationSettingsChangedSettingKey
包含通知
CRDSettings.NotificationSettingsChanged
中更改的设置值的CRDSettingsEntry
对象的键的名称
初始化器
-
CRDSettings(_ settingsBundleName: String? = nil)
使用给定的设置捆绑包名称创建一个新的CRDSettings对象,默认为"Settings",如果指定为nil。
公共属性
-
groups: [CRDSettingsGroup]? { get }
返回设置中的组集合(如果有)。
公共方法
-
findGroup(title: String) -> CRDSettingsGroup?
返回一个代表找到的第一个匹配指定组标题的CRDSettingsGroup对象的CRDSettingsGroup对象,如果没有找到则返回nil。
-
findSetting(identifier: String) -> CRDSettingsEntry?
返回一个代表在所有组中匹配指定标识符的第一个CRDSettingsEntry对象的CRDSettingsEntry对象,如果没有找到则返回nil。
CRDSettingsGroup
概述
该类代表设置包中的一种PSGroupSpecifier类型的条目。
公共属性
-
title: String { get }
组的标题。
-
entries: [CRDSettingsEntry]? { get }
该组中包含的CRDSettingsEntry对象集合(如有)。
公共方法
add(_ entry: CRDSettingsEntry, afterIdentifier: String? = default)
将指定的CRDSettingsEntry添加到该组中,如果指定并且找到,则添加到具有指定标识符的条目之后,否则添加到组末尾。
insert(_ entry: CRDSettingsEntry, atIndex: Int)
在指定索引将指定的CRDSettingsEntry插入到该组中。
find(_ identifier: String) -> CRDSettingsEntry?
返回第一个匹配指定标识符的CRDSettingsEntry,如果没有找到则返回nil。
CRDSettingsToggleSwitch
概述
此类表示应用设置包中PSToggleSwitchSpecifier类型设置的条目。
公共属性
-
identifier: String { get }
设置条目的标识符。
-
title: String { get }
设置条目的标题。
-
currentValue: Any? { get set }
设置条目的当前值,如果有。对于开关,它是一个布尔值,要么是 true,要么是 false,取决于开关状态。
-
dependsOn: String? { get set }
此条目所依赖的另一个CRDSettingsEntry的标识符。如果该条目的当前值更改为 false,根据此设置条目属性
disableOnDepends
的值,此条目将被禁用或隐藏。 -
disableOnDepends: Bool { get set }
标志,用于控制当依赖(见
dependsOn
)的条目为 false 时,此设置条目是禁用(true)还是隐藏(false)。 -
enabled: Bool { get set }
标志,表示此设置条目是否启用以供用户交互。
CRDSettingsSlider
概述
此类表示应用设置包中PSSliderSpecifier类型条目。
公共属性
-
identifier: String { get }
设置条目的标识符。
-
currentValue: Any? { get set }
预设条目的当前值,如果有。在滑块的情况下,它是一个
Float
。 -
dependsOn: String? { get set }
此条目所依赖的另一个CRDSettingsEntry的标识符。如果该条目的当前值更改为 false,根据此设置条目属性
disableOnDepends
的值,此条目将被禁用或隐藏。 -
disableOnDepends: Bool { get set }
标志,用于控制当依赖(见
dependsOn
)的条目为 false 时,此设置条目是禁用(true)还是隐藏(false)。 -
enabled: Bool { get set }
标志,表示此设置条目是否启用以供用户交互。
-
minValue: Float? { get }
本条目设置的最小值,如果有。
-
minValueImage: String? { get }
用于滑块上的最小值的设置包中存储的图像的文件名(不带扩展名),如果有。
-
maxValue: Float? { get }
本条目设置的最大值,如果有。
-
maxValueImage: String? { get }
用于滑块上的最大值的设置包中存储的图像的文件名(不带扩展名),如果有。
-
incrementValue: Float? { get set }
本条目设置的增加值,如果有。
CRDSettingsMultiValue
概述
此类表示应用设置包中的 PSMultiValueSpecifier 类型条目。
公共属性
-
identifier: String { get }
设置条目的标识符。
-
title: String { get }
设置条目的标题。
-
currentValue: Any? { get set }
如果有,则设置条目的当前值。对于多值条目,它取决于
values
数组属性的类型的String
或NSNumber
。 -
dependsOn: String? { get set }
此条目所依赖的另一个CRDSettingsEntry的标识符。如果该条目的当前值更改为 false,根据此设置条目属性
disableOnDepends
的值,此条目将被禁用或隐藏。 -
disableOnDepends: Bool { get set }
标志,用于控制当依赖(见
dependsOn
)的条目为 false 时,此设置条目是禁用(true)还是隐藏(false)。 -
enabled: Bool { get set }
标志,表示此设置条目是否启用以供用户交互。
-
titles: [String]? { get }
设置条目的标题列表。
-
selectedTitle: String? { get }
从
titles
数组中当前选中的标题。 -
values: [Any]? { get }
关联于
titles
的设置条目的值列表。
CRDSettingsTextField
概览
此类表示应用设置包中的PSTextFieldSpecifier类型条目。
公共属性
-
identifier: String { get }
设置条目的标识符。
-
title: String { get }
设置条目的标题。
-
currentValue: Any? { get set }
设置条目的当前值(如有)。对于文本字段,它是一个表示当前输入文本的:
String
。 -
dependsOn: String? { get set }
此条目所依赖的另一个CRDSettingsEntry的标识符。如果该条目的当前值更改为 false,根据此设置条目属性
disableOnDepends
的值,此条目将被禁用或隐藏。 -
disableOnDepends: Bool { get set }
标志,用于控制当依赖(见
dependsOn
)的条目为 false 时,此设置条目是禁用(true)还是隐藏(false)。 -
enabled: Bool { get set }
标志,表示此设置条目是否启用以供用户交互。
-
isSecure: Bool { get }
一个标志,指示字段是否安全(如密码)。
-
keyboardType: CRDSettingsTextFieldKeyboardType { get }
在编辑此字段时显示的软键盘类型。这可以是以下枚举值之一:
Alphabet
、NumbersAndPunctuation
、NumberPad
、URL
或EmailAddress
。这些枚举值与UIKeyboardType中的枚举值具有相同的含义。 -
autoCapitalizationType: CRDSettingsTextFieldAutoCapitalizationType { get }
该字段的自动首字母大写类型。这可以是以下枚举值之一:
None
、Words
、Sentences
或AllCharacters
。这些枚举值与UITextAutocapitalizationType中的枚举值具有相同的含义。 -
autoCorrectionType: CRDSettingsTextFieldAutoCorrectionType { get }
该字段的自动更正类型。这可以是以下枚举值之一:
Default
、No
或Yes
。这些枚举值与UITextAutocorrectionType中的枚举值具有相同的含义。
CRDSettingsTitle
概览
此类表示应用设置包中的PSTitleValueSpecifier类型条目。
公共属性
-
identifier: String { get }
设置条目的标识符。
-
title: String { get }
设置条目的标题。
-
currentValue: Any? { get set }
设置条目的当前值,如果有的话。在标题条目的情况下,它是一个表示当前标题的
String
(相当于title
)。 -
dependsOn: String? { get set }
此条目所依赖的另一个CRDSettingsEntry的标识符。如果该条目的当前值更改为 false,根据此设置条目属性
disableOnDepends
的值,此条目将被禁用或隐藏。 -
disableOnDepends: Bool { get set }
标志,用于控制当依赖(见
dependsOn
)的条目为 false 时,此设置条目是禁用(true)还是隐藏(false)。 -
enabled: Bool { get set }
标志,表示此设置条目是否启用以供用户交互。
CRDSettingsActionButton
概览
此类表示应用设置包中类型为 button
的设置条目。注意:此设置条目在设置包根.plist文件中不受原生支持。
初始化器
-
使用指定标识符、标题和可选操作创建一个新的 CRDSettingsActionButton 对象,抛出异常。
瞬视为 CRDSettingsActionButton 对象,带有给定的标识符、标题和可选操作。CRDSettingsAction 是类型
(_ settingEntry: CRDSettingsEntry?) -> Void
函数的别名。因此,当按钮被按下执行动作代码时,将传递按钮的 CRDSettingsActionButton 设置条目实例到动作代码块。
公有属性
-
identifier: String { get }
设置条目的标识符。
-
title: String { get }
显示在按钮标题中的设置条目标题。
-
dependsOn: String? { get set }
此条目所依赖的另一个CRDSettingsEntry的标识符。如果该条目的当前值更改为 false,根据此设置条目属性
disableOnDepends
的值,此条目将被禁用或隐藏。 -
disableOnDepends: Bool { get set }
标志,用于控制当依赖(见
dependsOn
)的条目为 false 时,此设置条目是禁用(true)还是隐藏(false)。 -
enabled: Bool { get set }
标志,表示此设置条目是否启用以供用户交互。
-
action: CRDSettingsAction? { get }
按此设置条目时执行 CRDSettingsAction 代码块,如果有的话。
结论
希望这个框架对您的下一个 Swift 项目有所帮助。我会随着时间的推移和兴趣更新内容,当然我欢迎所有您的反馈。
已知的故障
-
框架不支持CRDSettingsToggleSwitch类中的PSToggleSwitchSpecifier设置条目的TrueValue和FalseValue。这是因为截至2016年5月30日,针对它有一个开放的radar(错误)报告。只要这个问题得到解决,我将尝试添加对其的支持。
-
当前框架不支持设置条目的PSChildPaneSpecifier类型。
-
当前框架不支持设置条目的PSRadioGroupSpecifier类型。
-
schema中许多设置条目的SupportedUserInterfaceIdioms键当前不被框架支持。
-
框架不支持PSGroupSpecifier键FooterText。
-
以下键为PSMultiValueSpecifier,当前不被框架支持:ShortTitles和DisplaySortedByTitle。
-
用于PSSliderSpecifier的MinimumValueImage和MaximumValueImage的图片文件必须直接添加到项目中Settings.bundle文件夹内,以确保这些图片能在iOS设置应用和CRDSettings表格视图中显示。遗憾的是,如果它们位于项目的Assets.xcassets中,则这些图片在iOS设置应用中不会显示。我认为这可能是此控件类型背后的Apple框架以及iOS设置应用的限制。
许可
CRDSettings遵循Apache 2.0许可证发布。有关详细信息,请参阅LICENSE文件。