├── .hound.yml
├── docs
├── img
│ ├── gh.png
│ ├── carat.png
│ ├── dash.png
│ └── spinner.gif
├── badge.svg
├── js
│ ├── jazzy.js
│ └── jazzy.search.js
├── css
│ ├── highlight.css
│ └── jazzy.css
├── Structs.html
├── Protocols.html
├── Protocols
│ └── OptionDescriptive.html
├── Classes
│ ├── KeyboardDismissTextField.html
│ └── KeyboardDismissAccessoryView.html
├── search.json
└── Classes.html
├── screenshots
├── ICTokenField.gif
├── ICTokenField.png
└── ICKeyboardDismissTextField.png
├── Example
├── Assets.xcassets
│ ├── Contents.json
│ ├── icook-iphone-input-search.imageset
│ │ ├── icook-iphone-input-search.pdf
│ │ └── Contents.json
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Base.lproj
│ ├── InfoPlist.strings
│ └── LaunchScreen.storyboard
├── Info.plist
├── Language.swift
├── AppDelegate.swift
├── StoryboardViewController.swift
├── ExampleCell.swift
├── CustomizedTokenField.swift
├── CustomizedTokenViewController.swift
├── ExampleViewController.swift
└── Main.storyboard
├── Gemfile
├── Source
├── KeyboardDismissTextField
│ ├── Images.xcassets
│ │ ├── Contents.json
│ │ └── icook-iphone-button-hide-keyboard.imageset
│ │ │ ├── icook-iphone-button-hide-keyboard.pdf
│ │ │ └── Contents.json
│ ├── KeyboardDismissTextField.swift
│ └── KeyboardDismissAccessoryView.swift
├── TokenField
│ ├── BackspaceTextField.swift
│ ├── InsetLabel.swift
│ └── Token.swift
└── OptionPickerControl
│ ├── Option.swift
│ └── OptionPickerControl.swift
├── fastlane
└── Scanfile
├── .swiftlint.yml
├── ICInputAccessory.xcodeproj
├── project.xcworkspace
│ └── contents.xcworkspacedata
└── xcshareddata
│ └── xcschemes
│ ├── ICInputAccessory-iOS.xcscheme
│ └── Example.xcscheme
├── Podfile
├── ICInputAccessory.xcworkspace
├── contents.xcworkspacedata
└── xcshareddata
│ └── IDEWorkspaceChecks.plist
├── .jazzy.yml
├── Podfile.lock
├── .gitignore
├── ICInputAccessoryUITests
├── Info.plist
├── KeyboardDismissTextFieldUITests.swift
├── OptionPickerControlUITests.swift
└── TokenFieldUITests.swift
├── ICInputAccessory
├── Info.plist
└── ICInputAccessory.h
├── .github
└── workflows
│ ├── push.yml
│ └── pull_request.yml
├── Makefile
├── Dangerfile
├── LICENSE
├── CHANGELOG.md
├── ICInputAccessory.podspec
├── README.md
└── Gemfile.lock
/.hound.yml:
--------------------------------------------------------------------------------
1 | swift:
2 | enabled: true
3 | config_file: .swiftlint.yml
4 |
--------------------------------------------------------------------------------
/docs/img/gh.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/polydice/ICInputAccessory/HEAD/docs/img/gh.png
--------------------------------------------------------------------------------
/docs/img/carat.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/polydice/ICInputAccessory/HEAD/docs/img/carat.png
--------------------------------------------------------------------------------
/docs/img/dash.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/polydice/ICInputAccessory/HEAD/docs/img/dash.png
--------------------------------------------------------------------------------
/docs/img/spinner.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/polydice/ICInputAccessory/HEAD/docs/img/spinner.gif
--------------------------------------------------------------------------------
/screenshots/ICTokenField.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/polydice/ICInputAccessory/HEAD/screenshots/ICTokenField.gif
--------------------------------------------------------------------------------
/screenshots/ICTokenField.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/polydice/ICInputAccessory/HEAD/screenshots/ICTokenField.png
--------------------------------------------------------------------------------
/Example/Assets.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/Gemfile:
--------------------------------------------------------------------------------
1 | source "http://rubygems.org"
2 |
3 | gem "cocoapods"
4 | gem "danger"
5 | gem "fastlane"
6 | gem "jazzy", ">= 0.8.0"
7 |
--------------------------------------------------------------------------------
/Source/KeyboardDismissTextField/Images.xcassets/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "info" : {
3 | "version" : 1,
4 | "author" : "xcode"
5 | }
6 | }
--------------------------------------------------------------------------------
/fastlane/Scanfile:
--------------------------------------------------------------------------------
1 | workspace "ICInputAccessory.xcworkspace"
2 | scheme "Example"
3 | clean true
4 | skip_build true
5 | code_coverage true
6 |
--------------------------------------------------------------------------------
/screenshots/ICKeyboardDismissTextField.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/polydice/ICInputAccessory/HEAD/screenshots/ICKeyboardDismissTextField.png
--------------------------------------------------------------------------------
/.swiftlint.yml:
--------------------------------------------------------------------------------
1 | disabled_rules:
2 | - file_length
3 | - identifier_name
4 | - line_length
5 | - type_body_length
6 | - vertical_whitespace
7 | excluded:
8 | - Carthage
9 | - Pods
10 | - vendor
11 |
--------------------------------------------------------------------------------
/Example/Assets.xcassets/icook-iphone-input-search.imageset/icook-iphone-input-search.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/polydice/ICInputAccessory/HEAD/Example/Assets.xcassets/icook-iphone-input-search.imageset/icook-iphone-input-search.pdf
--------------------------------------------------------------------------------
/Example/Base.lproj/InfoPlist.strings:
--------------------------------------------------------------------------------
1 | /*
2 | InfoPlist.strings
3 | Example
4 |
5 | Created by Ben on 07/03/2016.
6 | Copyright © 2016 Polydice, Inc. All rights reserved.
7 | */
8 |
9 | "CFBundleDisplayName" = "ICInputAccessory";
10 |
--------------------------------------------------------------------------------
/ICInputAccessory.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/Example/Assets.xcassets/icook-iphone-input-search.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "icook-iphone-input-search.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/Podfile:
--------------------------------------------------------------------------------
1 | platform :ios, "8.0"
2 | use_frameworks!
3 |
4 | workspace "ICInputAccessory"
5 | project "ICInputAccessory"
6 |
7 | target "Example" do
8 | pod "SwiftLint", podspec: "https://raw.githubusercontent.com/CocoaPods/Specs/master/Specs/4/0/1/SwiftLint/0.25.1/SwiftLint.podspec.json"
9 | end
10 |
--------------------------------------------------------------------------------
/Source/KeyboardDismissTextField/Images.xcassets/icook-iphone-button-hide-keyboard.imageset/icook-iphone-button-hide-keyboard.pdf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/polydice/ICInputAccessory/HEAD/Source/KeyboardDismissTextField/Images.xcassets/icook-iphone-button-hide-keyboard.imageset/icook-iphone-button-hide-keyboard.pdf
--------------------------------------------------------------------------------
/ICInputAccessory.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/ICInputAccessory.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/Source/KeyboardDismissTextField/Images.xcassets/icook-iphone-button-hide-keyboard.imageset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "universal",
5 | "filename" : "icook-iphone-button-hide-keyboard.pdf"
6 | }
7 | ],
8 | "info" : {
9 | "version" : 1,
10 | "author" : "xcode"
11 | }
12 | }
--------------------------------------------------------------------------------
/.jazzy.yml:
--------------------------------------------------------------------------------
1 | clean: true
2 | author: polydice
3 | author_url: https://github.com/polydice
4 | github_url: https://github.com/polydice/ICInputAccessory
5 | github_file_prefix: https://github.com/polydice/ICInputAccessory/blob/develop
6 | xcodebuild_arguments: [-project, ICInputAccessory.xcodeproj, -scheme, ICInputAccessory-iOS]
7 | module: ICInputAccessory
8 | module_version: 2.0.1
9 | output: docs
10 | theme: fullwidth
11 | skip_undocumented: true
12 |
--------------------------------------------------------------------------------
/Podfile.lock:
--------------------------------------------------------------------------------
1 | PODS:
2 | - SwiftLint (0.25.1)
3 |
4 | DEPENDENCIES:
5 | - SwiftLint (from `https://raw.githubusercontent.com/CocoaPods/Specs/master/Specs/4/0/1/SwiftLint/0.25.1/SwiftLint.podspec.json`)
6 |
7 | EXTERNAL SOURCES:
8 | SwiftLint:
9 | :podspec: https://raw.githubusercontent.com/CocoaPods/Specs/master/Specs/4/0/1/SwiftLint/0.25.1/SwiftLint.podspec.json
10 |
11 | SPEC CHECKSUMS:
12 | SwiftLint: ce933681be10c3266e82576dad676fa815a602e9
13 |
14 | PODFILE CHECKSUM: 74bc2bf59f17e7cc006ae2aa1d4d73e50cc2b4ff
15 |
16 | COCOAPODS: 1.9.3
17 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # https://github.com/github/gitignore
4 |
5 | ## Build generated
6 | build/
7 | DerivedData
8 | test_output
9 |
10 | ## Various settings
11 | *.pbxuser
12 | !default.pbxuser
13 | *.mode1v3
14 | !default.mode1v3
15 | *.mode2v3
16 | !default.mode2v3
17 | *.perspectivev3
18 | !default.perspectivev3
19 | xcuserdata
20 |
21 | ## Other
22 | *.xccheckout
23 | *.moved-aside
24 | *.xcuserstate
25 | *.xcscmblueprint
26 |
27 | ## Obj-C/Swift specific
28 | *.hmap
29 | *.ipa
30 |
31 | ## Docs
32 | undocumented.json
33 | *.docset
34 | *.tgz
35 |
36 | ## CocoaPods
37 | Pods/
38 |
39 | ## Carthage
40 | Carthage/
41 |
--------------------------------------------------------------------------------
/ICInputAccessoryUITests/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | BNDL
17 | CFBundleShortVersionString
18 | 2.0.1
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 |
24 |
25 |
--------------------------------------------------------------------------------
/ICInputAccessory/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleExecutable
8 | $(EXECUTABLE_NAME)
9 | CFBundleIdentifier
10 | $(PRODUCT_BUNDLE_IDENTIFIER)
11 | CFBundleInfoDictionaryVersion
12 | 6.0
13 | CFBundleName
14 | $(PRODUCT_NAME)
15 | CFBundlePackageType
16 | FMWK
17 | CFBundleShortVersionString
18 | 2.0.1
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | $(CURRENT_PROJECT_VERSION)
23 | NSPrincipalClass
24 |
25 |
26 |
27 |
--------------------------------------------------------------------------------
/.github/workflows/push.yml:
--------------------------------------------------------------------------------
1 | name: iOS build
2 |
3 | on: push
4 |
5 | jobs:
6 | build:
7 | runs-on: macos-latest
8 | steps:
9 | - uses: actions/checkout@v1
10 | - name: Apply Ruby
11 | uses: actions/setup-ruby@v1
12 | with:
13 | ruby-version: '2.x'
14 | - uses: actions/cache@v1
15 | with:
16 | path: vendor/bundle
17 | key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
18 | restore-keys: |
19 | ${{ runner.os }}-gems-
20 | - uses: actions/cache@v1
21 | with:
22 | path: Pods
23 | key: ${{ runner.os }}-pods-${{ hashFiles('**/Podfile.lock') }}
24 | restore-keys: |
25 | ${{ runner.os }}-pods-
26 | - name: Install and setup
27 | run: make install
28 | - name: Run build
29 | run: |
30 | bundle exec fastlane scan
31 | make -B carthage
32 | make -B docs
33 |
--------------------------------------------------------------------------------
/Makefile:
--------------------------------------------------------------------------------
1 | bootstrap:
2 | gem install bundler
3 | bundle install
4 | bundle exec pod install
5 |
6 | install: bundle-install pod-install
7 |
8 | bundle-install:
9 | bundle install --without development --deployment --jobs=3 --retry=3
10 |
11 | pod-install:
12 | bundle exec pod install
13 |
14 | bump:
15 | ifeq (,$(strip $(version)))
16 | # Usage: make bump version=
17 | else
18 | ruby -pi -e "gsub(/\d+\.\d+\.\d+/i, \""$(version)"\")" ICInputAccessory.podspec
19 | ruby -pi -e "gsub(/:\s\d+\.\d+\.\d+/i, \": "$(version)"\")" .jazzy.yml
20 | xcrun agvtool new-marketing-version $(version)
21 | make -B docs
22 | endif
23 |
24 | carthage:
25 | set -o pipefail && carthage build --no-skip-current --verbose | bundle exec xcpretty
26 |
27 | docs:
28 | bundle exec jazzy --config .jazzy.yml
29 | for file in "html" "css" "js" "json"; do \
30 | echo "Trimming whitespace in *."$$file ; \
31 | find docs -name "*."$$file -exec sed -E -i "" -e "s/[[:blank:]]*$$//" {} \; ; \
32 | done
33 |
--------------------------------------------------------------------------------
/Dangerfile:
--------------------------------------------------------------------------------
1 | #!/usr/bin/env ruby
2 |
3 | # Sometimes it's a README fix, or something like that - which isn't relevant for
4 | # including in a project's CHANGELOG for example
5 | declared_trivial = (github.pr_title + github.pr_body).include? "#trivial"
6 |
7 | # Make it more obvious that a PR is a work in progress and shouldn't be merged yet
8 | warn "PR is classed as Work in Progress" if github.pr_title.include? "[WIP]"
9 |
10 | # Warn when there is a big PR
11 | warn "Big PR" if git.lines_of_code > 500
12 |
13 | # Ensure there is a summary for a PR
14 | fail "Please provide a summary in the Pull Request description" if github.pr_body.length < 5
15 |
16 | # Add a CHANGELOG entry for app changes
17 | if git.lines_of_code > 50 && !git.modified_files.include?("CHANGELOG.md") && !declared_trivial
18 | fail "Please update [CHANGELOG.md](https://github.com/polydice/ICInputAccessory/blob/develop/CHANGELOG.md).", sticky: true
19 | end
20 |
21 | # Ensure a clean commits history
22 | if git.commits.any? { |c| c.message =~ /^Merge branch/ }
23 | fail "Please rebase to get rid of the merge commits in this PR", sticky: true
24 | end
25 |
--------------------------------------------------------------------------------
/Example/Assets.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "20x20",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "20x20",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "29x29",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "29x29",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "40x40",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "40x40",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "iphone",
35 | "size" : "60x60",
36 | "scale" : "2x"
37 | },
38 | {
39 | "idiom" : "iphone",
40 | "size" : "60x60",
41 | "scale" : "3x"
42 | },
43 | {
44 | "idiom" : "ios-marketing",
45 | "size" : "1024x1024",
46 | "scale" : "1x"
47 | }
48 | ],
49 | "info" : {
50 | "version" : 1,
51 | "author" : "xcode"
52 | }
53 | }
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License (MIT)
2 |
3 | Copyright (c) 2016 Polydice, Inc.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/docs/badge.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 | documentation
17 |
18 |
19 | documentation
20 |
21 |
22 | 73%
23 |
24 |
25 | 73%
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/.github/workflows/pull_request.yml:
--------------------------------------------------------------------------------
1 | name: iOS review
2 |
3 | on: pull_request
4 |
5 | jobs:
6 | build:
7 | runs-on: ubuntu-latest
8 | steps:
9 | - uses: actions/checkout@v2
10 | with:
11 | fetch-depth: 0
12 | - name: Apply Ruby
13 | uses: actions/setup-ruby@v1
14 | with:
15 | ruby-version: '2.x'
16 | - uses: actions/cache@v1
17 | with:
18 | path: vendor/bundle
19 | key: ${{ runner.os }}-gems-${{ hashFiles('**/Gemfile.lock') }}
20 | restore-keys: |
21 | ${{ runner.os }}-gems-
22 | - name: Bundle install
23 | run: |
24 | bundle config path vendor/bundle
25 | bundle install --jobs 4 --retry 3
26 | - name: Run Danger
27 | run: bundle exec danger
28 | env:
29 | DANGER_GITHUB_API_TOKEN: ${{ secrets.GITHUB_TOKEN }}
30 | - name: Fetch base ref
31 | run: git fetch --no-tags --prune --depth=1 origin ${{ github.base_ref }}
32 | - name: Run SwiftLint
33 | uses: norio-nomura/action-swiftlint@3.1.0
34 | with:
35 | args: --force-exclude
36 | env:
37 | DIFF_BASE: origin/${{ github.base_ref }}
38 |
--------------------------------------------------------------------------------
/docs/js/jazzy.js:
--------------------------------------------------------------------------------
1 | window.jazzy = {'docset': false}
2 | if (typeof window.dash != 'undefined') {
3 | document.documentElement.className += ' dash'
4 | window.jazzy.docset = true
5 | }
6 | if (navigator.userAgent.match(/xcode/i)) {
7 | document.documentElement.className += ' xcode'
8 | window.jazzy.docset = true
9 | }
10 |
11 | // On doc load, toggle the URL hash discussion if present
12 | $(document).ready(function() {
13 | if (!window.jazzy.docset) {
14 | var linkToHash = $('a[href="' + window.location.hash +'"]');
15 | linkToHash.trigger("click");
16 | }
17 | });
18 |
19 | // On token click, toggle its discussion and animate token.marginLeft
20 | $(".token").click(function(event) {
21 | if (window.jazzy.docset) {
22 | return;
23 | }
24 | var link = $(this);
25 | var animationDuration = 300;
26 | $content = link.parent().parent().next();
27 | $content.slideToggle(animationDuration);
28 |
29 | // Keeps the document from jumping to the hash.
30 | var href = $(this).attr('href');
31 | if (history.pushState) {
32 | history.pushState({}, '', href);
33 | } else {
34 | location.hash = href;
35 | }
36 | event.preventDefault();
37 | });
38 |
39 | // Dumb down quotes within code blocks that delimit strings instead of quotations
40 | // https://github.com/realm/jazzy/issues/714
41 | $("code q").replaceWith(function () {
42 | return ["\"", $(this).contents(), "\""];
43 | });
44 |
--------------------------------------------------------------------------------
/Example/Info.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | CFBundleDevelopmentRegion
6 | en
7 | CFBundleDisplayName
8 | ICInputAccessoryExample
9 | CFBundleExecutable
10 | $(EXECUTABLE_NAME)
11 | CFBundleIdentifier
12 | $(PRODUCT_BUNDLE_IDENTIFIER)
13 | CFBundleInfoDictionaryVersion
14 | 6.0
15 | CFBundleName
16 | $(PRODUCT_NAME)
17 | CFBundlePackageType
18 | APPL
19 | CFBundleShortVersionString
20 | 2.0.1
21 | CFBundleSignature
22 | ????
23 | CFBundleVersion
24 | 101
25 | LSRequiresIPhoneOS
26 |
27 | UILaunchStoryboardName
28 | LaunchScreen
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UIRequiresFullScreen
34 |
35 | UISupportedInterfaceOrientations
36 |
37 | UIInterfaceOrientationPortrait
38 | UIInterfaceOrientationLandscapeLeft
39 | UIInterfaceOrientationLandscapeRight
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/ICInputAccessory/ICInputAccessory.h:
--------------------------------------------------------------------------------
1 | //
2 | // ICInputAccessory.h
3 | // ICInputAccessory
4 | //
5 | // Created by Ben on 04/03/2016.
6 | // Copyright © 2016 Polydice, Inc.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 |
27 | #import
28 |
29 | //! Project version number for ICInputAccessory.
30 | FOUNDATION_EXPORT double ICInputAccessoryVersionNumber;
31 |
32 | //! Project version string for ICInputAccessory.
33 | FOUNDATION_EXPORT const unsigned char ICInputAccessoryVersionString[];
34 |
35 | // In this header, you should import all the public headers of your framework using statements like #import
36 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## Unreleased
2 |
3 | * Update CI infrastructure to GitHub Actions
4 | * Swift 5.0
5 |
6 | ## v2.0.1
7 |
8 | * Fix the embedded standard library issue [#32](https://github.com/polydice/ICInputAccessory/pull/32)
9 |
10 | ## v2.0.0
11 |
12 | * Drop Class Name Prefixes
13 | * Add an easy to use `OptionPickerControl` that displays a `UIPickerView` with given options
14 |
15 | ## v1.5.0
16 |
17 | * Swift 4.0
18 |
19 | ## v1.4.1
20 |
21 | * Fix `tokenField(_:didChangeInputText:)` with the delete key [#20](https://github.com/polydice/ICInputAccessory/pull/20)
22 |
23 | #### Project Updates
24 |
25 | * Reenable UI tests
26 | * Combine the framework and example projects
27 | * Specify SwiftLint version via CocoaPods
28 |
29 | ## v1.4.0
30 |
31 | * Added delegate methods:
32 |
33 | ```swift
34 | @objc optional func tokenField(_ tokenField: ICTokenField, didChangeInputText text: String)
35 | @objc optional func tokenField(_ tokenField: ICTokenField, shouldCompleteText text: String) -> Bool
36 | @objc optional func tokenField(_ tokenField: ICTokenField, subsequentDelimiterForCompletedText text: String) -> String
37 | ```
38 |
39 | * Renamed delegate method:
40 |
41 | ```swift
42 | @objc optional func tokenField(_ tokenField: ICTokenField, didCompleteText text: String)
43 | ```
44 |
45 | ## v1.3.0
46 |
47 | * Swift 3.0
48 | * Support `pod try ICInputAccessory`
49 |
50 | ## v1.2.1
51 |
52 | * Update to Xcode 8.2
53 |
54 | ## v1.2.0
55 |
56 | * Swift 2.3
57 |
58 | ## v1.1.0
59 |
60 | * Swift 2.2
61 | * Support storyboard
62 | * Support subspecs
63 |
64 | ## v1.0.0
65 |
66 | Initial release written in Swift 2.1.
67 |
68 | * `ICKeyboardDismissTextField` with an accessory view to dismiss keyboard.
69 | * `ICTokenField`, a text field that groups input texts as tokens.
70 |
--------------------------------------------------------------------------------
/docs/js/jazzy.search.js:
--------------------------------------------------------------------------------
1 | $(function(){
2 | var searchIndex = lunr(function() {
3 | this.ref('url');
4 | this.field('name');
5 | });
6 |
7 | var $typeahead = $('[data-typeahead]');
8 | var $form = $typeahead.parents('form');
9 | var searchURL = $form.attr('action');
10 |
11 | function displayTemplate(result) {
12 | return result.name;
13 | }
14 |
15 | function suggestionTemplate(result) {
16 | var t = '';
17 | t += '' + result.name + ' ';
18 | if (result.parent_name) {
19 | t += '' + result.parent_name + ' ';
20 | }
21 | t += '
';
22 | return t;
23 | }
24 |
25 | $typeahead.one('focus', function() {
26 | $form.addClass('loading');
27 |
28 | $.getJSON(searchURL).then(function(searchData) {
29 | $.each(searchData, function (url, doc) {
30 | searchIndex.add({url: url, name: doc.name});
31 | });
32 |
33 | $typeahead.typeahead(
34 | {
35 | highlight: true,
36 | minLength: 3
37 | },
38 | {
39 | limit: 10,
40 | display: displayTemplate,
41 | templates: { suggestion: suggestionTemplate },
42 | source: function(query, sync) {
43 | var results = searchIndex.search(query).map(function(result) {
44 | var doc = searchData[result.ref];
45 | doc.url = result.ref;
46 | return doc;
47 | });
48 | sync(results);
49 | }
50 | }
51 | );
52 | $form.removeClass('loading');
53 | $typeahead.trigger('focus');
54 | });
55 | });
56 |
57 | var baseURL = searchURL.slice(0, -"search.json".length);
58 |
59 | $typeahead.on('typeahead:select', function(e, result) {
60 | window.location = baseURL + result.url;
61 | });
62 | });
63 |
--------------------------------------------------------------------------------
/Example/Language.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Language.swift
3 | // Example
4 | //
5 | // Created by Ben on 20/01/2018.
6 | // Copyright © 2018 bcylin.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 |
27 | import Foundation
28 | import ICInputAccessory
29 |
30 | enum Language: String, OptionDescriptive {
31 |
32 | case english
33 | case french
34 | case german
35 | case japanese
36 | case mandarin
37 | case spanish
38 |
39 | static var availableLanguages: [Language] = [
40 | .english,
41 | .french,
42 | .german,
43 | .japanese,
44 | .mandarin,
45 | .spanish
46 | ]
47 |
48 | // MARK: - OptionDescriptive
49 |
50 | var title: String {
51 | return rawValue.capitalized
52 | }
53 |
54 | static var titleForOptionalValue: String {
55 | return "(Optional)"
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/Example/AppDelegate.swift:
--------------------------------------------------------------------------------
1 | //
2 | // AppDelegate.swift
3 | // Example
4 | //
5 | // Created by Ben on 07/03/2016.
6 | // Copyright © 2016 Polydice, Inc.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 |
27 | import UIKit
28 |
29 | @UIApplicationMain
30 | class AppDelegate: UIResponder, UIApplicationDelegate {
31 |
32 | var window: UIWindow?
33 |
34 | func application(_ application: UIApplication,
35 | didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil)
36 | -> Bool {
37 | window = UIWindow(frame: UIScreen.main.bounds)
38 | window?.backgroundColor = UIColor.white
39 | window?.rootViewController = UINavigationController(rootViewController: ExampleViewController())
40 | window?.makeKeyAndVisible()
41 | return true
42 | }
43 |
44 | }
45 |
--------------------------------------------------------------------------------
/ICInputAccessory.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "ICInputAccessory"
3 | s.version = "2.0.1"
4 | s.summary = "A customized token text field used in the iCook app."
5 | s.description = <<-DESC
6 | KeyboardDismissTextField:
7 | * An input accessory view with a button to dismiss keyboard.
8 |
9 | TokenField:
10 | * A horizontal scrolling UI that groups input texts.
11 | * Easy to add, select and delete tokens.
12 | * Customizable icon and colors.
13 | * Supports storyboard.
14 |
15 | OptionPickerControl:
16 | * An easy to use UIControl that displays a UIPickerView with given options.
17 | DESC
18 |
19 | s.screenshots = "https://raw.githubusercontent.com/polydice/ICInputAccessory/master/screenshots/ICTokenField.png",
20 | "https://raw.githubusercontent.com/polydice/ICInputAccessory/master/screenshots/ICKeyboardDismissTextField.png"
21 | s.homepage = "https://github.com/polydice/ICInputAccessory"
22 | s.license = { type: "MIT", file: "LICENSE" }
23 | s.authors = "bcylin", "trisix"
24 | s.platform = :ios, "8.0"
25 | s.swift_version = "4.0"
26 | s.source = { git: "https://github.com/polydice/ICInputAccessory.git", tag: "v#{s.version}" }
27 | s.requires_arc = true
28 |
29 | s.default_subspecs = "KeyboardDismissTextField", "OptionPickerControl", "TokenField"
30 |
31 | s.subspec "KeyboardDismissTextField" do |sp|
32 | sp.source_files = "Source/KeyboardDismissTextField/*.swift"
33 | sp.resources = "Source/KeyboardDismissTextField/*.xcassets"
34 | end
35 |
36 | s.subspec "OptionPickerControl" do |sp|
37 | sp.source_files = "Source/OptionPickerControl/*.swift"
38 | end
39 |
40 | s.subspec "TokenField" do |sp|
41 | sp.source_files = "Source/TokenField/*.swift"
42 | end
43 | end
44 |
--------------------------------------------------------------------------------
/Example/StoryboardViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // StoryboardViewController.swift
3 | // Example
4 | //
5 | // Created by Ben on 16/03/2016.
6 | // Copyright © 2016 Polydice, Inc.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 |
27 | import UIKit
28 | import ICInputAccessory
29 |
30 | class StoryboardViewController: UITableViewController {
31 |
32 | @IBOutlet weak var tokenField: TokenField! {
33 | didSet {
34 | tokenField.normalTokenAttributes = [
35 | .foregroundColor: UIColor.white,
36 | .backgroundColor: UIColor.white.withAlphaComponent(0.25)
37 | ]
38 |
39 | tokenField.highlightedTokenAttributes = [
40 | .foregroundColor: UIColor.darkGray,
41 | .backgroundColor: UIColor.white
42 | ]
43 | }
44 | }
45 |
46 | @IBAction func dismiss(_ sender: UIButton) {
47 | presentingViewController?.dismiss(animated: true, completion: nil)
48 | }
49 |
50 | }
51 |
--------------------------------------------------------------------------------
/ICInputAccessoryUITests/KeyboardDismissTextFieldUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // KeyboardDismissTextFieldUITests.swift
3 | // ICInputAccessoryUITests
4 | //
5 | // Created by Ben on 20/03/2016.
6 | // Copyright © 2016 Polydice, Inc.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 |
27 | import XCTest
28 |
29 | extension XCUIElement {
30 | func waitAndForceTap(timeout: TimeInterval = 5000) {
31 | XCTAssert(waitForExistence(timeout: timeout))
32 | coordinate(withNormalizedOffset: CGVector(dx: 0.5, dy: 0.5)).tap()
33 | }
34 | }
35 |
36 | class KeyboardDismissTextFieldUITests: XCTestCase {
37 |
38 | private lazy var app = XCUIApplication()
39 |
40 | override func setUp() {
41 | super.setUp()
42 | continueAfterFailure = false
43 | XCUIApplication().launch()
44 | }
45 |
46 | func testKeyboardDismissing() {
47 | app.tables.textFields["KeyboardDismissTextField"].tap()
48 | app.buttons["Dismiss Keyboard"].waitAndForceTap()
49 | }
50 |
51 | func testStoryboard() {
52 | app.tables.buttons["Storyboard"].tap()
53 | app.tables.textFields["Storyboard KeyboardDismissTextField"].tap()
54 | app.buttons["Dismiss Keyboard"].waitAndForceTap()
55 | app.tables.buttons["Back to Code"].tap()
56 | }
57 |
58 | }
59 |
--------------------------------------------------------------------------------
/Source/TokenField/BackspaceTextField.swift:
--------------------------------------------------------------------------------
1 | //
2 | // BackspaceTextField.swift
3 | // iCook
4 | //
5 | // Created by Ben on 02/03/2016.
6 | // Copyright © 2016 Polydice, Inc.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 |
27 | import UIKit
28 |
29 | internal protocol BackspaceTextFieldDelegate: class {
30 | func textFieldShouldDelete(_ textField: BackspaceTextField) -> Bool
31 | }
32 |
33 | ////////////////////////////////////////////////////////////////////////////////
34 |
35 |
36 | internal class BackspaceTextField: UITextField {
37 |
38 | weak var backspaceDelegate: BackspaceTextFieldDelegate?
39 |
40 | var showsCursor = true {
41 | didSet {
42 | // Trigger the lazy instantiation of cursorColor
43 | let color = cursorColor
44 | tintColor = showsCursor ? color : UIColor.clear
45 | }
46 | }
47 |
48 | lazy var cursorColor: UIColor! = { self.tintColor }()
49 |
50 | // MARK: - UIView
51 |
52 | override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
53 | // Forward touches to the superview when the cursor is hidden.
54 | return showsCursor && super.point(inside: point, with: event)
55 | }
56 |
57 | // MARK: - UITextField
58 |
59 | @objc func keyboardInputShouldDelete(_ textField: UITextField) -> Bool {
60 | return backspaceDelegate?.textFieldShouldDelete(self) ?? true
61 | }
62 |
63 | }
64 |
--------------------------------------------------------------------------------
/ICInputAccessoryUITests/OptionPickerControlUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OptionPickerControlUITests.swift
3 | // ICInputAccessoryUITests
4 | //
5 | // Created by Ben on 21/01/2018.
6 | // Copyright © 2018 bcylin.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 |
27 | import XCTest
28 |
29 | final class OptionPickerControlUITests: XCTestCase {
30 |
31 | private lazy var app = XCUIApplication()
32 |
33 | override func setUp() {
34 | super.setUp()
35 | continueAfterFailure = false
36 | XCUIApplication().launch()
37 | }
38 |
39 | func testOptionSelection() {
40 | app.tables.staticTexts["(Optional)"].tap()
41 | let picker = app.pickerWheels.element
42 |
43 | picker.adjust(toPickerWheelValue: "English")
44 | XCTAssert(app.tables.staticTexts["English"].exists)
45 |
46 | picker.adjust(toPickerWheelValue: "French")
47 | XCTAssert(app.tables.staticTexts["French"].exists)
48 |
49 | picker.adjust(toPickerWheelValue: "German")
50 | XCTAssert(app.tables.staticTexts["German"].exists)
51 |
52 | picker.adjust(toPickerWheelValue: "Japanese")
53 | XCTAssert(app.tables.staticTexts["Japanese"].exists)
54 |
55 | picker.adjust(toPickerWheelValue: "Mandarin")
56 | XCTAssert(app.tables.staticTexts["Mandarin"].exists)
57 |
58 | picker.adjust(toPickerWheelValue: "Spanish")
59 | XCTAssert(app.tables.staticTexts["Spanish"].exists)
60 |
61 | app.toolbars.buttons["Done"].tap()
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/Source/TokenField/InsetLabel.swift:
--------------------------------------------------------------------------------
1 | //
2 | // InsetLabel.swift
3 | // iCook
4 | //
5 | // Created by Ben on 10/07/2015.
6 | // Copyright (c) 2015 Polydice, Inc.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 |
27 | import UIKit
28 |
29 | internal class InsetLabel: UILabel {
30 |
31 | enum CornerRadius {
32 | case dynamic
33 | case constant(CGFloat)
34 | }
35 |
36 | var contentEdgeInsets = UIEdgeInsets.zero
37 | var cornerRadius = CornerRadius.constant(0)
38 |
39 | convenience init(contentEdgeInsets: UIEdgeInsets, cornerRadius: CornerRadius = .constant(0)) {
40 | self.init(frame: CGRect.zero)
41 | self.contentEdgeInsets = contentEdgeInsets
42 | self.cornerRadius = cornerRadius
43 |
44 | switch cornerRadius {
45 | case let .constant(radius) where radius > 0:
46 | layer.cornerRadius = radius
47 | fallthrough // swiftlint:disable:this fallthrough
48 | case .dynamic:
49 | layer.masksToBounds = true
50 | layer.shouldRasterize = true
51 | layer.rasterizationScale = UIScreen.main.scale
52 | default:
53 | break
54 | }
55 | }
56 |
57 | // MARK: - UIView
58 |
59 | override var intrinsicContentSize: CGSize {
60 | let size = super.intrinsicContentSize
61 | return CGSize(
62 | width: contentEdgeInsets.left + size.width + contentEdgeInsets.right,
63 | height: contentEdgeInsets.top + size.height + contentEdgeInsets.bottom
64 | )
65 | }
66 |
67 | override func layoutSubviews() {
68 | super.layoutSubviews()
69 | if case .dynamic = cornerRadius {
70 | layer.cornerRadius = frame.height / 2
71 | }
72 | }
73 |
74 | }
75 |
--------------------------------------------------------------------------------
/Example/ExampleCell.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ExampleCell.swift
3 | // Example
4 | //
5 | // Created by Ben on 07/03/2016.
6 | // Copyright © 2016 Polydice, Inc.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 |
27 | import UIKit
28 |
29 | class ExampleCell: UITableViewCell {
30 |
31 | var showcase: UIView? {
32 | didSet {
33 | oldValue?.removeFromSuperview()
34 | if let displayingView = showcase {
35 | contentView.addSubview(displayingView)
36 | displayingView.translatesAutoresizingMaskIntoConstraints = false
37 |
38 | if #available(iOS 9.0, *) {
39 | displayingView.topAnchor.constraint(equalTo: contentView.topAnchor).isActive = true
40 | displayingView.leftAnchor.constraint(equalTo: contentView.leftAnchor).isActive = true
41 | displayingView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
42 | displayingView.rightAnchor.constraint(equalTo: contentView.rightAnchor).isActive = true
43 | } else {
44 | let views = ["view": displayingView]
45 | contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[view]|", options: [], metrics: nil, views: views))
46 | contentView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|[view]|", options: [], metrics: nil, views: views))
47 | }
48 | }
49 | }
50 | }
51 |
52 | // MARK: - UITableViewCell
53 |
54 | override func prepareForReuse() {
55 | super.prepareForReuse()
56 | showcase?.removeFromSuperview()
57 | showcase = nil
58 | textLabel?.text = nil
59 | accessoryType = .none
60 | }
61 |
62 | }
63 |
--------------------------------------------------------------------------------
/ICInputAccessoryUITests/TokenFieldUITests.swift:
--------------------------------------------------------------------------------
1 | //
2 | // TokenFieldUITests.swift
3 | // ICInputAccessoryUITests
4 | //
5 | // Created by Ben on 08/03/2016.
6 | // Copyright © 2016 Polydice, Inc.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 |
27 | import XCTest
28 |
29 | class TokenFieldUITests: XCTestCase {
30 |
31 | private lazy var app = XCUIApplication()
32 |
33 | override func setUp() {
34 | super.setUp()
35 | continueAfterFailure = false
36 | app.launch()
37 | }
38 |
39 | private func typeTexts(in textField: XCUIElement) {
40 | textField.tap()
41 | textField.typeText("Try")
42 | textField.typeText(" ")
43 | textField.typeText("iCook")
44 | textField.typeText(",")
45 | textField.typeText("beta")
46 | textField.typeText(" ")
47 |
48 | let deleteKey = app.keys["delete"]
49 | deleteKey.tap()
50 | deleteKey.tap()
51 |
52 | textField.typeText("TestFlight")
53 | textField.typeText(",")
54 |
55 | app.buttons["Search"].tap()
56 | }
57 |
58 | func testTokenField() {
59 | let textField = app.tables.cells.textFields["TokenField"]
60 | typeTexts(in: textField)
61 | }
62 |
63 | func testCustomizedTokenField() {
64 | app.tables.staticTexts["CustomizedTokenField"].tap()
65 | let tokenField = app.navigationBars["Example.CustomizedTokenView"].scrollViews.children(matching: .textField).element
66 | typeTexts(in: tokenField)
67 | }
68 |
69 | func testStoryboard() {
70 | app.tables.buttons["Storyboard"].tap()
71 | let tokenField = app.tables.cells.textFields["Storyboard TokenField"]
72 | typeTexts(in: tokenField)
73 | app.tables.buttons["Back to Code"].tap()
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/Source/OptionPickerControl/Option.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Option.swift
3 | // ICInputAccessory
4 | //
5 | // Created by Ben on 22/11/2017.
6 | // Copyright © 2017 bcylin.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 |
27 | import Foundation
28 |
29 | /// The protocol defines the required variables to be displayed in a `UIPickerView` via `OptionPickerControl`.
30 | public protocol OptionDescriptive: Equatable {
31 | /// The text for the row in the `UIPickerView`.
32 | var title: String { get }
33 | /// The text for a placeholder row when the picker selection is optional.
34 | static var titleForOptionalValue: String { get }
35 | }
36 |
37 |
38 | /// An option struct that carries the `OptionDescriptive`
39 | public struct Option: Equatable {
40 |
41 | // MARK: - Initialization
42 |
43 | /// Returns an option that displays the optional value of an `OptionDescriptive` type.
44 | public static var optional: Option {
45 | return Option()
46 | }
47 |
48 | /// Returns an initialized option with an instance of an `OptionDescriptive` type.
49 | public init(_ value: T) {
50 | self.value = value
51 | }
52 |
53 | // MARK: - Properties
54 |
55 | /// Conformance to `OptionDescriptive`.
56 | public var title: String {
57 | return value?.title ?? T.titleForOptionalValue
58 | }
59 |
60 | /// The `OptionDescriptive` value of the option. Returns `nil` when it's the `optional` placeholder.
61 | public let value: T?
62 |
63 | // MARK: - Private
64 |
65 | private init() {
66 | self.value = nil
67 | }
68 |
69 | // MARK: - Equatable
70 |
71 | /// Returns true when two options' values are equal.
72 | public static func == (lhs: Option, rhs: Option) -> Bool {
73 | return lhs.value == rhs.value
74 | }
75 |
76 | }
77 |
--------------------------------------------------------------------------------
/Example/CustomizedTokenField.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CustomizedTokenField.swift
3 | // Example
4 | //
5 | // Created by Ben on 09/03/2016.
6 | // Copyright © 2016 Polydice, Inc.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 |
27 | import UIKit
28 | import ICInputAccessory
29 |
30 | class CustomizedTokenField: TokenField {
31 |
32 | override init(frame: CGRect) {
33 | super.init(frame: frame)
34 | applyCustomizedStyle()
35 | }
36 |
37 | required init?(coder aDecoder: NSCoder) {
38 | super.init(coder: aDecoder)
39 | applyCustomizedStyle()
40 | }
41 |
42 | override var intrinsicContentSize: CGSize {
43 | return UIView.layoutFittingExpandedSize
44 | }
45 |
46 | }
47 |
48 |
49 | ////////////////////////////////////////////////////////////////////////////////
50 |
51 |
52 | extension TokenField {
53 |
54 | func applyCustomizedStyle() {
55 | icon = UIImage(named: "icook-iphone-input-search")
56 |
57 | layer.cornerRadius = 5
58 | layer.shouldRasterize = true
59 | layer.rasterizationScale = UIScreen.main.scale
60 | backgroundColor = UIColor(red: 0.8, green: 0.32, blue: 0.24, alpha: 1)
61 |
62 | textField.textColor = UIColor.white
63 | textField.tintColor = UIColor.white
64 | textField.font = UIFont.boldSystemFont(ofSize: 14)
65 |
66 | attributedPlaceholder = NSAttributedString(
67 | string: String(describing: type(of: self)),
68 | attributes: [
69 | .foregroundColor: UIColor.white.withAlphaComponent(0.5),
70 | .font: UIFont.boldSystemFont(ofSize: 14)
71 | ]
72 | )
73 |
74 | normalTokenAttributes = [
75 | .foregroundColor: UIColor.white,
76 | .backgroundColor: UIColor.white.withAlphaComponent(0.25),
77 | .font: UIFont.boldSystemFont(ofSize: 14)
78 | ]
79 |
80 | highlightedTokenAttributes = [
81 | .foregroundColor: UIColor(red: 0.8, green: 0.32, blue: 0.24, alpha: 1),
82 | .backgroundColor: UIColor.white,
83 | .font: UIFont.boldSystemFont(ofSize: 14)
84 | ]
85 | }
86 |
87 | }
88 |
--------------------------------------------------------------------------------
/ICInputAccessory.xcodeproj/xcshareddata/xcschemes/ICInputAccessory-iOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
32 |
33 |
43 |
44 |
50 |
51 |
52 |
53 |
59 |
60 |
66 |
67 |
68 |
69 |
71 |
72 |
75 |
76 |
77 |
--------------------------------------------------------------------------------
/Example/Base.lproj/LaunchScreen.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
--------------------------------------------------------------------------------
/Source/KeyboardDismissTextField/KeyboardDismissTextField.swift:
--------------------------------------------------------------------------------
1 | //
2 | // KeyboardDismissTextField.swift
3 | // ICInputAccessory
4 | //
5 | // Created by Ben on 07/03/2016.
6 | // Copyright © 2016 Polydice, Inc.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 |
27 | import UIKit
28 |
29 | /// A text field that has a button to dismiss keyboard on the input accessory view.
30 | @IBDesignable
31 | open class KeyboardDismissTextField: UITextField {
32 |
33 | /// The custom input accessory view with a button to dismiss keyboard.
34 | @IBOutlet public var keyboardAccessoryView: KeyboardDismissAccessoryView! {
35 | didSet {
36 | if UI_USER_INTERFACE_IDIOM() != .phone { return }
37 | keyboardAccessoryView.dismissButton.addTarget(self, action: .dismiss, for: .touchUpInside)
38 | inputAccessoryView = keyboardAccessoryView
39 | }
40 | }
41 |
42 | // MARK: - Initialization
43 |
44 | /// Initializes and returns a newly allocated view object with the specified frame rectangle.
45 | public override init(frame: CGRect) {
46 | super.init(frame: frame)
47 | setUpAccessoryView()
48 | }
49 |
50 | /// Returns an object initialized from data in a given unarchiver.
51 | public required init?(coder aDecoder: NSCoder) {
52 | super.init(coder: aDecoder)
53 | setUpAccessoryView()
54 | }
55 |
56 | // MARK: - UIResponder
57 |
58 | open override func becomeFirstResponder() -> Bool {
59 | if UI_USER_INTERFACE_IDIOM() == .phone {
60 | keyboardAccessoryView.alpha = 1
61 | }
62 | return super.becomeFirstResponder()
63 | }
64 |
65 | @objc fileprivate func dismiss(_ sender: UIButton) {
66 | resignFirstResponder()
67 | UIView.animate(withDuration: 0.3) {
68 | self.keyboardAccessoryView.alpha = 0
69 | }
70 | }
71 |
72 | // MARK: - Private Methods
73 |
74 | private func setUpAccessoryView() {
75 | if keyboardAccessoryView == nil {
76 | // Set an initial frame for the button to appear during UI testing.
77 | let frame = CGRect(x: 0, y: 0, width: 320, height: 60)
78 | keyboardAccessoryView = KeyboardDismissAccessoryView(frame: frame)
79 | }
80 | }
81 |
82 | }
83 |
84 |
85 | ////////////////////////////////////////////////////////////////////////////////
86 |
87 |
88 | private extension Selector {
89 | static let dismiss = #selector(KeyboardDismissTextField.dismiss(_:))
90 | }
91 |
--------------------------------------------------------------------------------
/ICInputAccessory.xcodeproj/xcshareddata/xcschemes/Example.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
42 |
48 |
49 |
50 |
51 |
52 |
62 |
64 |
70 |
71 |
72 |
73 |
79 |
81 |
87 |
88 |
89 |
90 |
92 |
93 |
96 |
97 |
98 |
--------------------------------------------------------------------------------
/Source/OptionPickerControl/OptionPickerControl.swift:
--------------------------------------------------------------------------------
1 | //
2 | // OptionPickerControl.swift
3 | // ICInputAccessory
4 | //
5 | // Created by Ben on 27/11/2017.
6 | // Copyright © 2017 bcylin.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 |
27 | import UIKit
28 |
29 | /// A `UIControl` that displays a `UIPickerView` and notifies changed selection and via `UIControlEvents` `.valueChanged`.
30 | open class OptionPickerControl: UIControl, UIPickerViewDataSource, UIPickerViewDelegate {
31 |
32 | // MARK: - Initialization
33 |
34 | /// Returns an initialized `OptionPickerControl`.
35 | public init() {
36 | super.init(frame: .zero)
37 | addSubview(hiddenTextField)
38 | }
39 |
40 | /// Not supported. `OptionPickerControl` is not compatible with storyboards.
41 | required public init?(coder aDecoder: NSCoder) {
42 | fatalError("init(coder:) is not supported")
43 | }
44 |
45 | // MARK: - Properties
46 |
47 | /// Options that shows in the `UIPickerView`.
48 | public var options: [Option] = [.optional]
49 |
50 | /// The currently selected item in the options.
51 | public var selectedOption: Option = .optional {
52 | didSet {
53 | if hiddenTextField.isFirstResponder {
54 | sendActions(for: .valueChanged)
55 | } else if let index = options.firstIndex(of: selectedOption) {
56 | picker.selectRow(index, inComponent: 0, animated: false)
57 | }
58 | }
59 | }
60 |
61 | /// A reference to the displayed `UIPickerView` for customization.
62 | public private(set) lazy var picker: UIPickerView = {
63 | let picker = UIPickerView()
64 | picker.dataSource = self
65 | picker.delegate = self
66 | return picker
67 | }()
68 |
69 | // MARK: - Lazy Instantiation
70 |
71 | private lazy var doneBarButton: UIBarButtonItem =
72 | UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(dismissPicker(_:)))
73 |
74 | private lazy var pickerToolbar: UIToolbar = {
75 | let toolbar = UIToolbar(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 44))
76 | toolbar.items = [
77 | UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil),
78 | self.doneBarButton
79 | ]
80 | return toolbar
81 | }()
82 |
83 | private lazy var hiddenTextField: UITextField = {
84 | let textField = UITextField()
85 | textField.inputAccessoryView = self.pickerToolbar
86 | textField.inputView = self.picker
87 | return textField
88 | }()
89 |
90 | // MARK: - UIResponder
91 |
92 | @discardableResult
93 | override open func becomeFirstResponder() -> Bool {
94 | return super.becomeFirstResponder() || hiddenTextField.becomeFirstResponder()
95 | }
96 |
97 | @discardableResult
98 | override open func resignFirstResponder() -> Bool {
99 | return hiddenTextField.resignFirstResponder()
100 | }
101 |
102 | // MARK: - UIPickerViewDataSource
103 |
104 | /// Currently `OptionPickerControl` only supports one component.
105 | open func numberOfComponents(in pickerView: UIPickerView) -> Int {
106 | return 1
107 | }
108 |
109 | open func pickerView(_ pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int {
110 | return options.count
111 | }
112 |
113 | // MARK: - UIPickerViewDelegate
114 |
115 | open func pickerView(_ pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? {
116 | return options[row].title
117 | }
118 |
119 | open func pickerView(_ pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) {
120 | selectedOption = options[row]
121 | }
122 |
123 | // MARK: - IBActions
124 |
125 | @objc private func dismissPicker(_ sender: Any) {
126 | resignFirstResponder()
127 | }
128 |
129 | }
130 |
--------------------------------------------------------------------------------
/Source/KeyboardDismissTextField/KeyboardDismissAccessoryView.swift:
--------------------------------------------------------------------------------
1 | //
2 | // KeyboardDismissAccessoryView.swift
3 | // iCook
4 | //
5 | // Created by Ben on 27/08/2015.
6 | // Copyright (c) 2015 Polydice, Inc.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 |
27 | import UIKit
28 |
29 | /// A customized keyboard accessory view with a dismiss button.
30 | @IBDesignable
31 | open class KeyboardDismissAccessoryView: UIView {
32 |
33 | /// The background color of the button to dismiss keyboard.
34 | @IBInspectable public var buttonColor: UIColor = Constants.ButtonColor {
35 | didSet {
36 | dismissButton.backgroundColor = buttonColor
37 | }
38 | }
39 |
40 | /// The button to dismiss keyboard.
41 | public private(set) lazy var dismissButton: UIButton = {
42 | let _button = UIButton()
43 | let resources = Bundle(for: type(of: self))
44 | let icon = UIImage(named: "icook-iphone-button-hide-keyboard", in: resources, compatibleWith: nil)
45 | _button.setImage(icon, for: UIControl.State())
46 | _button.backgroundColor = Constants.ButtonColor
47 | _button.isExclusiveTouch = true
48 | _button.layer.cornerRadius = 4
49 | _button.layer.shouldRasterize = true
50 | _button.layer.rasterizationScale = UIScreen.main.scale
51 | _button.accessibilityLabel = "Dismiss Keyboard"
52 | return _button
53 | }()
54 |
55 | private struct Constants {
56 | static let ButtonColor = UIColor(red: 0.21, green: 0.2, blue: 0.19, alpha: 0.5)
57 | static let EdgePadding = CGFloat(7)
58 | static let InteractiveSize = CGSize(width: 44, height: 44)
59 | }
60 |
61 | // MARK: - Initialization
62 |
63 | /// Initializes and returns a newly allocated view object with the specified frame rectangle.
64 | public override init(frame: CGRect) {
65 | super.init(frame: frame)
66 | setUpSubviews()
67 | }
68 |
69 | /// Returns an object initialized from data in a given unarchiver.
70 | public required init?(coder aDecoder: NSCoder) {
71 | super.init(coder: aDecoder)
72 | setUpSubviews()
73 | }
74 |
75 | // MARK: - UIView
76 |
77 | open override func point(inside point: CGPoint, with event: UIEvent?) -> Bool {
78 | for subview in subviews {
79 | if !subview.isHidden && subview.alpha > 0 &&
80 | subview.isUserInteractionEnabled &&
81 | subview.point(inside: convert(point, to: subview), with: event) {
82 | return true
83 | }
84 | }
85 | return false
86 | }
87 |
88 | // MARK: - NSKeyValueCoding
89 |
90 | open override func setValue(_ value: Any?, forKey key: String) {
91 | if let color = value as? UIColor, key == "buttonColor" {
92 | buttonColor = color
93 | }
94 | }
95 |
96 | // MARK: - Private Methods
97 |
98 | private func setUpSubviews() {
99 | backgroundColor = UIColor.clear
100 |
101 | addSubview(dismissButton)
102 | dismissButton.translatesAutoresizingMaskIntoConstraints = false
103 |
104 | let views = ["button": dismissButton]
105 | let metrics = [
106 | "width": Constants.InteractiveSize.width,
107 | "height": Constants.InteractiveSize.height,
108 | "padding": Constants.EdgePadding
109 | ]
110 |
111 | addConstraints(NSLayoutConstraint.constraints(
112 | withVisualFormat: "H:[button(width)]-(padding)-|",
113 | options: [],
114 | metrics: metrics,
115 | views: views
116 | ))
117 | addConstraints(NSLayoutConstraint.constraints(
118 | withVisualFormat: "V:[button(height)]-(padding)-|",
119 | options: [],
120 | metrics: metrics,
121 | views: views
122 | ))
123 | }
124 |
125 | // MARK: - Internal Methods
126 |
127 | class func requiredHeight() -> CGFloat {
128 | return Constants.InteractiveSize.height + Constants.EdgePadding * 2
129 | }
130 |
131 | }
132 |
--------------------------------------------------------------------------------
/Source/TokenField/Token.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Token.swift
3 | // iCook
4 | //
5 | // Created by Ben on 03/03/2016.
6 | // Copyright © 2016 Polydice, Inc.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 |
27 | import UIKit
28 |
29 | internal class Token: UIView {
30 |
31 | var text = "" {
32 | didSet {
33 | updateTextLabel()
34 | frame = CGRect(origin: CGPoint.zero, size: systemLayoutSizeFitting(UIView.layoutFittingCompressedSize))
35 | }
36 | }
37 |
38 | var isHighlighted = false {
39 | didSet {
40 | updateTextLabel()
41 | }
42 | }
43 |
44 | var normalTextAttributes: [NSAttributedString.Key: NSObject] = [
45 | .foregroundColor: UIColor(red: 0.14, green: 0.38, blue: 0.95, alpha: 1),
46 | .backgroundColor: UIColor.clear
47 | ] {
48 | didSet {
49 | if !isHighlighted { updateTextLabel() }
50 | delimiterLabel.textColor = self.normalTextAttributes[.foregroundColor] as? UIColor
51 | }
52 | }
53 |
54 | var highlightedTextAttributes: [NSAttributedString.Key: NSObject] = [
55 | .foregroundColor: UIColor.white,
56 | .backgroundColor: UIColor(red: 0.14, green: 0.38, blue: 0.95, alpha: 1)
57 | ] {
58 | didSet {
59 | if isHighlighted { updateTextLabel() }
60 | }
61 | }
62 |
63 | // MARK: - Private Properties
64 |
65 | private(set) lazy var delimiterLabel: UILabel = {
66 | let _label = UILabel()
67 | _label.textColor = self.normalTextAttributes[.foregroundColor] as? UIColor
68 | _label.textAlignment = .right
69 | return _label
70 | }()
71 |
72 | private(set) lazy var textLabel: UILabel = {
73 | let _label = InsetLabel(contentEdgeInsets: UIEdgeInsets(top: 3, left: 5, bottom: 3, right: 5), cornerRadius: .constant(3))
74 | _label.textAlignment = .center
75 | _label.textColor = self.normalTextAttributes[.foregroundColor] as? UIColor
76 | _label.backgroundColor = self.normalTextAttributes[.backgroundColor] as? UIColor
77 | _label.numberOfLines = 1
78 | return _label
79 | }()
80 |
81 | // MARK: - Initialization
82 |
83 | override init(frame: CGRect) {
84 | super.init(frame: frame)
85 | setUpSubviews()
86 | }
87 |
88 | required init?(coder aDecoder: NSCoder) {
89 | super.init(coder: aDecoder)
90 | setUpSubviews()
91 | }
92 |
93 | convenience init(
94 | text: String,
95 | delimiter: String = ",",
96 | normalAttributes: [NSAttributedString.Key: NSObject]? = nil,
97 | highlightedAttributes: [NSAttributedString.Key: NSObject]? = nil
98 | ) {
99 | self.init()
100 | if let attributes = normalAttributes { normalTextAttributes = attributes }
101 | if let attributes = highlightedAttributes { highlightedTextAttributes = attributes }
102 | delimiterLabel.text = delimiter
103 | ({
104 | // Workaround to trigger didSet inside the initializer
105 | self.text = text
106 | })()
107 | }
108 |
109 | // MARK: - Private Methods
110 |
111 | private func updateTextLabel() {
112 | var attributes = isHighlighted ? highlightedTextAttributes : normalTextAttributes
113 | if let color = attributes[.backgroundColor] as? UIColor {
114 | textLabel.backgroundColor = color
115 | }
116 | // Avoid overlapped translucent background colors
117 | attributes[.backgroundColor] = nil
118 | textLabel.attributedText = NSAttributedString(string: text, attributes: attributes)
119 |
120 | delimiterLabel.textColor = normalTextAttributes[.foregroundColor] as? UIColor
121 | delimiterLabel.font = normalTextAttributes[.font] as? UIFont
122 | }
123 |
124 | private func setUpSubviews() {
125 | addSubview(textLabel)
126 | addSubview(delimiterLabel)
127 | textLabel.translatesAutoresizingMaskIntoConstraints = false
128 | delimiterLabel.translatesAutoresizingMaskIntoConstraints = false
129 |
130 | let views = [
131 | "text": textLabel,
132 | "delimiter": delimiterLabel
133 | ]
134 | addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[text][delimiter]-5-|",
135 | options: [.alignAllCenterY],
136 | metrics: nil,
137 | views: views
138 | ))
139 | addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-2-[text]-2-|",
140 | options: [],
141 | metrics: nil,
142 | views: views
143 | ))
144 | }
145 |
146 | }
147 |
--------------------------------------------------------------------------------
/docs/css/highlight.css:
--------------------------------------------------------------------------------
1 | /* Credit to https://gist.github.com/wataru420/2048287 */
2 | .highlight {
3 | /* Comment */
4 | /* Error */
5 | /* Keyword */
6 | /* Operator */
7 | /* Comment.Multiline */
8 | /* Comment.Preproc */
9 | /* Comment.Single */
10 | /* Comment.Special */
11 | /* Generic.Deleted */
12 | /* Generic.Deleted.Specific */
13 | /* Generic.Emph */
14 | /* Generic.Error */
15 | /* Generic.Heading */
16 | /* Generic.Inserted */
17 | /* Generic.Inserted.Specific */
18 | /* Generic.Output */
19 | /* Generic.Prompt */
20 | /* Generic.Strong */
21 | /* Generic.Subheading */
22 | /* Generic.Traceback */
23 | /* Keyword.Constant */
24 | /* Keyword.Declaration */
25 | /* Keyword.Pseudo */
26 | /* Keyword.Reserved */
27 | /* Keyword.Type */
28 | /* Literal.Number */
29 | /* Literal.String */
30 | /* Name.Attribute */
31 | /* Name.Builtin */
32 | /* Name.Class */
33 | /* Name.Constant */
34 | /* Name.Entity */
35 | /* Name.Exception */
36 | /* Name.Function */
37 | /* Name.Namespace */
38 | /* Name.Tag */
39 | /* Name.Variable */
40 | /* Operator.Word */
41 | /* Text.Whitespace */
42 | /* Literal.Number.Float */
43 | /* Literal.Number.Hex */
44 | /* Literal.Number.Integer */
45 | /* Literal.Number.Oct */
46 | /* Literal.String.Backtick */
47 | /* Literal.String.Char */
48 | /* Literal.String.Doc */
49 | /* Literal.String.Double */
50 | /* Literal.String.Escape */
51 | /* Literal.String.Heredoc */
52 | /* Literal.String.Interpol */
53 | /* Literal.String.Other */
54 | /* Literal.String.Regex */
55 | /* Literal.String.Single */
56 | /* Literal.String.Symbol */
57 | /* Name.Builtin.Pseudo */
58 | /* Name.Variable.Class */
59 | /* Name.Variable.Global */
60 | /* Name.Variable.Instance */
61 | /* Literal.Number.Integer.Long */ }
62 | .highlight .c {
63 | color: #999988;
64 | font-style: italic; }
65 | .highlight .err {
66 | color: #a61717;
67 | background-color: #e3d2d2; }
68 | .highlight .k {
69 | color: #000000;
70 | font-weight: bold; }
71 | .highlight .o {
72 | color: #000000;
73 | font-weight: bold; }
74 | .highlight .cm {
75 | color: #999988;
76 | font-style: italic; }
77 | .highlight .cp {
78 | color: #999999;
79 | font-weight: bold; }
80 | .highlight .c1 {
81 | color: #999988;
82 | font-style: italic; }
83 | .highlight .cs {
84 | color: #999999;
85 | font-weight: bold;
86 | font-style: italic; }
87 | .highlight .gd {
88 | color: #000000;
89 | background-color: #ffdddd; }
90 | .highlight .gd .x {
91 | color: #000000;
92 | background-color: #ffaaaa; }
93 | .highlight .ge {
94 | color: #000000;
95 | font-style: italic; }
96 | .highlight .gr {
97 | color: #aa0000; }
98 | .highlight .gh {
99 | color: #999999; }
100 | .highlight .gi {
101 | color: #000000;
102 | background-color: #ddffdd; }
103 | .highlight .gi .x {
104 | color: #000000;
105 | background-color: #aaffaa; }
106 | .highlight .go {
107 | color: #888888; }
108 | .highlight .gp {
109 | color: #555555; }
110 | .highlight .gs {
111 | font-weight: bold; }
112 | .highlight .gu {
113 | color: #aaaaaa; }
114 | .highlight .gt {
115 | color: #aa0000; }
116 | .highlight .kc {
117 | color: #000000;
118 | font-weight: bold; }
119 | .highlight .kd {
120 | color: #000000;
121 | font-weight: bold; }
122 | .highlight .kp {
123 | color: #000000;
124 | font-weight: bold; }
125 | .highlight .kr {
126 | color: #000000;
127 | font-weight: bold; }
128 | .highlight .kt {
129 | color: #445588; }
130 | .highlight .m {
131 | color: #009999; }
132 | .highlight .s {
133 | color: #d14; }
134 | .highlight .na {
135 | color: #008080; }
136 | .highlight .nb {
137 | color: #0086B3; }
138 | .highlight .nc {
139 | color: #445588;
140 | font-weight: bold; }
141 | .highlight .no {
142 | color: #008080; }
143 | .highlight .ni {
144 | color: #800080; }
145 | .highlight .ne {
146 | color: #990000;
147 | font-weight: bold; }
148 | .highlight .nf {
149 | color: #990000; }
150 | .highlight .nn {
151 | color: #555555; }
152 | .highlight .nt {
153 | color: #000080; }
154 | .highlight .nv {
155 | color: #008080; }
156 | .highlight .ow {
157 | color: #000000;
158 | font-weight: bold; }
159 | .highlight .w {
160 | color: #bbbbbb; }
161 | .highlight .mf {
162 | color: #009999; }
163 | .highlight .mh {
164 | color: #009999; }
165 | .highlight .mi {
166 | color: #009999; }
167 | .highlight .mo {
168 | color: #009999; }
169 | .highlight .sb {
170 | color: #d14; }
171 | .highlight .sc {
172 | color: #d14; }
173 | .highlight .sd {
174 | color: #d14; }
175 | .highlight .s2 {
176 | color: #d14; }
177 | .highlight .se {
178 | color: #d14; }
179 | .highlight .sh {
180 | color: #d14; }
181 | .highlight .si {
182 | color: #d14; }
183 | .highlight .sx {
184 | color: #d14; }
185 | .highlight .sr {
186 | color: #009926; }
187 | .highlight .s1 {
188 | color: #d14; }
189 | .highlight .ss {
190 | color: #990073; }
191 | .highlight .bp {
192 | color: #999999; }
193 | .highlight .vc {
194 | color: #008080; }
195 | .highlight .vg {
196 | color: #008080; }
197 | .highlight .vi {
198 | color: #008080; }
199 | .highlight .il {
200 | color: #009999; }
201 |
--------------------------------------------------------------------------------
/Example/CustomizedTokenViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // CustomizedTokenViewController.swift
3 | // Example
4 | //
5 | // Created by Ben on 11/03/2016.
6 | // Copyright © 2016 Polydice, Inc.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 |
27 | import UIKit
28 | import ICInputAccessory
29 |
30 | class CustomizedTokenViewController: UIViewController, TokenFieldDelegate {
31 |
32 | private let tokenField = CustomizedTokenField()
33 | private let textView = UITextView()
34 |
35 | // MARK: - UIViewController
36 |
37 | override func loadView() {
38 | super.loadView()
39 | view.backgroundColor = UIColor.white
40 | textView.isEditable = false
41 | textView.isSelectable = false
42 | textView.text = "[\n\n]"
43 | textView.font = UIFont.preferredFont(forTextStyle: .subheadline)
44 | textView.frame = view.bounds.insetBy(dx: 10, dy: 10)
45 | textView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
46 | view.addSubview(textView)
47 | }
48 |
49 | override func viewDidLoad() {
50 | super.viewDidLoad()
51 | navigationController?.navigationBar.barTintColor = UIColor(red: 0.96, green: 0.48, blue: 0.4, alpha: 1)
52 | navigationController?.navigationBar.isTranslucent = false
53 | navigationController?.navigationBar.barStyle = .black
54 |
55 | let cancelBarButton = UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: .dismiss)
56 | cancelBarButton.tintColor = UIColor.white
57 | navigationItem.rightBarButtonItem = cancelBarButton
58 |
59 | navigationItem.titleView = {
60 | if #available(iOS 11, *) {
61 | tokenField.translatesAutoresizingMaskIntoConstraints = false
62 | let views = ["field": tokenField]
63 | let metrics = ["padding": 7]
64 | let containerView = UIView()
65 | containerView.addSubview(tokenField)
66 | containerView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "H:|[field]-padding-|", options: [], metrics: metrics, views: views))
67 | containerView.addConstraints(NSLayoutConstraint.constraints(withVisualFormat: "V:|-padding-[field]-padding-|", options: [], metrics: metrics, views: views))
68 | return containerView
69 | } else {
70 | return tokenField
71 | }
72 | }()
73 | tokenField.delegate = self
74 | }
75 |
76 | override func viewWillAppear(_ animated: Bool) {
77 | super.viewWillAppear(animated)
78 | _ = tokenField.becomeFirstResponder()
79 | }
80 |
81 | override func viewWillDisappear(_ animated: Bool) {
82 | super.viewWillAppear(animated)
83 | _ = tokenField.resignFirstResponder()
84 | textView.endEditing(true)
85 | }
86 |
87 | // MARK: - TokenFieldDelegate
88 |
89 | func tokenFieldDidBeginEditing(_ tokenField: TokenField) {
90 | print(#function)
91 | }
92 |
93 | func tokenFieldDidEndEditing(_ tokenField: TokenField) {
94 | print(#function)
95 | }
96 |
97 | func tokenFieldWillReturn(_ tokenField: TokenField) {
98 | print(#function)
99 | }
100 |
101 | func tokenField(_ tokenField: TokenField, didChangeInputText text: String) {
102 | print("Typing \"\(text)\"")
103 | }
104 |
105 | func tokenField(_ tokenField: TokenField, shouldCompleteText text: String) -> Bool {
106 | print("Should add \"\(text)\"?")
107 | return text != "42"
108 | }
109 |
110 | func tokenField(_ tokenField: TokenField, didCompleteText text: String) {
111 | print("Added \"\(text)\"")
112 | updateTexts()
113 | }
114 |
115 | func tokenField(_ tokenField: TokenField, didDeleteText text: String, atIndex index: Int) {
116 | print("Deleted \"\(text)\"")
117 | updateTexts()
118 | }
119 |
120 | func tokenField(_ tokenField: TokenField, subsequentDelimiterForCompletedText text: String) -> String {
121 | return " ,"
122 | }
123 |
124 | // MARK: - UIResponder Callbacks
125 |
126 | @objc fileprivate func dismiss(_ sender: UIBarButtonItem) {
127 | presentingViewController?.dismiss(animated: true, completion: nil)
128 | }
129 |
130 | // MARK: - Private Methods
131 |
132 | private func updateTexts() {
133 | let tokens = tokenField.texts.map { "\"" + $0 + "\"" } .joined(separator: ",\n ")
134 | textView.text = "[\n " + tokens + "\n]"
135 | }
136 |
137 | }
138 |
139 |
140 | ////////////////////////////////////////////////////////////////////////////////
141 |
142 |
143 | private extension Selector {
144 | static let dismiss = #selector(CustomizedTokenViewController.dismiss(_:))
145 | }
146 |
--------------------------------------------------------------------------------
/docs/Structs.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Structures Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
34 |
35 |
41 |
42 |
43 |
44 |
45 | ICInputAccessory Reference
46 |
47 | Structures Reference
48 |
49 |
50 |
51 |
52 |
90 |
91 |
92 |
93 |
94 |
95 |
Structures
96 |
The following structures are available globally.
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 | Option
111 |
112 |
113 |
114 |
115 |
116 |
117 |
122 |
123 |
Declaration
124 |
125 |
Swift
126 |
public struct Option < T > : Equatable where T : OptionDescriptive
127 |
128 |
129 |
130 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
147 |
148 |
149 |
150 |
--------------------------------------------------------------------------------
/Example/ExampleViewController.swift:
--------------------------------------------------------------------------------
1 | //
2 | // ExampleViewController.swift
3 | // Example
4 | //
5 | // Created by Ben on 07/03/2016.
6 | // Copyright © 2016 Polydice, Inc.
7 | //
8 | // Permission is hereby granted, free of charge, to any person obtaining a copy
9 | // of this software and associated documentation files (the "Software"), to deal
10 | // in the Software without restriction, including without limitation the rights
11 | // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12 | // copies of the Software, and to permit persons to whom the Software is
13 | // furnished to do so, subject to the following conditions:
14 | //
15 | // The above copyright notice and this permission notice shall be included in all
16 | // copies or substantial portions of the Software.
17 | //
18 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19 | // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20 | // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21 | // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22 | // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23 | // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
24 | // SOFTWARE.
25 | //
26 |
27 | import UIKit
28 | import ICInputAccessory
29 |
30 | class ExampleViewController: UITableViewController {
31 |
32 | private let showcases: [UIView.Type] = [
33 | KeyboardDismissTextField.self,
34 | TokenField.self,
35 | CustomizedTokenField.self,
36 | OptionPickerControl.self
37 | ]
38 |
39 | private lazy var languagePicker: OptionPickerControl = {
40 | let picker = OptionPickerControl()
41 | picker.options += Language.availableLanguages.map(Option.init(_:))
42 | picker.addTarget(self, action: .updateLanguage, for: .valueChanged)
43 | return picker
44 | }()
45 |
46 | private lazy var flipButton: UIButton = {
47 | let _button = UIButton(type: .system)
48 | _button.frame = CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: 88)
49 | _button.setTitle("Storyboard", for: UIControl.State())
50 | _button.addTarget(self, action: .showStoryboard, for: .touchUpInside)
51 | return _button
52 | }()
53 |
54 | // MARK: - Initialization
55 |
56 | convenience init() {
57 | self.init(style: .grouped)
58 | title = "ICInputAccessory"
59 | }
60 |
61 | // MARK: - UIViewController
62 |
63 | override func viewDidLoad() {
64 | super.viewDidLoad()
65 | tableView.rowHeight = 44
66 | tableView.register(ExampleCell.self, forCellReuseIdentifier: String(describing: ExampleCell.self))
67 | tableView.tableFooterView = flipButton
68 | tableView.tableFooterView?.isUserInteractionEnabled = true
69 | view.addSubview(languagePicker)
70 | }
71 |
72 | // MARK: - UITableViewDataSource
73 |
74 | override func numberOfSections(in tableView: UITableView) -> Int {
75 | return showcases.count
76 | }
77 |
78 | override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
79 | return 1
80 | }
81 |
82 | override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
83 | switch showcases[section] {
84 | case is KeyboardDismissTextField.Type:
85 | return "Dismiss Keyboard"
86 | case is TokenField.Type:
87 | return "Text Field with Tokens"
88 | case is CustomizedTokenField.Type:
89 | return "Customize Token Field"
90 | case is OptionPickerControl.Type:
91 | return "Option Picker Control"
92 | default:
93 | return ""
94 | }
95 | }
96 |
97 | override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
98 | let cell = tableView.dequeueReusableCell(withIdentifier: String(describing: ExampleCell.self), for: indexPath)
99 | cell.accessoryType = .none
100 |
101 | switch showcases[indexPath.section] {
102 | case let type as KeyboardDismissTextField.Type:
103 | let textField = type.init()
104 | textField.leftViewMode = .always
105 | textField.leftView = UIView(frame: CGRect(x: 0, y: 0, width: 15, height: 15))
106 | textField.placeholder = String(describing: type)
107 | (cell as? ExampleCell)?.showcase = textField
108 |
109 | case let type as CustomizedTokenField.Type:
110 | cell.textLabel?.text = String(describing: type)
111 | cell.accessoryType = .disclosureIndicator
112 |
113 | case let type as TokenField.Type:
114 | let container = UIView(frame: cell.bounds)
115 | let tokenField = type.init()
116 | tokenField.placeholder = String(describing: type)
117 | tokenField.frame = container.bounds.insetBy(dx: 5, dy: 0)
118 | tokenField.autoresizingMask = [.flexibleWidth, .flexibleHeight]
119 | container.addSubview(tokenField)
120 | (cell as? ExampleCell)?.showcase = container
121 |
122 | case is OptionPickerControl.Type:
123 | (cell as? ExampleCell)?.showcase = nil
124 | cell.textLabel?.text = languagePicker.selectedOption.title
125 | cell.accessoryType = .disclosureIndicator
126 |
127 | default:
128 | break
129 | }
130 | return cell
131 | }
132 |
133 | // MARK: - UITableViewDelegate
134 |
135 | override func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
136 | switch showcases[indexPath.section] {
137 | case is CustomizedTokenField.Type:
138 | return true
139 | case is OptionPickerControl.Type:
140 | return true
141 | default:
142 | return false
143 | }
144 | }
145 |
146 | override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
147 | switch showcases[indexPath.section] {
148 | case is CustomizedTokenField.Type:
149 | let controller = UINavigationController(rootViewController: CustomizedTokenViewController())
150 | controller.modalPresentationStyle = .fullScreen
151 | present(controller, animated: true, completion: nil)
152 | case is OptionPickerControl.Type:
153 | tableView.deselectRow(at: indexPath, animated: true)
154 | languagePicker.becomeFirstResponder()
155 | default:
156 | break
157 | }
158 | }
159 |
160 | // MARK: - UIResponder Callbacks
161 |
162 | @objc fileprivate func showStoryboard(_ sender: UIButton) {
163 | if let controller = UIStoryboard(name: "Main", bundle: Bundle.main).instantiateInitialViewController() {
164 | controller.modalPresentationStyle = .fullScreen
165 | controller.modalTransitionStyle = .flipHorizontal
166 | present(controller, animated: true, completion: nil)
167 | }
168 | }
169 |
170 | @objc fileprivate func updateLanguage(_ sender: UIControl) {
171 | tableView.reloadData()
172 | }
173 |
174 | }
175 |
176 |
177 | ////////////////////////////////////////////////////////////////////////////////
178 |
179 |
180 | private extension Selector {
181 | static let showStoryboard = #selector(ExampleViewController.showStoryboard(_:))
182 | static let updateLanguage = #selector(ExampleViewController.updateLanguage(_:))
183 | }
184 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # ICInputAccessory
2 |
3 | Customized text fields used in the [iCook app](https://itunes.apple.com/app/id554065086).
4 |
5 | 
6 | [](https://github.com/Carthage/Carthage)
7 | [](https://cocoapods.org/pods/ICInputAccessory)
8 | 
9 | 
10 |
11 | ### KeyboardDismissTextField
12 |
13 | * A text field that has a button to dismiss keyboard on the input accessory view.
14 |
15 | ### TokenField
16 |
17 | * A horizontal scrolling UI that groups input texts.
18 | * Easy to add, select and delete tokens.
19 | * Customizable icon and colors.
20 | * Supports storyboard.
21 |
22 | 
23 |
24 | ### OptionPickerControl
25 |
26 | * An easy to use `UIControl` that displays a `UIPickerView` with given options.
27 |
28 | ## Requirements
29 |
30 | ICInputAccessory | iOS | Xcode | Swift
31 | ---------------- | :--: | :---: | -----
32 | `~> 1.0.0` | 8.0+ | 7.2 | 
33 | `~> 1.1.0` | 8.0+ | 7.3 | 
34 | `~> 1.2.0` | 8.0+ | 8.0 | 
35 | `~> 1.3.0` | 8.0+ | 8.0 | 
36 | `~> 1.4.0` | 8.0+ | 8.3 | 
37 | `~> 1.5.0` | 8.0+ | 9.3 | 
38 | `~> 2.0.0` | 8.0+ | 10.0 | 
39 | `develop` | 8.0+ | 11.1 | 
40 |
41 | ## Installation
42 |
43 | ### Use [Carthage](https://github.com/Carthage/Carthage)
44 |
45 | Create a `Cartfile` with the following specification and run `carthage update ICInputAccessory`. Follow the [instructions](https://github.com/Carthage/Carthage#if-youre-building-for-ios) to add the framework to an iOS project.
46 |
47 | ```
48 | github "polydice/ICInputAccessory"
49 | ```
50 |
51 | ### Use [CocoaPods](http://guides.cocoapods.org/)
52 |
53 | **ICInputAccessory** supports subspecs. Create a `Podfile` with the following specification and run `pod install`.
54 |
55 | ```rb
56 | platform :ios, '8.0'
57 | use_frameworks!
58 |
59 | pod 'ICInputAccessory/TokenField'
60 | pod 'ICInputAccessory/KeyboardDismissTextField'
61 | ```
62 |
63 | ### Use Git Submodule
64 |
65 | ```
66 | git submodule add -b master git@github.com:polydice/ICInputAccessory.git Dependencies/ICInputAccessory
67 | ```
68 |
69 | * Everything you need resides in the `Source` directory. Add those files to your project.
70 | * Alternatively, drag **ICInputAccessory.xcodeproj** to your app project as a subproject. Add **ICInputAccessory-iOS** to the **Target Dependencies** in the application target's **Build Phases** settings.
71 |
72 | ## Usage
73 |
74 | ### KeyboardDismissTextField
75 |
76 | ```swift
77 | let textField = KeyboardDismissTextField(frame: rect)
78 | ```
79 |
80 | ### TokenField
81 |
82 | ```swift
83 | let tokenField = TokenField(frame: rect)
84 | tokenField.delegate = self as? TokenFieldDelegate
85 | ```
86 |
87 | The characters that complete a token:
88 |
89 | ```swift
90 | /// Characters that complete a new token, defaults are whitespace and commas.
91 | public var delimiters: [String]
92 | ```
93 |
94 | Tokens:
95 |
96 | ```swift
97 | /// Texts of each created token.
98 | public var texts: [String] { get }
99 |
100 | /// Creates a token with the current input text.
101 | public func completeCurrentInputText()
102 |
103 | /// Removes the input text and all displayed tokens.
104 | public func resetTokens()
105 | ```
106 |
107 | UI customization:
108 |
109 | ```swift
110 | /// The image on the left of text field.
111 | public var icon: UIImage? { get set }
112 |
113 | /// The placeholder with the default color and font.
114 | public var placeholder: String? { get set }
115 |
116 | /// The placeholder with customized attributes.
117 | public var attributedPlaceholder: NSAttributedString? { get set }
118 |
119 | /// Customized attributes for tokens in the normal state, e.g. .font and .foregroundColor.
120 | public var normalTokenAttributes: [NSAttributedStringKey : NSObject]? { get set }
121 |
122 | /// Customized attributes for tokens in the highlighted state.
123 | public var highlightedTokenAttributes: [NSAttributedStringKey : NSObject]? { get set }
124 | ```
125 |
126 | Customizable properties in storyboard:
127 |
128 | ```swift
129 | @IBInspectable var icon: UIImage?
130 | @IBInspectable var placeholder: String?
131 | @IBInspectable var textColor: UIColor?
132 | @IBInspectable var cornerRadius: CGFloat
133 | ```
134 |
135 | See `Example/CustomizedTokenField.swift` for more details.
136 |
137 | #### TokenFieldDelegate
138 |
139 | `TokenField` currently notifies its delegate the following events:
140 |
141 | ```swift
142 | @objc optional func tokenFieldDidBeginEditing(_ tokenField: TokenField)
143 | @objc optional func tokenFieldDidEndEditing(_ tokenField: TokenField)
144 | @objc optional func tokenFieldWillReturn(_ tokenField: TokenField)
145 | @objc optional func tokenField(_ tokenField: TokenField, didChangeInputText text: String)
146 | @objc optional func tokenField(_ tokenField: TokenField, shouldCompleteText text: String) -> Bool
147 | @objc optional func tokenField(_ tokenField: TokenField, didCompleteText text: String)
148 | @objc optional func tokenField(_ tokenField: TokenField, didDeleteText text: String, atIndex index: Int)
149 | ```
150 |
151 | The displayed delimiter string can be customized by:
152 |
153 | ```swift
154 | @objc optional func tokenField(_ tokenField: TokenField, subsequentDelimiterForCompletedText text: String) -> String
155 | ```
156 |
157 | ### OptionPickerControl
158 |
159 | An example type that conforms to `OptionDescriptive`:
160 |
161 | ```swift
162 | extension String: OptionDescriptive {
163 |
164 | var title: String {
165 | return self
166 | }
167 |
168 | static var titleForOptionalValue: String {
169 | return "(optional)"
170 | }
171 |
172 | }
173 | ```
174 |
175 | To initialize `OptionPickerControl` with `CGRect.zero` and add it to the view hierarchy:
176 |
177 | ```swift
178 | let optionPicker = OptionPickerControl()
179 | optionPicker.options = [.optional, Option("Option 1"), Option("Option 2")]
180 | optionPicker.addTarget(self, action: #selector(didChangeOption(_:)), for: .valueChanged)
181 | view.addSubview(optionPicker)
182 | ```
183 |
184 | To show the `UIPickerView`:
185 |
186 | ```swift
187 | optionPicker.becomeFirstResponder()
188 | ```
189 |
190 | ### Documentation
191 |
192 | * [ICInputAccessory Reference](https://polydice.github.io/ICInputAccessory)
193 | * [Example Project](https://github.com/polydice/ICInputAccessory/tree/develop/Example)
194 |
195 | ## Development
196 |
197 | * Set up dependencies by running the following command in the project root:
198 |
199 | ```
200 | make bootstrap
201 | ```
202 |
203 | * Open **ICInputAccessory.xcworkspace** and run the demo app with the `Example` scheme.
204 |
205 | * See more tasks for building and testing:
206 |
207 | ```
208 | rake -T
209 | ```
210 |
211 | ## Contributing
212 |
213 | Thank you for being interested in contributing to this project. We'd love to hear your ideas!
214 |
215 | Please fork this repository, create a branch named like `feature/some-new-feature` and send us a pull request to make this project better.
216 |
217 | ## Contact
218 |
219 | [](https://twitter.com/polydice)
220 | [](https://gitter.im/polydice/ICInputAccessory)
221 |
222 | ## License
223 |
224 | Copyright (c) 2016 [Polydice, Inc.](https://polydice.com)
225 |
226 | **ICInputAccessory** is released under the MIT license. See [LICENSE](https://github.com/polydice/ICInputAccessory/blob/master/LICENSE) for details.
227 |
--------------------------------------------------------------------------------
/docs/Protocols.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Protocols Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
43 |
44 |
45 | ICInputAccessory Reference
46 |
47 | Protocols Reference
48 |
49 |
50 |
51 |
52 |
90 |
91 |
92 |
93 |
94 |
95 |
Protocols
96 |
The following protocols are available globally.
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
113 |
114 |
115 |
116 |
117 |
118 |
The protocol defines the required variables to be displayed in a UIPickerView via OptionPickerControl .
119 |
120 |
See more
121 |
122 |
123 |
Declaration
124 |
125 |
Swift
126 |
public protocol OptionDescriptive : Equatable
127 |
128 |
129 |
130 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
148 |
149 |
150 |
151 |
152 |
153 |
The protocol defines the messages sent to a delegate. All the methods are optional.
154 |
155 |
See more
156 |
157 |
158 |
Declaration
159 |
160 |
Swift
161 |
@objc
162 | public protocol TokenFieldDelegate : NSObjectProtocol
163 |
164 |
165 |
166 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
179 |
183 |
184 |
185 |
186 |
--------------------------------------------------------------------------------
/docs/css/jazzy.css:
--------------------------------------------------------------------------------
1 | *, *:before, *:after {
2 | box-sizing: inherit; }
3 |
4 | body {
5 | margin: 0;
6 | background: #fff;
7 | color: #333;
8 | font: 16px/1.7 "Helvetica Neue", Helvetica, Arial, sans-serif;
9 | letter-spacing: .2px;
10 | -webkit-font-smoothing: antialiased;
11 | box-sizing: border-box; }
12 |
13 | h1 {
14 | font-size: 2rem;
15 | font-weight: 700;
16 | margin: 1.275em 0 0.6em; }
17 |
18 | h2 {
19 | font-size: 1.75rem;
20 | font-weight: 700;
21 | margin: 1.275em 0 0.3em; }
22 |
23 | h3 {
24 | font-size: 1.5rem;
25 | font-weight: 700;
26 | margin: 1em 0 0.3em; }
27 |
28 | h4 {
29 | font-size: 1.25rem;
30 | font-weight: 700;
31 | margin: 1.275em 0 0.85em; }
32 |
33 | h5 {
34 | font-size: 1rem;
35 | font-weight: 700;
36 | margin: 1.275em 0 0.85em; }
37 |
38 | h6 {
39 | font-size: 1rem;
40 | font-weight: 700;
41 | margin: 1.275em 0 0.85em;
42 | color: #777; }
43 |
44 | p {
45 | margin: 0 0 1em; }
46 |
47 | ul, ol {
48 | padding: 0 0 0 2em;
49 | margin: 0 0 0.85em; }
50 |
51 | blockquote {
52 | margin: 0 0 0.85em;
53 | padding: 0 15px;
54 | color: #858585;
55 | border-left: 4px solid #e5e5e5; }
56 |
57 | img {
58 | max-width: 100%; }
59 |
60 | a {
61 | color: #4183c4;
62 | text-decoration: none; }
63 | a:hover, a:focus {
64 | outline: 0;
65 | text-decoration: underline; }
66 |
67 | table {
68 | background: #fff;
69 | width: 100%;
70 | border-collapse: collapse;
71 | border-spacing: 0;
72 | overflow: auto;
73 | margin: 0 0 0.85em; }
74 |
75 | tr:nth-child(2n) {
76 | background-color: #fbfbfb; }
77 |
78 | th, td {
79 | padding: 6px 13px;
80 | border: 1px solid #ddd; }
81 |
82 | pre {
83 | margin: 0 0 1.275em;
84 | padding: .85em 1em;
85 | overflow: auto;
86 | background: #f7f7f7;
87 | font-size: .85em;
88 | font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; }
89 |
90 | code {
91 | font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace; }
92 |
93 | p > code, li > code {
94 | background: #f7f7f7;
95 | padding: .2em; }
96 | p > code:before, p > code:after, li > code:before, li > code:after {
97 | letter-spacing: -.2em;
98 | content: "\00a0"; }
99 |
100 | pre code {
101 | padding: 0;
102 | white-space: pre; }
103 |
104 | .content-wrapper {
105 | display: flex;
106 | flex-direction: column; }
107 | @media (min-width: 768px) {
108 | .content-wrapper {
109 | flex-direction: row; } }
110 |
111 | .header {
112 | display: flex;
113 | padding: 8px;
114 | font-size: 0.875em;
115 | background: #444;
116 | color: #999; }
117 |
118 | .header-col {
119 | margin: 0;
120 | padding: 0 8px; }
121 |
122 | .header-col--primary {
123 | flex: 1; }
124 |
125 | .header-link {
126 | color: #fff; }
127 |
128 | .header-icon {
129 | padding-right: 6px;
130 | vertical-align: -4px;
131 | height: 16px; }
132 |
133 | .breadcrumbs {
134 | font-size: 0.875em;
135 | padding: 8px 16px;
136 | margin: 0;
137 | background: #fbfbfb;
138 | border-bottom: 1px solid #ddd; }
139 |
140 | .carat {
141 | height: 10px;
142 | margin: 0 5px; }
143 |
144 | .navigation {
145 | order: 2; }
146 | @media (min-width: 768px) {
147 | .navigation {
148 | order: 1;
149 | width: 25%;
150 | max-width: 300px;
151 | padding-bottom: 64px;
152 | overflow: hidden;
153 | word-wrap: normal;
154 | background: #fbfbfb;
155 | border-right: 1px solid #ddd; } }
156 |
157 | .nav-groups {
158 | list-style-type: none;
159 | padding-left: 0; }
160 |
161 | .nav-group-name {
162 | border-bottom: 1px solid #ddd;
163 | padding: 8px 0 8px 16px; }
164 |
165 | .nav-group-name-link {
166 | color: #333; }
167 |
168 | .nav-group-tasks {
169 | margin: 8px 0;
170 | padding: 0 0 0 8px; }
171 |
172 | .nav-group-task {
173 | font-size: 1em;
174 | list-style-type: none;
175 | white-space: nowrap; }
176 |
177 | .nav-group-task-link {
178 | color: #808080; }
179 |
180 | .main-content {
181 | order: 1; }
182 | @media (min-width: 768px) {
183 | .main-content {
184 | order: 2;
185 | flex: 1;
186 | padding-bottom: 60px; } }
187 |
188 | .section {
189 | padding: 0 32px;
190 | border-bottom: 1px solid #ddd; }
191 |
192 | .section-content {
193 | max-width: 834px;
194 | margin: 0 auto;
195 | padding: 16px 0; }
196 |
197 | .section-name {
198 | color: #666;
199 | display: block; }
200 |
201 | .declaration .highlight {
202 | overflow-x: initial;
203 | padding: 8px 0;
204 | margin: 0;
205 | background-color: transparent;
206 | border: none; }
207 |
208 | .task-group-section {
209 | border-top: 1px solid #ddd; }
210 |
211 | .task-group {
212 | padding-top: 0px; }
213 |
214 | .task-name-container a[name]:before {
215 | content: "";
216 | display: block; }
217 |
218 | .item-container {
219 | padding: 0; }
220 |
221 | .item {
222 | padding-top: 8px;
223 | width: 100%;
224 | list-style-type: none; }
225 | .item a[name]:before {
226 | content: "";
227 | display: block; }
228 | .item .token {
229 | padding-left: 3px;
230 | margin-left: 0px;
231 | font-size: 1rem; }
232 | .item .declaration-note {
233 | font-size: .85em;
234 | color: #808080;
235 | font-style: italic; }
236 |
237 | .pointer-container {
238 | border-bottom: 1px solid #ddd;
239 | left: -23px;
240 | padding-bottom: 13px;
241 | position: relative;
242 | width: 110%; }
243 |
244 | .pointer {
245 | left: 21px;
246 | top: 7px;
247 | display: block;
248 | position: absolute;
249 | width: 12px;
250 | height: 12px;
251 | border-left: 1px solid #ddd;
252 | border-top: 1px solid #ddd;
253 | background: #fff;
254 | transform: rotate(45deg); }
255 |
256 | .height-container {
257 | display: none;
258 | position: relative;
259 | width: 100%;
260 | overflow: hidden; }
261 | .height-container .section {
262 | background: #fff;
263 | border: 1px solid #ddd;
264 | border-top-width: 0;
265 | padding-top: 10px;
266 | padding-bottom: 5px;
267 | padding: 8px 16px; }
268 |
269 | .aside, .language {
270 | padding: 6px 12px;
271 | margin: 12px 0;
272 | border-left: 5px solid #dddddd;
273 | overflow-y: hidden; }
274 | .aside .aside-title, .language .aside-title {
275 | font-size: 9px;
276 | letter-spacing: 2px;
277 | text-transform: uppercase;
278 | padding-bottom: 0;
279 | margin: 0;
280 | color: #aaa;
281 | -webkit-user-select: none; }
282 | .aside p:last-child, .language p:last-child {
283 | margin-bottom: 0; }
284 |
285 | .language {
286 | border-left: 5px solid #cde9f4; }
287 | .language .aside-title {
288 | color: #4183c4; }
289 |
290 | .aside-warning {
291 | border-left: 5px solid #ff6666; }
292 | .aside-warning .aside-title {
293 | color: #ff0000; }
294 |
295 | .graybox {
296 | border-collapse: collapse;
297 | width: 100%; }
298 | .graybox p {
299 | margin: 0;
300 | word-break: break-word;
301 | min-width: 50px; }
302 | .graybox td {
303 | border: 1px solid #ddd;
304 | padding: 5px 25px 5px 10px;
305 | vertical-align: middle; }
306 | .graybox tr td:first-of-type {
307 | text-align: right;
308 | padding: 7px;
309 | vertical-align: top;
310 | word-break: normal;
311 | width: 40px; }
312 |
313 | .slightly-smaller {
314 | font-size: 0.9em; }
315 |
316 | .footer {
317 | padding: 8px 16px;
318 | background: #444;
319 | color: #ddd;
320 | font-size: 0.8em; }
321 | .footer p {
322 | margin: 8px 0; }
323 | .footer a {
324 | color: #fff; }
325 |
326 | html.dash .header, html.dash .breadcrumbs, html.dash .navigation {
327 | display: none; }
328 | html.dash .height-container {
329 | display: block; }
330 |
331 | form[role=search] input {
332 | font: 16px/1.7 "Helvetica Neue", Helvetica, Arial, sans-serif;
333 | font-size: 14px;
334 | line-height: 24px;
335 | padding: 0 10px;
336 | margin: 0;
337 | border: none;
338 | border-radius: 1em; }
339 | .loading form[role=search] input {
340 | background: white url(../img/spinner.gif) center right 4px no-repeat; }
341 | form[role=search] .tt-menu {
342 | margin: 0;
343 | min-width: 300px;
344 | background: #fbfbfb;
345 | color: #333;
346 | border: 1px solid #ddd; }
347 | form[role=search] .tt-highlight {
348 | font-weight: bold; }
349 | form[role=search] .tt-suggestion {
350 | font: 16px/1.7 "Helvetica Neue", Helvetica, Arial, sans-serif;
351 | padding: 0 8px; }
352 | form[role=search] .tt-suggestion span {
353 | display: table-cell;
354 | white-space: nowrap; }
355 | form[role=search] .tt-suggestion .doc-parent-name {
356 | width: 100%;
357 | text-align: right;
358 | font-weight: normal;
359 | font-size: 0.9em;
360 | padding-left: 16px; }
361 | form[role=search] .tt-suggestion:hover,
362 | form[role=search] .tt-suggestion.tt-cursor {
363 | cursor: pointer;
364 | background-color: #4183c4;
365 | color: #fff; }
366 | form[role=search] .tt-suggestion:hover .doc-parent-name,
367 | form[role=search] .tt-suggestion.tt-cursor .doc-parent-name {
368 | color: #fff; }
369 |
--------------------------------------------------------------------------------
/docs/Protocols/OptionDescriptive.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | OptionDescriptive Protocol Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
43 |
44 |
45 | ICInputAccessory Reference
46 |
47 | OptionDescriptive Protocol Reference
48 |
49 |
50 |
51 |
52 |
90 |
91 |
92 |
93 |
94 |
95 |
OptionDescriptive
96 |
97 |
98 |
public protocol OptionDescriptive : Equatable
99 |
100 |
101 |
102 |
The protocol defines the required variables to be displayed in a UIPickerView via OptionPickerControl .
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 | title
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
The text for the row in the UIPickerView.
125 |
126 |
127 |
128 |
Declaration
129 |
130 |
Swift
131 |
var title : String { get }
132 |
133 |
134 |
135 |
138 |
139 |
140 |
141 |
142 |
149 |
150 |
151 |
152 |
153 |
154 |
The text for a placeholder row when the picker selection is optional.
155 |
156 |
157 |
158 |
Declaration
159 |
160 |
Swift
161 |
static var titleForOptionalValue : String { get }
162 |
163 |
164 |
165 |
168 |
169 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
182 |
183 |
184 |
185 |
--------------------------------------------------------------------------------
/Gemfile.lock:
--------------------------------------------------------------------------------
1 | GEM
2 | remote: http://rubygems.org/
3 | specs:
4 | CFPropertyList (3.0.2)
5 | activesupport (4.2.11.3)
6 | i18n (~> 0.7)
7 | minitest (~> 5.1)
8 | thread_safe (~> 0.3, >= 0.3.4)
9 | tzinfo (~> 1.1)
10 | addressable (2.7.0)
11 | public_suffix (>= 2.0.2, < 5.0)
12 | algoliasearch (1.27.3)
13 | httpclient (~> 2.8, >= 2.8.3)
14 | json (>= 1.5.1)
15 | atomos (0.1.3)
16 | aws-eventstream (1.1.0)
17 | aws-partitions (1.358.0)
18 | aws-sdk-core (3.104.4)
19 | aws-eventstream (~> 1, >= 1.0.2)
20 | aws-partitions (~> 1, >= 1.239.0)
21 | aws-sigv4 (~> 1.1)
22 | jmespath (~> 1.0)
23 | aws-sdk-kms (1.36.0)
24 | aws-sdk-core (~> 3, >= 3.99.0)
25 | aws-sigv4 (~> 1.1)
26 | aws-sdk-s3 (1.78.0)
27 | aws-sdk-core (~> 3, >= 3.104.3)
28 | aws-sdk-kms (~> 1)
29 | aws-sigv4 (~> 1.1)
30 | aws-sigv4 (1.2.2)
31 | aws-eventstream (~> 1, >= 1.0.2)
32 | babosa (1.0.3)
33 | claide (1.0.3)
34 | claide-plugins (0.9.2)
35 | cork
36 | nap
37 | open4 (~> 1.3)
38 | cocoapods (1.9.3)
39 | activesupport (>= 4.0.2, < 5)
40 | claide (>= 1.0.2, < 2.0)
41 | cocoapods-core (= 1.9.3)
42 | cocoapods-deintegrate (>= 1.0.3, < 2.0)
43 | cocoapods-downloader (>= 1.2.2, < 2.0)
44 | cocoapods-plugins (>= 1.0.0, < 2.0)
45 | cocoapods-search (>= 1.0.0, < 2.0)
46 | cocoapods-stats (>= 1.0.0, < 2.0)
47 | cocoapods-trunk (>= 1.4.0, < 2.0)
48 | cocoapods-try (>= 1.1.0, < 2.0)
49 | colored2 (~> 3.1)
50 | escape (~> 0.0.4)
51 | fourflusher (>= 2.3.0, < 3.0)
52 | gh_inspector (~> 1.0)
53 | molinillo (~> 0.6.6)
54 | nap (~> 1.0)
55 | ruby-macho (~> 1.4)
56 | xcodeproj (>= 1.14.0, < 2.0)
57 | cocoapods-core (1.9.3)
58 | activesupport (>= 4.0.2, < 6)
59 | algoliasearch (~> 1.0)
60 | concurrent-ruby (~> 1.1)
61 | fuzzy_match (~> 2.0.4)
62 | nap (~> 1.0)
63 | netrc (~> 0.11)
64 | typhoeus (~> 1.0)
65 | cocoapods-deintegrate (1.0.4)
66 | cocoapods-downloader (1.4.0)
67 | cocoapods-plugins (1.0.0)
68 | nap
69 | cocoapods-search (1.0.0)
70 | cocoapods-stats (1.1.0)
71 | cocoapods-trunk (1.5.0)
72 | nap (>= 0.8, < 2.0)
73 | netrc (~> 0.11)
74 | cocoapods-try (1.2.0)
75 | colored (1.2)
76 | colored2 (3.1.2)
77 | commander-fastlane (4.4.6)
78 | highline (~> 1.7.2)
79 | concurrent-ruby (1.1.7)
80 | cork (0.3.0)
81 | colored2 (~> 3.1)
82 | danger (8.0.4)
83 | claide (~> 1.0)
84 | claide-plugins (>= 0.9.2)
85 | colored2 (~> 3.1)
86 | cork (~> 0.1)
87 | faraday (>= 0.9.0, < 2.0)
88 | faraday-http-cache (~> 2.0)
89 | git (~> 1.7)
90 | kramdown (~> 2.0)
91 | kramdown-parser-gfm (~> 1.0)
92 | no_proxy_fix
93 | octokit (~> 4.7)
94 | terminal-table (~> 1)
95 | declarative (0.0.20)
96 | declarative-option (0.1.0)
97 | digest-crc (0.6.1)
98 | rake (~> 13.0)
99 | domain_name (0.5.20190701)
100 | unf (>= 0.0.5, < 1.0.0)
101 | dotenv (2.7.6)
102 | emoji_regex (3.0.0)
103 | escape (0.0.4)
104 | ethon (0.12.0)
105 | ffi (>= 1.3.0)
106 | excon (0.76.0)
107 | faraday (1.0.1)
108 | multipart-post (>= 1.2, < 3)
109 | faraday-cookie_jar (0.0.6)
110 | faraday (>= 0.7.4)
111 | http-cookie (~> 1.0.0)
112 | faraday-http-cache (2.2.0)
113 | faraday (>= 0.8)
114 | faraday_middleware (1.0.0)
115 | faraday (~> 1.0)
116 | fastimage (2.2.0)
117 | fastlane (2.156.1)
118 | CFPropertyList (>= 2.3, < 4.0.0)
119 | addressable (>= 2.3, < 3.0.0)
120 | aws-sdk-s3 (~> 1.0)
121 | babosa (>= 1.0.3, < 2.0.0)
122 | bundler (>= 1.12.0, < 3.0.0)
123 | colored
124 | commander-fastlane (>= 4.4.6, < 5.0.0)
125 | dotenv (>= 2.1.1, < 3.0.0)
126 | emoji_regex (>= 0.1, < 4.0)
127 | excon (>= 0.71.0, < 1.0.0)
128 | faraday (~> 1.0)
129 | faraday-cookie_jar (~> 0.0.6)
130 | faraday_middleware (~> 1.0)
131 | fastimage (>= 2.1.0, < 3.0.0)
132 | gh_inspector (>= 1.1.2, < 2.0.0)
133 | google-api-client (>= 0.37.0, < 0.39.0)
134 | google-cloud-storage (>= 1.15.0, < 2.0.0)
135 | highline (>= 1.7.2, < 2.0.0)
136 | json (< 3.0.0)
137 | jwt (>= 2.1.0, < 3)
138 | mini_magick (>= 4.9.4, < 5.0.0)
139 | multipart-post (~> 2.0.0)
140 | plist (>= 3.1.0, < 4.0.0)
141 | rubyzip (>= 2.0.0, < 3.0.0)
142 | security (= 0.1.3)
143 | simctl (~> 1.6.3)
144 | slack-notifier (>= 2.0.0, < 3.0.0)
145 | terminal-notifier (>= 2.0.0, < 3.0.0)
146 | terminal-table (>= 1.4.5, < 2.0.0)
147 | tty-screen (>= 0.6.3, < 1.0.0)
148 | tty-spinner (>= 0.8.0, < 1.0.0)
149 | word_wrap (~> 1.0.0)
150 | xcodeproj (>= 1.13.0, < 2.0.0)
151 | xcpretty (~> 0.3.0)
152 | xcpretty-travis-formatter (>= 0.0.3)
153 | ffi (1.13.1)
154 | fourflusher (2.3.1)
155 | fuzzy_match (2.0.4)
156 | gh_inspector (1.1.3)
157 | git (1.7.0)
158 | rchardet (~> 1.8)
159 | google-api-client (0.38.0)
160 | addressable (~> 2.5, >= 2.5.1)
161 | googleauth (~> 0.9)
162 | httpclient (>= 2.8.1, < 3.0)
163 | mini_mime (~> 1.0)
164 | representable (~> 3.0)
165 | retriable (>= 2.0, < 4.0)
166 | signet (~> 0.12)
167 | google-cloud-core (1.5.0)
168 | google-cloud-env (~> 1.0)
169 | google-cloud-errors (~> 1.0)
170 | google-cloud-env (1.3.3)
171 | faraday (>= 0.17.3, < 2.0)
172 | google-cloud-errors (1.0.1)
173 | google-cloud-storage (1.27.0)
174 | addressable (~> 2.5)
175 | digest-crc (~> 0.4)
176 | google-api-client (~> 0.33)
177 | google-cloud-core (~> 1.2)
178 | googleauth (~> 0.9)
179 | mini_mime (~> 1.0)
180 | googleauth (0.13.1)
181 | faraday (>= 0.17.3, < 2.0)
182 | jwt (>= 1.4, < 3.0)
183 | memoist (~> 0.16)
184 | multi_json (~> 1.11)
185 | os (>= 0.9, < 2.0)
186 | signet (~> 0.14)
187 | highline (1.7.10)
188 | http-cookie (1.0.3)
189 | domain_name (~> 0.5)
190 | httpclient (2.8.3)
191 | i18n (0.9.5)
192 | concurrent-ruby (~> 1.0)
193 | jazzy (0.13.5)
194 | cocoapods (~> 1.5)
195 | mustache (~> 1.1)
196 | open4
197 | redcarpet (~> 3.4)
198 | rouge (>= 2.0.6, < 4.0)
199 | sassc (~> 2.1)
200 | sqlite3 (~> 1.3)
201 | xcinvoke (~> 0.3.0)
202 | jmespath (1.4.0)
203 | json (2.3.1)
204 | jwt (2.2.2)
205 | kramdown (2.3.0)
206 | rexml
207 | kramdown-parser-gfm (1.1.0)
208 | kramdown (~> 2.0)
209 | liferaft (0.0.6)
210 | memoist (0.16.2)
211 | mini_magick (4.10.1)
212 | mini_mime (1.0.2)
213 | minitest (5.14.1)
214 | molinillo (0.6.6)
215 | multi_json (1.15.0)
216 | multipart-post (2.0.0)
217 | mustache (1.1.1)
218 | nanaimo (0.3.0)
219 | nap (1.1.0)
220 | naturally (2.2.0)
221 | netrc (0.11.0)
222 | no_proxy_fix (0.1.2)
223 | octokit (4.18.0)
224 | faraday (>= 0.9)
225 | sawyer (~> 0.8.0, >= 0.5.3)
226 | open4 (1.3.4)
227 | os (1.1.1)
228 | plist (3.5.0)
229 | public_suffix (4.0.5)
230 | rake (13.0.1)
231 | rchardet (1.8.0)
232 | redcarpet (3.5.0)
233 | representable (3.0.4)
234 | declarative (< 0.1.0)
235 | declarative-option (< 0.2.0)
236 | uber (< 0.2.0)
237 | retriable (3.1.2)
238 | rexml (3.2.4)
239 | rouge (2.0.7)
240 | ruby-macho (1.4.0)
241 | rubyzip (2.3.0)
242 | sassc (2.4.0)
243 | ffi (~> 1.9)
244 | sawyer (0.8.2)
245 | addressable (>= 2.3.5)
246 | faraday (> 0.8, < 2.0)
247 | security (0.1.3)
248 | signet (0.14.0)
249 | addressable (~> 2.3)
250 | faraday (>= 0.17.3, < 2.0)
251 | jwt (>= 1.5, < 3.0)
252 | multi_json (~> 1.10)
253 | simctl (1.6.8)
254 | CFPropertyList
255 | naturally
256 | slack-notifier (2.3.2)
257 | sqlite3 (1.4.2)
258 | terminal-notifier (2.0.0)
259 | terminal-table (1.8.0)
260 | unicode-display_width (~> 1.1, >= 1.1.1)
261 | thread_safe (0.3.6)
262 | tty-cursor (0.7.1)
263 | tty-screen (0.8.1)
264 | tty-spinner (0.9.3)
265 | tty-cursor (~> 0.7)
266 | typhoeus (1.4.0)
267 | ethon (>= 0.9.0)
268 | tzinfo (1.2.7)
269 | thread_safe (~> 0.1)
270 | uber (0.1.0)
271 | unf (0.1.4)
272 | unf_ext
273 | unf_ext (0.0.7.7)
274 | unicode-display_width (1.7.0)
275 | word_wrap (1.0.0)
276 | xcinvoke (0.3.0)
277 | liferaft (~> 0.0.6)
278 | xcodeproj (1.18.0)
279 | CFPropertyList (>= 2.3.3, < 4.0)
280 | atomos (~> 0.1.3)
281 | claide (>= 1.0.2, < 2.0)
282 | colored2 (~> 3.1)
283 | nanaimo (~> 0.3.0)
284 | xcpretty (0.3.0)
285 | rouge (~> 2.0.7)
286 | xcpretty-travis-formatter (1.0.0)
287 | xcpretty (~> 0.2, >= 0.0.7)
288 |
289 | PLATFORMS
290 | ruby
291 |
292 | DEPENDENCIES
293 | cocoapods
294 | danger
295 | fastlane
296 | jazzy (>= 0.8.0)
297 |
298 | BUNDLED WITH
299 | 2.1.4
300 |
--------------------------------------------------------------------------------
/docs/Classes/KeyboardDismissTextField.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | KeyboardDismissTextField Class Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
43 |
44 |
45 | ICInputAccessory Reference
46 |
47 | KeyboardDismissTextField Class Reference
48 |
49 |
50 |
51 |
52 |
90 |
91 |
92 |
93 |
94 |
95 |
KeyboardDismissTextField
96 |
97 |
98 |
@IBDesignable
99 | open class KeyboardDismissTextField : UITextField
100 |
101 |
102 |
103 |
A text field that has a button to dismiss keyboard on the input accessory view.
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
120 |
121 |
122 |
123 |
124 |
125 |
The custom input accessory view with a button to dismiss keyboard.
126 |
127 |
128 |
129 |
Declaration
130 |
136 |
137 |
140 |
141 |
142 |
143 |
144 |
145 |
146 |
153 |
154 |
155 |
162 |
163 |
164 |
165 |
166 |
167 |
Initializes and returns a newly allocated view object with the specified frame rectangle.
168 |
169 |
170 |
171 |
Declaration
172 |
173 |
Swift
174 |
public override init ( frame : CGRect )
175 |
176 |
177 |
178 |
181 |
182 |
183 |
184 |
185 |
192 |
193 |
194 |
195 |
196 |
197 |
Returns an object initialized from data in a given unarchiver.
198 |
199 |
200 |
201 |
Declaration
202 |
203 |
Swift
204 |
public required init ?( coder aDecoder : NSCoder )
205 |
206 |
207 |
208 |
211 |
212 |
213 |
214 |
215 |
216 |
217 |
218 |
219 |
220 |
221 |
225 |
226 |
227 |
228 |
--------------------------------------------------------------------------------
/docs/search.json:
--------------------------------------------------------------------------------
1 | {"Structs/Option.html#/s:16ICInputAccessory6OptionV8optionalACyxGvpZ":{"name":"optional","abstract":"Returns an option that displays the optional value of an OptionDescriptive type.
","parent_name":"Option"},"Structs/Option.html#/s:16ICInputAccessory6OptionVyACyxGxcfc":{"name":"init(_:)","abstract":"Returns an initialized option with an instance of an OptionDescriptive type.
","parent_name":"Option"},"Structs/Option.html#/s:16ICInputAccessory6OptionV5titleSSvp":{"name":"title","abstract":"Conformance to OptionDescriptive .
","parent_name":"Option"},"Structs/Option.html#/s:16ICInputAccessory6OptionV5valuexSgvp":{"name":"value","abstract":"The OptionDescriptive value of the option. Returns nil when it’s the optional placeholder.
","parent_name":"Option"},"Structs/Option.html#/s:16ICInputAccessory6OptionV2eeoiySbACyxG_AEtFZ":{"name":"==(_:_:)","abstract":"Returns true when two options’ values are equal.
","parent_name":"Option"},"Structs/Option.html":{"name":"Option","abstract":"An option struct that carries the OptionDescriptive
"},"Protocols/TokenFieldDelegate.html#/c:@M@ICInputAccessory@objc(pl)TokenFieldDelegate(im)tokenFieldDidBeginEditing:":{"name":"tokenFieldDidBeginEditing(_:)","abstract":"Tells the delegate that editing began for the token field.
","parent_name":"TokenFieldDelegate"},"Protocols/TokenFieldDelegate.html#/c:@M@ICInputAccessory@objc(pl)TokenFieldDelegate(im)tokenFieldDidEndEditing:":{"name":"tokenFieldDidEndEditing(_:)","abstract":"Tells the delegate that editing stopped for the token field.
","parent_name":"TokenFieldDelegate"},"Protocols/TokenFieldDelegate.html#/c:@M@ICInputAccessory@objc(pl)TokenFieldDelegate(im)tokenFieldWillReturn:":{"name":"tokenFieldWillReturn(_:)","abstract":"Tells the delegate that the token field will process the pressing of the return button.
","parent_name":"TokenFieldDelegate"},"Protocols/TokenFieldDelegate.html#/c:@M@ICInputAccessory@objc(pl)TokenFieldDelegate(im)tokenField:didChangeInputText:":{"name":"tokenField(_:didChangeInputText:)","abstract":"Tells the delegate the input text is changed.
","parent_name":"TokenFieldDelegate"},"Protocols/TokenFieldDelegate.html#/c:@M@ICInputAccessory@objc(pl)TokenFieldDelegate(im)tokenField:shouldCompleteText:":{"name":"tokenField(_:shouldCompleteText:)","abstract":"Asks the delegate if the text should become a token in the token field.
","parent_name":"TokenFieldDelegate"},"Protocols/TokenFieldDelegate.html#/c:@M@ICInputAccessory@objc(pl)TokenFieldDelegate(im)tokenField:didCompleteText:":{"name":"tokenField(_:didCompleteText:)","abstract":"Tells the delegate that the text becomes a token in the token field.
","parent_name":"TokenFieldDelegate"},"Protocols/TokenFieldDelegate.html#/c:@M@ICInputAccessory@objc(pl)TokenFieldDelegate(im)tokenField:didDeleteText:atIndex:":{"name":"tokenField(_:didDeleteText:atIndex:)","abstract":"Tells the delegate that the token at certain index is removed from the token field.
","parent_name":"TokenFieldDelegate"},"Protocols/TokenFieldDelegate.html#/c:@M@ICInputAccessory@objc(pl)TokenFieldDelegate(im)tokenField:subsequentDelimiterForCompletedText:":{"name":"tokenField(_:subsequentDelimiterForCompletedText:)","abstract":"Asks the delegate for the subsequent delimiter string for a completed text in the token field.
","parent_name":"TokenFieldDelegate"},"Protocols/OptionDescriptive.html#/s:16ICInputAccessory17OptionDescriptiveP5titleSSvp":{"name":"title","abstract":"The text for the row in the UIPickerView.
","parent_name":"OptionDescriptive"},"Protocols/OptionDescriptive.html#/s:16ICInputAccessory17OptionDescriptiveP21titleForOptionalValueSSvpZ":{"name":"titleForOptionalValue","abstract":"The text for a placeholder row when the picker selection is optional.
","parent_name":"OptionDescriptive"},"Protocols/OptionDescriptive.html":{"name":"OptionDescriptive","abstract":"The protocol defines the required variables to be displayed in a UIPickerView via OptionPickerControl .
"},"Protocols/TokenFieldDelegate.html":{"name":"TokenFieldDelegate","abstract":"The protocol defines the messages sent to a delegate. All the methods are optional.
"},"Classes/TokenField.html#/s:16ICInputAccessory10TokenFieldC8delegateAA0cD8Delegate_pSgXwvp":{"name":"delegate","abstract":"The receiver’s delegate.
","parent_name":"TokenField"},"Classes/TokenField.html#/s:16ICInputAccessory10TokenFieldC10delimitersSaySSGvp":{"name":"delimiters","abstract":"Characters that completes a new token, defaults are whitespace and commas.
","parent_name":"TokenField"},"Classes/TokenField.html#/s:16ICInputAccessory10TokenFieldC5textsSaySSGvp":{"name":"texts","abstract":"Texts of each created token.
","parent_name":"TokenField"},"Classes/TokenField.html#/c:@M@ICInputAccessory@objc(cs)TokenField(py)icon":{"name":"icon","abstract":"The image on the left of text field.
","parent_name":"TokenField"},"Classes/TokenField.html#/s:16ICInputAccessory10TokenFieldC04textD0So06UITextD0Cvp":{"name":"textField","abstract":"The text field that handles text inputs.","parent_name":"TokenField"},"Classes/TokenField.html#/c:@M@ICInputAccessory@objc(cs)TokenField(py)placeholder":{"name":"placeholder","abstract":"
The placeholder with the default color and font.
","parent_name":"TokenField"},"Classes/TokenField.html#/s:16ICInputAccessory10TokenFieldC21attributedPlaceholderSo18NSAttributedStringCSgvp":{"name":"attributedPlaceholder","abstract":"The placeholder with customized attributes.
","parent_name":"TokenField"},"Classes/TokenField.html#/s:16ICInputAccessory10TokenFieldC06normalC10AttributesSDySo21NSAttributedStringKeyaSo8NSObjectCGSgvp":{"name":"normalTokenAttributes","abstract":"Customized attributes for tokens in the normal state, e.g. .font and .foregroundColor.
","parent_name":"TokenField"},"Classes/TokenField.html#/s:16ICInputAccessory10TokenFieldC011highlightedC10AttributesSDySo21NSAttributedStringKeyaSo8NSObjectCGSgvp":{"name":"highlightedTokenAttributes","abstract":"Customized attributes for tokens in the highlighted state.
","parent_name":"TokenField"},"Classes/TokenField.html#/c:@M@ICInputAccessory@objc(cs)TokenField(py)tintColor":{"name":"tintColor","abstract":"The tint color of icon image and text field.
","parent_name":"TokenField"},"Classes/TokenField.html#/c:@M@ICInputAccessory@objc(cs)TokenField(im)initWithFrame:":{"name":"init(frame:)","abstract":"Initializes and returns a newly allocated view object with the specified frame rectangle.
","parent_name":"TokenField"},"Classes/TokenField.html#/c:@M@ICInputAccessory@objc(cs)TokenField(im)initWithCoder:":{"name":"init(coder:)","abstract":"Returns an object initialized from data in a given unarchiver.
","parent_name":"TokenField"},"Classes/TokenField.html#/s:16ICInputAccessory10TokenFieldC24completeCurrentInputTextyyF":{"name":"completeCurrentInputText()","abstract":"Creates a token with the current input text.
","parent_name":"TokenField"},"Classes/TokenField.html#/s:16ICInputAccessory10TokenFieldC11resetTokensyyF":{"name":"resetTokens()","abstract":"Removes the input text and all displayed tokens.
","parent_name":"TokenField"},"Classes/OptionPickerControl.html#/s:16ICInputAccessory19OptionPickerControlCACyxGycfc":{"name":"init()","abstract":"Returns an initialized OptionPickerControl.
","parent_name":"OptionPickerControl"},"Classes/OptionPickerControl.html#/s:16ICInputAccessory19OptionPickerControlC5coderACyxGSgSo7NSCoderC_tcfc":{"name":"init(coder:)","abstract":"Not supported. OptionPickerControl is not compatible with storyboards.
","parent_name":"OptionPickerControl"},"Classes/OptionPickerControl.html#/s:16ICInputAccessory19OptionPickerControlC7optionsSayAA0C0VyxGGvp":{"name":"options","abstract":"Options that shows in the UIPickerView.
","parent_name":"OptionPickerControl"},"Classes/OptionPickerControl.html#/s:16ICInputAccessory19OptionPickerControlC08selectedC0AA0C0VyxGvp":{"name":"selectedOption","abstract":"The currently selected item in the options.
","parent_name":"OptionPickerControl"},"Classes/OptionPickerControl.html#/s:16ICInputAccessory19OptionPickerControlC6pickerSo12UIPickerViewCvp":{"name":"picker","abstract":"A reference to the displayed UIPickerView for customization.
","parent_name":"OptionPickerControl"},"Classes/OptionPickerControl.html#/s:16ICInputAccessory19OptionPickerControlC18numberOfComponents2inSiSo12UIPickerViewC_tF":{"name":"numberOfComponents(in:)","abstract":"Currently OptionPickerControl only supports one component.
","parent_name":"OptionPickerControl"},"Classes/KeyboardDismissTextField.html#/c:@M@ICInputAccessory@objc(cs)KeyboardDismissTextField(py)keyboardAccessoryView":{"name":"keyboardAccessoryView","abstract":"The custom input accessory view with a button to dismiss keyboard.
","parent_name":"KeyboardDismissTextField"},"Classes/KeyboardDismissTextField.html#/c:@M@ICInputAccessory@objc(cs)KeyboardDismissTextField(im)initWithFrame:":{"name":"init(frame:)","abstract":"Initializes and returns a newly allocated view object with the specified frame rectangle.
","parent_name":"KeyboardDismissTextField"},"Classes/KeyboardDismissTextField.html#/c:@M@ICInputAccessory@objc(cs)KeyboardDismissTextField(im)initWithCoder:":{"name":"init(coder:)","abstract":"Returns an object initialized from data in a given unarchiver.
","parent_name":"KeyboardDismissTextField"},"Classes/KeyboardDismissAccessoryView.html#/c:@M@ICInputAccessory@objc(cs)KeyboardDismissAccessoryView(py)buttonColor":{"name":"buttonColor","abstract":"The background color of the button to dismiss keyboard.
","parent_name":"KeyboardDismissAccessoryView"},"Classes/KeyboardDismissAccessoryView.html#/s:16ICInputAccessory015KeyboardDismissB4ViewC13dismissButtonSo8UIButtonCvp":{"name":"dismissButton","abstract":"The button to dismiss keyboard.
","parent_name":"KeyboardDismissAccessoryView"},"Classes/KeyboardDismissAccessoryView.html#/c:@M@ICInputAccessory@objc(cs)KeyboardDismissAccessoryView(im)initWithFrame:":{"name":"init(frame:)","abstract":"Initializes and returns a newly allocated view object with the specified frame rectangle.
","parent_name":"KeyboardDismissAccessoryView"},"Classes/KeyboardDismissAccessoryView.html#/c:@M@ICInputAccessory@objc(cs)KeyboardDismissAccessoryView(im)initWithCoder:":{"name":"init(coder:)","abstract":"Returns an object initialized from data in a given unarchiver.
","parent_name":"KeyboardDismissAccessoryView"},"Classes/KeyboardDismissAccessoryView.html":{"name":"KeyboardDismissAccessoryView","abstract":"A customized keyboard accessory view with a dismiss button.
"},"Classes/KeyboardDismissTextField.html":{"name":"KeyboardDismissTextField","abstract":"A text field that has a button to dismiss keyboard on the input accessory view.
"},"Classes/OptionPickerControl.html":{"name":"OptionPickerControl","abstract":"A UIControl that displays a UIPickerView and notifies changed selection and via UIControlEvents .valueChanged.
"},"Classes/TokenField.html":{"name":"TokenField","abstract":"A text field that groups input texts with delimiters.
"},"Classes.html":{"name":"Classes","abstract":"The following classes are available globally.
"},"Protocols.html":{"name":"Protocols","abstract":"The following protocols are available globally.
"},"Structs.html":{"name":"Structures","abstract":"The following structures are available globally.
"}}
2 |
--------------------------------------------------------------------------------
/Example/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
123 |
124 |
125 |
126 |
127 |
128 |
129 |
130 |
131 |
132 |
133 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
143 |
144 |
--------------------------------------------------------------------------------
/docs/Classes.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Classes Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
43 |
44 |
45 | ICInputAccessory Reference
46 |
47 | Classes Reference
48 |
49 |
50 |
51 |
52 |
90 |
91 |
92 |
93 |
94 |
95 |
Classes
96 |
The following classes are available globally.
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
113 |
114 |
115 |
116 |
117 |
118 |
A customized keyboard accessory view with a dismiss button.
119 |
120 |
See more
121 |
122 |
123 |
Declaration
124 |
125 |
Swift
126 |
@IBDesignable
127 | open class KeyboardDismissAccessoryView : UIView
128 |
129 |
130 |
131 |
134 |
135 |
136 |
137 |
138 |
139 |
140 |
141 |
142 |
149 |
150 |
151 |
152 |
153 |
154 |
A text field that has a button to dismiss keyboard on the input accessory view.
155 |
156 |
See more
157 |
158 |
159 |
Declaration
160 |
161 |
Swift
162 |
@IBDesignable
163 | open class KeyboardDismissTextField : UITextField
164 |
165 |
166 |
167 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
177 |
178 |
185 |
186 |
187 |
188 |
189 |
190 |
A UIControl that displays a UIPickerView and notifies changed selection and via UIControlEvents .valueChanged.
191 |
192 |
See more
193 |
194 |
195 |
Declaration
196 |
197 |
Swift
198 |
open class OptionPickerControl < T > : UIControl , UIPickerViewDataSource , UIPickerViewDelegate where T : OptionDescriptive
199 |
200 |
201 |
202 |
205 |
206 |
207 |
208 |
209 |
210 |
211 |
212 |
213 |
220 |
221 |
222 |
223 |
224 |
225 |
A text field that groups input texts with delimiters.
226 |
227 |
See more
228 |
229 |
230 |
Declaration
231 |
232 |
Swift
233 |
@IBDesignable
234 | open class TokenField : UIView , UITextFieldDelegate , BackspaceTextFieldDelegate
235 |
236 |
237 |
238 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
255 |
256 |
257 |
258 |
--------------------------------------------------------------------------------
/docs/Classes/KeyboardDismissAccessoryView.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | KeyboardDismissAccessoryView Class Reference
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
43 |
44 |
45 | ICInputAccessory Reference
46 |
47 | KeyboardDismissAccessoryView Class Reference
48 |
49 |
50 |
51 |
52 |
90 |
91 |
92 |
93 |
94 |
95 |
KeyboardDismissAccessoryView
96 |
97 |
98 |
@IBDesignable
99 | open class KeyboardDismissAccessoryView : UIView
100 |
101 |
102 |
103 |
A customized keyboard accessory view with a dismiss button.
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
120 |
121 |
122 |
123 |
124 |
125 |
The background color of the button to dismiss keyboard.
126 |
127 |
128 |
129 |
Declaration
130 |
131 |
Swift
132 |
@IBInspectable
133 | public var buttonColor : UIColor { get set }
134 |
135 |
136 |
137 |
140 |
141 |
142 |
143 |
144 |
151 |
152 |
153 |
154 |
155 |
156 |
The button to dismiss keyboard.
157 |
158 |
159 |
160 |
Declaration
161 |
162 |
Swift
163 |
public private(set) lazy var dismissButton : UIButton { get set }
164 |
165 |
166 |
167 |
170 |
171 |
172 |
173 |
174 |
175 |
176 |
183 |
184 |
185 |
192 |
193 |
194 |
195 |
196 |
197 |
Initializes and returns a newly allocated view object with the specified frame rectangle.
198 |
199 |
200 |
201 |
Declaration
202 |
203 |
Swift
204 |
public override init ( frame : CGRect )
205 |
206 |
207 |
208 |
211 |
212 |
213 |
214 |
215 |
222 |
223 |
224 |
225 |
226 |
227 |
Returns an object initialized from data in a given unarchiver.
228 |
229 |
230 |
231 |
Declaration
232 |
233 |
Swift
234 |
public required init ?( coder aDecoder : NSCoder )
235 |
236 |
237 |
238 |
241 |
242 |
243 |
244 |
245 |
246 |
247 |
248 |
249 |
250 |
251 |
255 |
256 |
257 |
258 |
--------------------------------------------------------------------------------