{"id":3042,"url":"https://github.com/futuretap/InAppSettingsKit","last_synced_at":"2025-08-03T13:31:36.575Z","repository":{"id":713991,"uuid":"468596","full_name":"futuretap/InAppSettingsKit","owner":"futuretap","description":"This iOS framework allows settings to be in-app in addition to or instead of being in the Settings app.","archived":false,"fork":false,"pushed_at":"2025-07-25T19:28:54.000Z","size":4332,"stargazers_count":3212,"open_issues_count":10,"forks_count":541,"subscribers_count":104,"default_branch":"master","last_synced_at":"2025-07-26T01:56:16.720Z","etag":null,"topics":["ios","ipad","iphone","settings-editor","uikit","uikit-components"],"latest_commit_sha":null,"homepage":"https://www.futuretap.com/blog/inappsettingskit-3-0","language":"Objective-C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/futuretap.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":"futuretap"}},"created_at":"2010-01-12T09:37:53.000Z","updated_at":"2025-07-25T19:28:29.000Z","dependencies_parsed_at":"2023-11-28T11:26:57.226Z","dependency_job_id":"84fe5bcf-32eb-4c37-90f2-e290acd180be","html_url":"https://github.com/futuretap/InAppSettingsKit","commit_stats":{"total_commits":734,"total_committers":88,"mean_commits":8.340909090909092,"dds":0.720708446866485,"last_synced_commit":"5b6a33cd5d227d71f79bf8e43be2049d981c6aad"},"previous_names":[],"tags_count":78,"template":false,"template_full_name":null,"purl":"pkg:github/futuretap/InAppSettingsKit","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/futuretap%2FInAppSettingsKit","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/futuretap%2FInAppSettingsKit/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/futuretap%2FInAppSettingsKit/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/futuretap%2FInAppSettingsKit/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/futuretap","download_url":"https://codeload.github.com/futuretap/InAppSettingsKit/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/futuretap%2FInAppSettingsKit/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":267150480,"owners_count":24043473,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","status":"online","status_checked_at":"2025-07-26T02:00:08.937Z","response_time":62,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ios","ipad","iphone","settings-editor","uikit","uikit-components"],"created_at":"2024-01-05T20:16:29.744Z","updated_at":"2025-08-03T13:31:36.070Z","avatar_url":"https://github.com/futuretap.png","language":"Objective-C","readme":"# InAppSettingsKit\n\n[![Build Status](https://travis-ci.org/futuretap/InAppSettingsKit.svg?branch=master)](https://travis-ci.org/futuretap/InAppSettingsKit)\n[![Version](https://img.shields.io/cocoapods/v/InAppSettingsKit.svg?style=flat)](http://cocoapods.org/pods/InAppSettingsKit)\n[![Swift Package Manager compatible](https://img.shields.io/badge/SPM-compatible-brightgreen.svg)](https://swiftpackageindex.com/futuretap/InAppSettingsKit)\n[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/Carthage/Carthage)\n[![License](https://img.shields.io/cocoapods/l/InAppSettingsKit.svg?style=flat)](https://github.com/futuretap/InAppSettingsKit/blob/master/LICENSE)\n![Platform](https://img.shields.io/endpoint?url=https%3A%2F%2Fswiftpackageindex.com%2Fapi%2Fpackages%2Ffuturetap%2FInAppSettingsKit%2Fbadge%3Ftype%3Dplatforms)\n[![Sponsor](https://img.shields.io/badge/Sponsor-ff40a0)](https://github.com/sponsors/futuretap)\n[![Mastodon](https://img.shields.io/mastodon/follow/000010558?domain=https%3A%2F%2Fmastodon.cloud)](https://mastodon.cloud/@ortwingentz)\n\nInAppSettingsKit (IASK) is an open source framework to easily add in-app settings to your iOS, Catalyst, or visionOS apps. Normally iOS apps use the `Settings.bundle` resource to add app-specific settings in the Settings app. InAppSettingsKit takes advantage of the same bundle and allows you to present the same settings screen within your app. So the user has the choice where to change the settings.\n\nIASK not only replicates the feature set of system settings but supports a large number of additional elements and configuration options.\n\n**Updating from IASK 2.x?** Please read the [Release Notes](RELEASE_NOTES.md).\n\n![](IASK.gif)\n\n- [How does it work?](#how-does-it-work)\n- [How to include it?](#how-to-include-it)\n- [Sample application](#sample-application)\n- [App Integration](#app-integration)\n- [Goodies](#goodies)\n\t- [Custom inApp plists](#custom-inapp-plists)\n\t- [Privacy link](#privacy-link)\n\t- [Open URL](#open-url)\n    - [Web View Controller](#web-view-controller)\n\t- [Mail Composer](#mail-composer)\n\t- [Button](#button)\n\t- [Multiline Text View](#multiline-text-view)\n\t- [Date Picker](#date-picker)\n\t- [List Groups](#list-groups)\n\t- [Custom Views](#custom-views)\n\t- [Section Headers and Footers](#section-headers-and-footers)\n\t- [Extending Child Panes](#extending-child-panes)\n\t- [Extending various specifiers](#extending-various-specifiers)\n\t- [Extending Text Fields](#extending-text-fields)\n\t- [Customizing Toggles](#customizing-toggles)\n\t- [Dynamic MultiValue Lists](#dynamic-multivalue-lists)\n\t- [Settings Storage](#settings-storage)\n\t- [Notifications](#notifications)\n\t- [Dynamic cell hiding](#dynamic-cell-hiding)\n\t- [Register default values](#register-default-values)\n- [iCloud sync](#icloud-sync)\n- [Support](#support)\n- [License](#license)\n- [Author](#author)\n\n\n# How does it work?\n\nTo support traditional Settings.app panes, the app must include a `Settings.bundle` with at least a `Root.plist` to specify the connection of settings UI elements with `NSUserDefaults` keys. InAppSettingsKit basically just uses the same Settings.bundle to do its work. This means there's no additional work when you want to include a new settings parameter. It just has to be added to the Settings.bundle and it will appear both in-app and in Settings.app. All settings types like text fields, sliders, toggle elements, child views etc. are supported.\n\n\n# How to include it?\n\nThe source code is available on [github](http://github.com/futuretap/InAppSettingsKit). There are several ways of installing it:\n\n**Using SPM**\n\nTo install InAppSettingsKit using [Swift Package Manager](https://github.com/apple/swift-package-manager) you can follow the [tutorial published by Apple](https://developer.apple.com/documentation/xcode/adding_package_dependencies_to_your_app) using the URL for the InAppSettingsKit repo with the current version:\n\n1. In Xcode, select “File” → “Add Packages…”\n1. Enter `https://github.com/futuretap/InAppSettingsKit.git`\n\n\n**Using CocoaPods**\n\nAdd to your `Podfile`:\n\n    pod 'InAppSettingsKit'\n\nThen run `pod install`.\n\n**Using Carthage**\n\nAdd to your `Cartfile`:\n\n    github \"futuretap/InAppSettingsKit\" \"master\"\n\n\n# Sample application\n\nInAppSettingsKit contains an Xcode sample application, that demonstrates all of it's extensive features. Both for a push and modal view controller.  \nTo run the sample application:\n\n1. From the project root folder, open `InAppSettingsKit.xcworkspace` in Xcode.\n2. Change the scheme to `Sample App` (Product \u003e Scheme \u003e Sample App).\n3. Select a destination, like an iPhone Simulator.\n4. To build and run the application, choose Product \u003e Run, or click the Run button in the Xcode toolbar.\n\n\n# App Integration\n\nIn order to start using IASK add `Settings.bundle` to your project (`File` -\u003e `Add File` -\u003e `Settings bundle`) and edit `Root.plist` with your settings (see Apple's documentation on the [Schema File Root Content](https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/UserDefaults/Preferences/Preferences.html)). Read on to get insight into more advanced uses.\n\nTo display InAppSettingsKit, instantiate `IASKAppSettingsViewController` and push it onto the navigation stack or embed it as the root view controller of a navigation controller.\n\n**In code, using Swift:**\n\n```swift\nlet appSettingsViewController = IASKAppSettingsViewController()\nnavigationController.pushViewController(appSettingsViewController, animated: true)\n```\n\n**In code, using Swift as part of a swift package:**\n\nIn a modularized app, you might want to move all settings-related code into a separate package, and only reference the InAppSettingsKit dependency there. Your `Package.swift` would look like this:\n\n```swift\nlet package = Package(\n    name: \"SettingsPackage\",\n    platforms: [.iOS(.v17)],\n    dependencies: [\n        .package(url: \"https://github.com/futuretap/inappsettingskit\", from: \"3.4.0\")\n    ],\n    .target(\n        name: \"SettingsPackage\",\n        dependencies: [\n            .product(name: \"InAppSettingsKit\", package: \"inappsettingskit\"),\n        ],\n        resources: [\n            .copy(\"InAppSettings.bundle\")\n        ]\n    )\n)\n```\n\n(Note that the `InAppSettings.bundle` directory is also part of the package, and does not belong to the main app anymore.)\n\nCreating an `IASKAppSettingsViewController` now requires setting its `bundle` property to the package's bundle:\n\n```swift\nstruct InAppSettingsView: UIViewControllerRepresentable {\n    func makeUIViewController(context: Context) -\u003e some UIViewController {\n        let iask = IASKAppSettingsViewController(style: .insetGrouped)\n        iask.bundle = Bundle.module // IMPORTANT\n        return iask\n    }\n\n    func updateUIViewController(_ uiViewController: UIViewControllerType, context: Context) { }\n}\n\n```\n\n**In code, using Objective-C:**\n\n```objc\nIASKAppSettingsViewController *appSettingsViewController = [[IASKAppSettingsViewController alloc] init];\n[self.navigationController pushViewController:appSettingsViewController animated:YES];\n```\n\n**Via storyboard:**\n\n- Drag and drop a Table View Controller embedded into a Navigation Controller into your app and wire the storyboard to your app UI\n- Set the Table View Controller class to `IASKAppSettingsViewController`\n- Set the Table View to \"Grouped\" style.\n- If you’re presenting the navigation controller modally: \n\t- In the Table View Controller set \"Show Done Button\" under \"App Settings View Controller\" to \"On\"\n\t- Set the delegate comforming to `IASKAppSettingsViewControllerDelegate`.\n\t- Implement the delegate method `-settingsViewControllerDidEnd:` and dismiss the view controller.\n\nThe [sample application](#sample-application) shows how to wire everything up.\n\n**Additional changes**\n\nTo customize the behavior, implement `IASKSettingsDelegate` and set the `delegate` property of `IASKAppSettingsViewController`. For advanced customization needs, subclassing of IASKAppSettingsViewController is supported.\n\nDepending on your project it might be needed to make some changes in the startup code of your app. Your app has to be able to reconfigure itself at runtime if the settings are changed by the user. This could be done in a `-reconfigure` method that is being called from `-applicationDidFinishLaunching` as well as in the delegate method `-settingsViewControllerDidEnd:` of `IASKAppSettingsViewController`.\n\n\n# Goodies\nThe intention of InAppSettingsKit was to create a 100% imitation of the Settings.app behavior (see the [Apple Settings Application Schema Reference](https://developer.apple.com/library/archive/documentation/PreferenceSettings/Conceptual/SettingsApplicationSchemaReference/Introduction/Introduction.html#//apple_ref/doc/uid/TP40007071)). On top of that, we added a ton of bonus features that make IASK much more flexible and dynamic.\n\n\n## Custom inApp plists\nSettings plists can be device-dependent: `Root~ipad.plist` will be used on iPad and `Root~iphone.plist` on iPhone. If not existent, `Root.plist` will be used.\n\nInAppSettingsKit adds the possibility to override those standard files by using `.inApp.plist` instead of `.plist`. Alternatively, you can create a totally separate bundle named `InAppSettings.bundle` instead of the usual `Settings.bundle`. The latter approach is useful if you want to suppress the settings in Settings.app.\n\nThis is the complete search order for the plists:\n\n- InAppSettings.bundle/FILE~DEVICE.inApp.plist\n- InAppSettings.bundle/FILE.inApp.plist\n- InAppSettings.bundle/FILE~DEVICE.plist\n- InAppSettings.bundle/FILE.plist\n- Settings.bundle/FILE~DEVICE.inApp.plist\n- Settings.bundle/FILE.inApp.plist\n- Settings.bundle/FILE~DEVICE.plist\n- Settings.bundle/FILE.plist\n\n\n## Privacy link\nIf the app includes a usage key for various privacy features such as camera or location access in its `Info.plist`, IASK displays a \"Privacy\" cell at the top of the root settings page. This cell opens the system Settings app and displays the settings pane for the app where the user can specify the privacy settings for the app.\n\nIf you don't want to show Privacy cells, set the property `neverShowPrivacySettings` to `YES`.\n\nThe [sample application](#sample-application) defines `NSMicrophoneUsageDescription` to let the cell appear. Note that the settings page doesn't show any privacy settings yet because the app doesn't actually access the microphone. Privacy settings only show up in the Settings app after first use of the privacy-protected API.\n\n\n## Color schemes\nYou can specify `tintColor` by setting it on the view of your IASKAppSettingsViewController instance. The tint color is used for buttons and centered text (see below for both). Optionally, you can specify `settingsViewController.colorScheme = IASKColorSchemeTinted` to use tintColor for all user-editable options such as multi value elements.\n\n## Open URL\nInAppSettingsKit adds a new element `IASKOpenURLSpecifier` that allows to open a specified URL using an external application (i.e. Safari or Mail). The URL to launch is specified in the `File` parameter. See the sample `Root.inApp.plist` for details.\n\n\n## Web View Controller\nTo open a specified URL inside your application, `IASKAppSettingsWebViewController` displays a fullscreen View Controller with an embedded [`WKWebView`](https://developer.apple.com/documentation/webkit/wkwebview).  \nBy default it shows an indeterminate activity indicator on the right side of the navigation bar when a page is loading.\n\nThe Web View Controller can be defined in the Settings plist by using the following mandatory properties:\n\n- `Type`: set to `PSChildPaneSpecifier`\n- `IASKViewControllerClass`: set to `IASKAppSettingsWebViewController`\n- `IASKViewControllerSelector`: set to `initWithFile:specifier:`\n- `Title`: the localized title of the row\n- `File`: corresponds to the URL you want to load (e.g. \"https://www.futuretap.com\")\n\nUse the following optional properties to customize the Web View Controller:\n\n- `IASKWebViewShowProgress`: set to `YES` to replace the default activity indicator on the navigation bar by a progress bar just below the navigation bar, which dynamically updates according to the [`estimatedProgress`](https://developer.apple.com/documentation/webkit/wkwebview/1415007-estimatedprogress) property of [`WKWebView`](https://developer.apple.com/documentation/webkit/wkwebview).   \nThe progress bar will be removed when page loading completes.\n- `IASKWebViewShowNavigationalButtons`: set to `YES` to show navigational buttons on the right side of the navigation bar. Their enabled state will update dynamically based on the navigation history of the [`WKWebView`](https://developer.apple.com/documentation/webkit/wkwebview).\n- `IASKWebViewHideBottomBar`: set to `YES` to hide the tab bar at the bottom of the screen when the `IASKAppSettingsWebViewController` is pushed on to a navigation controller. This will present the [`WKWebView`](https://developer.apple.com/documentation/webkit/wkwebview) full screen and prevents situations where the user can navigate the tab bar while the `IASKAppSettingsWebViewController` stays still present.  \nThis setting is ignored when `IASKAppSettingsWebViewController` is presented modally.\n\nFor more details, open the [Sample application](#sample-application) and take a look at all rows that start with **WebView**.\n\nAlthough `IASKAppSettingsWebViewController` might look similar to [`SFSafariViewController`](https://developer.apple.com/documentation/safariservices/sfsafariviewcontroller), the big difference is that `IASKAppSettingsWebViewController` does not reveal the URL to the user, nor can it be opened in an external browser (i.e. Safari or Chrome).  \nIn other words, it keeps your source private.\n\n\n## Mail Composer\nThe custom `IASKMailComposeSpecifier` element allows to send mail from within the app by opening a mail compose view. You can set the following (optional) parameters using the settings plist: `IASKMailComposeToRecipents`, `IASKMailComposeCcRecipents`, `IASKMailComposeBccRecipents`, `IASKMailComposeSubject`, `IASKMailComposeBody`, `IASKMailComposeBodyIsHTML`. Optionally, you can implement\n\n    - (BOOL)settingsViewController:(id\u003cIASKViewController\u003e)settingsViewController shouldPresentMailComposeViewController:(MFMailComposeViewController*)mailComposeViewController forSpecifier:(IASKSpecifier*)specifier;\n\nin your delegate to customize the mail (e.g. pre-fill the body with dynamic content, add attachments) modify the appearance of the compose view controller or even block the standard presentation. An alert is displayed if Email is not configured on the device. `IASKSpecifier` is the internal model object defining a single settings cell. Important IASKSpecifier properties:\n\n- `key`: corresponds to the `Key` in the Settings plist\n- `title`: the localized title of settings key\n- `type`: corresponds to the `Type` in the Settings plist\n- `defaultValue`: corresponds to the `DefaultValue` in the Settings plist\n\n\n## Button\nInAppSettingsKit adds a `IASKButtonSpecifier` element that allows to call a custom action. Just add the following delegate method:\n\n    - (void)settingsViewController:(IASKAppSettingsViewController*)sender buttonTappedForSpecifier:(IASKSpecifier*)specifier;\n\nThe sender is always an instance of `IASKAppSettingsViewController`, a `UIViewController` subclass. So you can access its view property (might be handy to display an action sheet) or push another view controller. Another nifty feature is that the title of IASK buttons can be overriden by the (localizable) value from `NSUserDefaults` (or any other settings store - see below). This comes in handy for toggle buttons (e.g. Login/Logout). See the [sample application](#sample-application) for details.\n\nBy default, Buttons are aligned centered except if an image is specified (default: left-aligned). The default alignment may be overridden.\n\n\n## Multiline Text View\nSimilar to standard text fields, `IASKTextViewSpecifier` displays a full-width, multi line text view that resizes according to the entered text. It also supports `KeyboardType`, `AutocapitalizationType` and `AutocorrectionType`.\n\n\n## Date Picker\n`IASKDatePickerSpecifier` displays a `UIDatePicker` to set a date and/or time. It supports the following options:\n\n - `DatePickerMode`: one of `Date`, `Time`, or `DateAndTime` (see [UIDatePickerMode](https://developer.apple.com/documentation/uikit/uidatepickermode)). Default is `DateAndTime`.\n - `DatePickerStyle`: one of `Compact`, `Wheels`, or `Inline` (see [UIDatePickerStyle](https://developer.apple.com/documentation/uikit/uidatepickerstyle)). Default is `Wheels`. Feature requires iOS 14 or higher. If the OS doesn't support it, IASK falls back to `Wheels`.\n - `MinuteInterval`: The interval at which the date picker displays minutes. Default: 1.\n\nThere are 3 optional delegate methods to customize how to store and display dates and times:\n\n    - (NSDate*)settingsViewController:(IASKAppSettingsViewController*)sender dateForSpecifier:(IASKSpecifier*)specifier;\n\nImplement this if you store the date/time in a custom format other than as `NSDate` object. Called when the user starts editing a date/time by selecting the title cell above the date/time picker.\n\n    - (NSString*)settingsViewController:(IASKAppSettingsViewController*)sender datePickerTitleForSpecifier:(IASKSpecifier*)specifier;\n\nImplement this to customize the displayed value in the title cell above the date/time picker.\n\n    - (void)settingsViewController:(IASKAppSettingsViewController*)sender setDate:(NSDate*)date forSpecifier:(IASKSpecifier*)specifier;\n\nImplement this if you store the date/time in a custom format other than an `NSDate` object. Called when the user changes the date/time value using the picker.\n\n\n## List Groups\nList groups (`IASKListGroupSpecifier`) are an IASK-only feature that allow you to manage a variable number of items, including adding and deleting items. Arrays of tags, accounts, names are typical use cases. A list group consists of a variable number of `ItemSpecifier` items. The number of these items is determined by your actual content in your NSUserDefaults (or your custom settings store). In other words, `ItemSpecifier` defines the type of cell, whereas the number of cells and their content comes from NSUserDefaults or your store. Cells can be deleted via swipe if the `Deletable` parameter is set to YES.\n\nOptionally, a list group also has an `AddSpecifier` that controls the last item of the list group section. It is used to add items and could be a text field, a toggle, a slider, or a child pane. While the first three create a new item after editing is complete, a child pane presents a modal child view controller to configure a complex item, saved as a dictionary. Such child panes work very similarly to normal child panes with a few differences: They are presented not via push but modally and have a Cancel and Done button in the navigation bar. A new item is created by tapping the Done button.\n\nYou may want to specify some validation rules that need to be met before enabling the Done button. This can be achieved with the delegate method:\n\n    - (BOOL)settingsViewController:childPaneIsValidForSpecifier:contentDictionary:\n\nThe Done button is disabled when returning false from this method. Also note that the `contentDictionary` is a mutable dictionary. If you change some of the values, the UI will reflect that. This allows you to autocorrect invalid settings.\n\n\n\n## Custom Views\nYou can specify your own `UITableViewCell` within InAppSettingsKit by using the type `IASKCustomViewSpecifier`. A mandatory field in this case is the `Key` attribute. Also, you have to support the `IASKSettingsDelegate` protocol and implement these methods:\n\n    - (CGFloat)settingsViewController:(UITableViewController\u003cIASKViewController\u003e *)settingsViewController heightForSpecifier:(IASKSpecifier *)specifier;\n    - (UITableViewCell*)settingsViewController:(UITableViewController\u003cIASKViewController\u003e *)settingsViewController cellForSpecifier:(IASKSpecifier*)specifier;\n\nBoth methods are called for all your `IASKCustomViewSpecifier` entries. To differentiate them, you can access the `Key` attribute using `specifier.key`. In the first method you return the height of the cell, in the second method the cell itself. You should use reusable `UITableViewCell` objects as usual in table view programming. There's an example in the Demo app.\n\nOptionally you can implement\n\n    - (void)settingsViewController:(IASKAppSettingsViewController*)settingsViewController didSelectCustomViewSpecifier:(IASKSpecifier*)specifier;\n\nto catch tap events for your custom view.\n\nIf you specify `File`, `IASKViewControllerClass`, `IASKViewControllerStoryBoardId`, or `IASKSegueIdentifier` (see below), the selection behavior of a custom view is identical to a child pane and the delegate is not called on selection.\n\n\n\n## Section Headers and Footers\nThe FooterText key for Group elements is available in system settings. It is supported in InAppSettingsKit as well. On top of that, we support this key for Multi Value elements as well. The footer text is displayed below the table of multi value options.\n\nYou can define a custom header view for `PSGroupSpecifier` segments by adding a `Key` attribute and implementing the following method in your `IASKSettingsDelegate`:\n\n\t- (UIView *)settingsViewController:(id\u003cIASKViewController\u003e)settingsViewController tableView:(UITableView *)tableView viewForHeaderForSection:(NSInteger)section;\n\nYou can adjust the height of the header by implementing the following method:\n\n\t- (CGFloat)settingsViewController:(id\u003cIASKViewController\u003e)settingsViewController tableView:(UITableView*)tableView heightForHeaderForSection:(NSInteger)section;\n\nFor simpler header title customization without the need for a custom view, and provided the `-settingsViewController:tableView:viewForHeaderForSection:` method has not been implemented or returns `nil` for the section, implement the following method:\n\n\t- (NSString *)settingsViewController:(id\u003cIASKViewController\u003e)settingsViewController tableView:(UITableView*)tableView titleForHeaderForSection:(NSInteger)section;\n\nIf the method returns `nil` or a 0-length string, the title defined in the `.plist` will be used.\n\nThis behaviour is similar to custom table view cells. When implementing a method and if you need it, the section key can be retrieved from its index conveniently with:\n\n\tNSString *key = [settingsViewController.settingsReader keyForSection:section];\n\nCheck the demo app for a concrete example.\n\nFor footer customization, three methods from the `IASKSettingsDelegate` protocol can be similarly implemented.\n\n\n## Extending Child Panes\n\n### Custom ViewControllers\nFor child pane elements (`PSChildPaneSpecifier`), Apple requires a `file` key that specifies the child plist. InAppSettingsKit allow to alternatively specify `IASKViewControllerClass` and `IASKViewControllerSelector`. In this case, the child pane is displayed by instantiating a UIViewController subclass of the specified class and initializing it using the init method specified in the `IASKViewControllerSelector`. The selector must have two arguments: an `NSString` argument for the file name in the Settings bundle and the `IASKSpecifier`. The custom view controller is then pushed onto the navigation stack. See the [sample application](#sample-application) for more details.\n\n### Using Custom ViewControllers from StoryBoard\nAlternatively specify `IASKViewControllerStoryBoardId` to initiate a viewcontroller from [main storyboard](https://developer.apple.com/library/ios/documentation/general/conceptual/Devpedia-CocoaApp/Storyboard.html/).\nSpecify `IASKViewControllerStoryBoardFile` to use a storyboard other than the main storyboard from the app’s `Info.plist`.\n\n### Perform Segues\nAs an alternative to `IASKViewControllerClass` and `IASKViewControllerSelector` for child pane elements (`PSChildPaneSpecifier`), InAppSettingsKit is able to navigate to another view controller, by performing any segue defined in your storyboard. To do so specify the segue identifier in `IASKSegueIdentifier`.\n\n\n## Extending various specifiers\n\n### Subtitles\nThe `IASKSubtitle` key allows to define subtitles for these elements: Toggle, ChildPane, OpenURL, MailCompose, Button. Using a subtitle implies left alignment.\nA child pane displays its value as a subtitle, if available and no `IASKSubtitle` is specified.\nThe subtitle can be a localizable String or a Dictionary with localizable subtitles depending on the current value. `YES` and `NO` are used as keys for boolean toggle values. The dictionary may contain a `__default__` key to define a subtitle if no key is matching.\n\n### Text alignment\nFor some element types, a `IASKTextAlignment` attribute may be added with the following values to override the default alignment:\n\n- `IASKUITextAlignmentLeft` (ChildPane, TextField, Buttons, OpenURL, MailCompose)\n- `IASKUITextAlignmentCenter` (ChildPane, Buttons, OpenURL)\n- `IASKUITextAlignmentRight` (ChildPane, TextField, Buttons, OpenURL, MailCompose)\n\n### Variable font size\nBy default, the labels in the settings table are displayed in a variable font size, especially handy to squeeze-in long localizations (beware: this might break the look in Settings.app if labels are too long!).\nTo disable this behavior, add a `IASKAdjustsFontSizeToFitWidth` Boolean attribute with value `NO`.\n\n### Icons\nAll element types (except sliders which already have a `MinimumValueImage`) support an icon image on the left side of the cell. You can specify the image name in an optional `IASKCellImage` attribute. The \".png\" or \"@2x.png\" suffix is automatically appended and will be searched in the project. Optionally, you can add an image with suffix \"Highlighted.png\" or \"Highlighted@2x.png\" to the project and it will be automatically used as a highlight image when the cell is selected (for Buttons and ChildPanes).\nIf the image is not found as a resource in the project, InAppSettingsKit falls back to SF Symbols.\n\n\n## Extending Text Fields\n### Placeholder\nThe `IASKPlaceholder` key allows to define placeholder for TextField and TextView (`IASKTextViewSpecifier`).\n\n### Content Type\nTo support autofill based on the content type, add the `IASKTextContentType` key accepting the (prefix-less) constant names of [UITextContentType](https://developer.apple.com/documentation/uikit/uitextcontenttype). \nExample: to configure a text field with `UITextContentTypeEmailAddress`, use `IASKTextContentType`: `EmailAddress`.\n\n### Validation\nText fields can be validated using the delegate callback:\n\n\t- (IASKValidationResult)settingsViewController:(IASKAppSettingsViewController*)settingsViewController validateSpecifier:(IASKSpecifier*)specifier textField:(IASKTextField*)textField previousValue:(nullable NSString*)previousValue replacement:(NSString* _Nonnull __autoreleasing *_Nullable)replacement;\n\nThe callback receives the `IASKTextField` which is a `UITextField` subclass to allow styling of the text field in case of a validation error (e.g. red text). It contains a replacement out parameter to replace invalid text. Returning `IASKValidationResultFailedWithShake` lets the text field shake to visually indicate the validation error.\n\n\n## Customizing Toggles\n`PSToggleSwitchSpecifier` switches use a `UISwitch` by default. By specifying the option `IASKToggleStyle`: `Checkmark`, checkmarks are displayed for selected keys.\n\n\n## Dynamic MultiValue Lists\nMultiValue lists (`PSMultiValueSpecifier`) and radio groups (`PSRadioGroupSpecifier`) can fetch their values and titles dynamically from the delegate instead of the static Plist. Implement these two methods in your `IASKSettingsDelegate`:\n\n    - (NSArray*)settingsViewController:(IASKAppSettingsViewController*)sender valuesForSpecifier:(IASKSpecifier*)specifier;\n    - (NSArray\u003cNSString*\u003e*)settingsViewController:(IASKAppSettingsViewController*)sender titlesForSpecifier:(IASKSpecifier*)specifier;\n\nThe [sample application](#sample-application) returns a list of all country codes as values and the localized country names as titles.\n\nMultiValue lists can be sorted alphabetically by adding a `true` Boolean `DisplaySortedByTitle` key in the Plist.\nMultiValue list entries can be given an image. Specify images via the `IconNames` attribute (next to Values/Titles/ShortTitles etc.).\nMultiValue lists support an `IASKQuickMultiValueSelection` boolean key. If set to true, the child view controller is popped on selection, so tapping the back button is not needed.\n\n\n## Settings Storage\nThe default behaviour of IASK is to store the settings in `[NSUserDefaults standardUserDefaults]`. However, it is possible to change this behavior by setting the `settingsStore` property on an `IASKAppSettingsViewController`. IASK comes with two store implementations: `IASKSettingsStoreUserDefaults` (the default one) and `IASKSettingsStoreFile`, which read and write the settings in a file of the path you choose. If you need something more specific, you can also choose to create your own store. The easiest way to create your own store is to create a subclass of `IASKAbstractSettingsStore`. Only 3 methods are required to override. See `IASKSettingsStore.{h,m}` for more details.\n\n\n## Notifications\nThere's a `IASKSettingChangedNotification` notification that is sent for every changed settings key. The `object` of the notification is the sending view controller and the `userInfo` dictionary contains the key and new value of the affected key.\n\n\n## Dynamic cell hiding\nSometimes, options depend on each other. For instance, you might want to have an \"Auto Connect\" switch, and let the user set username and password if enabled. To react on changes of a specific setting, use the `IASKSettingChangedNotification` notification explained above.\n\nTo hide a set of cells use:\n\n    - (void)[IASKAppSettingsViewController setHiddenKeys:(NSSet*)hiddenKeys animated:(BOOL)animated];\n\nor the non-animated version:\n\n\t@property (nonatomic, strong) NSSet *hiddenKeys;\n\nSee the [sample application](#sample-application) for more details. Including a `PSGroupSpecifier` key in the `hiddenKeys` hides the complete section.\n\n\n## Register default values\nSettings property lists support the `DefaultValue` parameter to display default values in case there’s no value stored in `NSUserDefaults`. However, when the app queries `NSUserDefaults` for the value, that default value is not propagated. This makes sense since `NSUserDefaults` doesn’t know about settings property lists.\n\nTo initially set values for the various settings keys, `NSUserDefaults` provides the `registerDefaults:` method that takes a dictionary of \"fallback\" values that are returned from `NSUserDefaults` if no value has been stored. This is typically called at app launch.\n\nHowever, creating and maintaining that dictionary can be cumbersome and there’s a risk that this dictionary and the settings default values get out of sync.\n\nTo address this, `IASKSettingsReader` provides a method that generates this dictionary by traversing the Root.plist and all child plists and gathering the `DefaultValue` for all keys.\n\n    NSDictionary *defaultDict = [appSettingsViewController.settingsReader gatherDefaultsLimitedToEditableFields:YES];\n    [NSUserDefaults.standardUserDefaults registerDefaults:defaultDict];\n\n\n# iCloud sync\nTo sync your `NSUserDefaults` with iCloud, there's another project called [FTiCloudSync](https://github.com/futuretap/FTiCloudSync) which is implemented as a category on `NSUserDefaults`: All write and remove requests are automatically forwarded to iCloud and all updates from iCloud are automatically stored in `NSUserDefaults`. InAppSettingsKit automatically updates the UI if the standard `NSUserDefaults` based store is used.\n\n# Support\nPlease don't use Github issues for support requests, we'll close them. Instead, post your question on [StackOverflow](http://stackoverflow.com) with tag `inappsettingskit`.\n\n\n# License\nWe released the code under the liberal BSD license in order to make it possible to include it in every project, be it a free or paid app. The only thing we ask for is giving the original developers some credit. The easiest way to include credits is by leaving the \"Powered by InAppSettingsKit\" notice in the code. If you decide to remove this notice, a noticeable mention on the App Store description page or homepage is fine, too.\n\n# Author\nOriginally developed by Luc Vandal, [Ortwin Gentz](https://www.futuretap.com/about/ortwin-gentz) ([Mastodon](https://mastodon.cloud/@ortwingentz)) took over the development and continues to update the framework. InAppSettingsKit is used in [FutureTap](https://www.futuretap.com)’s [Where To?](https://wheretoapp.com) app, so we eat our own dog food!\n\n# Sponsors wanted\nIf you would like to support my Open Source work, consider joining me as a [sponsor](https://github.com/sponsors/futuretap)! 💪️ Your sponsorship enables me to spend more time on InAppSettingsKit and other community projects. Thank you!\n","funding_links":["https://github.com/sponsors/futuretap","https://github.com/sponsors/futuretap)!"],"categories":["Utility","Objective-C","Objective-C  Stars 1000以内排名整理","UI Components","etc"],"sub_categories":["Web View","Other free courses"],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffuturetap%2FInAppSettingsKit","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffuturetap%2FInAppSettingsKit","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffuturetap%2FInAppSettingsKit/lists"}