{"id":15025919,"url":"https://github.com/totocaster/typist","last_synced_at":"2025-05-16T09:05:32.163Z","repository":{"id":55012015,"uuid":"69236488","full_name":"totocaster/Typist","owner":"totocaster","description":"Swift UIKit keyboard manager for iOS apps.","archived":false,"fork":false,"pushed_at":"2021-05-27T23:32:20.000Z","size":107,"stargazers_count":1064,"open_issues_count":0,"forks_count":46,"subscribers_count":22,"default_branch":"master","last_synced_at":"2025-05-10T00:06:34.270Z","etag":null,"topics":["event-callback","keyboard","keyboard-events","keyboard-layout","keyboard-listeners"],"latest_commit_sha":null,"homepage":"","language":"Swift","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/totocaster.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null},"funding":{"github":["totocaster"],"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":null,"issuehunt":null,"otechie":null,"custom":null}},"created_at":"2016-09-26T09:52:04.000Z","updated_at":"2025-05-06T16:54:26.000Z","dependencies_parsed_at":"2022-08-14T09:00:59.225Z","dependency_job_id":null,"html_url":"https://github.com/totocaster/Typist","commit_stats":null,"previous_names":[],"tags_count":22,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/totocaster%2FTypist","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/totocaster%2FTypist/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/totocaster%2FTypist/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/totocaster%2FTypist/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/totocaster","download_url":"https://codeload.github.com/totocaster/Typist/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254501557,"owners_count":22081528,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["event-callback","keyboard","keyboard-events","keyboard-layout","keyboard-listeners"],"created_at":"2024-09-24T20:03:19.525Z","updated_at":"2025-05-16T09:05:27.153Z","avatar_url":"https://github.com/totocaster.png","language":"Swift","funding_links":["https://github.com/sponsors/totocaster"],"categories":[],"sub_categories":[],"readme":"# Typist\n\n![Swift Version](https://img.shields.io/badge/swift-5-orange.svg?style=flat)\n[![Platform](https://img.shields.io/cocoapods/p/Typist.svg?style=flat)](http://cocoapods.org/pods/Typist)\n[![CocoaPods Compatible](https://img.shields.io/cocoapods/v/Typist.svg)](https://img.shields.io/cocoapods/v/Typist.svg)\n[![Carthage compatible](https://img.shields.io/badge/Carthage-compatible-4BC51D.svg?style=flat)](https://github.com/totocaster/Typist)\n[![Accio supported](https://img.shields.io/badge/Accio-supported-0A7CF5.svg?style=flat)](https://github.com/JamitLabs/Accio)\n[![Twitter](https://img.shields.io/badge/twitter-@totocaster-blue.svg)](http://twitter.com/totocaster)\n\n\nTypist is a small, drop-in Swift UIKit keyboard manager for iOS apps. It helps you manage keyboard's screen presence and behavior without notification center and Objective-C.\n\n---\n\n## Usage\n\nDeclare what should happen on what event and `start()` listening to keyboard events. That's it.\n\n```swift\nlet keyboard = Typist.shared // use `Typist()` whenever you can, see note on singleton usage below\n\nfunc configureKeyboard() {\n\n    keyboard\n        .on(event: .didShow) { (options) in\n            print(\"New Keyboard Frame is \\(options.endFrame).\")\n        }\n        .on(event: .didHide) { (options) in\n            print(\"It took \\(options.animationDuration) seconds to animate keyboard out.\")\n        }\n        .start()\n\n}\n```\n\nYou _must_ call `start()` for callbacks to be triggered. Calling `stop()` on instance will stop callbacks from triggering, but callbacks themselves won't be dismissed, thus you can resume event callbacks by calling `start()` again.\n\nTo remove all event callbacks, call `clear()`.\n\n#### Interactivity and `inputAccessoryView`\n\nYou can dismiss keyboard interactively when using Typist with `UIScrollView` instances.\n\n```swift\nlet keyboard = Typist()\n\nfunc configureKeyboard() {\n\n    keyboard\n        .toolbar(scrollView: tableView) // Enables interactive dismissal\n        .on(event: .willChangeFrame) { (options) in\n            // You are responsible animating inputAccessoryView\n        }\n        .on(event: .willHide)  { (options) in\n            // Triggered when keyboard is dismissed non-interactively.\n        }\n        .start()\n\n}\n```\n\n`.on(event: .willChangeFrame, do: {...})` will update as frequently as keyboard frame changes due to UIScrollView scrolling. It is good practice to implement `.willHide` portion as well since keyboard might be dismissed non-interactively, for example, using `resignFirstResponder()`.\n\nExample from above is [implemented in demo app](Typist/ViewController.swift).\n\n#### On Singleton Usage\n\nUsage of `shared` singleton, considered to be OK for convenient access to instance. However, it is strongly recommended to instantiate dedicated `Typist()` for each usage (in `UIViewController`, most likely). **Do not use singleton** when two or more objects using `Typist.shared` are presented on screen simultaneously, as it will cause one of the controllers to fail receiving keyboard events.\n\n### Event Callback Options\n\nEvery event callback has a parameter of `Typist.KeyboardOptions` type. It is an inert/immutable struct which carries all data that keyboard has at the event of happening:\n\n* **`belongsToCurrentApp`** — `Bool` that identifies whether the keyboard belongs to the current app. With multitasking on iPad, all visible apps are notified when the keyboard appears and disappears. The value is `true` for the app that caused the keyboard to appear and `false` for any other apps.\n* **`startFrame`** — `CGRect` that identifies the start frame of the keyboard in screen coordinates. These coordinates do not take into account any rotation factors applied to the view’s contents as a result of interface orientation changes. Thus, you may need to convert the rectangle to view coordinates (using the `convert(CGRect, from: UIView?)` method) before using it.\n* **`endFrame`** — `CGRect` that identifies the end frame of the keyboard in screen coordinates. These coordinates do not take into account any rotation factors applied to the view’s contents as a result of interface orientation changes. Thus, you may need to convert the rectangle to view coordinates (using the `convert(CGRect, from: UIView?)` method) before using it.\n* **`animationCurve`** — `UIView.AnimationCurve` constant that defines how the keyboard will be animated onto or off the screen.\n* **`animationDuration`** — `Double` that identifies the duration of the animation in seconds.\n* **`animationOptions`** — `UIView.AnimationOptions` helper property that maps the `animationCurve` to its respective `UIView.AnimationOptions` value. Usefull when performming view animations using `UIView.animate(...`.  \n\n### Events\n\nFollowing keyboard events are supported:\n\n* `willShow`\n* `didShow`\n* `willHide`\n* `didHide`\n* `willChangeFrame`\n* `didChangeFrame` – e.g. when keyboard is dynamically dismissed from scroll view interaction.\n\nIf you declare two closures on same event, only latter will be executed.\n\n---\n\n## Installation\n\n#### CocoaPods\nYou can use [CocoaPods](http://cocoapods.org/) to install `Typist` by adding it to your `Podfile`:\n\n```ruby\nplatform :ios, '8.0'\nuse_frameworks!\npod 'Typist'\n```\n\nImport `Typist` wherever you plan to listen to keyboard events. Usually in your `UIViewController` subclasses.\n\n``` swift\nimport UIKit\nimport Typist\n```\n\n\n#### Carthage\nCreate a `Cartfile` that lists the framework and run `carthage update`. Follow the [instructions](https://github.com/Carthage/Carthage#if-youre-building-for-ios) to add `$(SRCROOT)/Carthage/Build/iOS/Typist.framework` to an iOS project.\n\n```\ngithub \"totocaster/Typist\"\n```\n\n#### Accio\n\nInitialize your project with [Accio](https://github.com/JamitLabs/Accio) using the `init` command.\n\nAdd the following to your Package.swift:\n\n```swift\n.package(url: \"https://github.com/totocaster/Typist.git\", .upToNextMajor(from: \"1.4.2\")),\n```\n\nNext, add `Typist` to your App targets dependencies like so:\n\n```swift\n.target(\n    name: \"App\",\n    dependencies: [\n        \"Typist\",\n    ]\n),\n```\n\nThen run `accio update`.\n\n#### Manually\nDownload and drop ```Typist.swift``` in your project.\n\n---\n\nMy thanks to [Jake Marsh](https://twitter.com/jakemarsh) for featuring Typist on Little Bites of Cocoa [#282: Taming the Keyboard with Typist ⌨️](https://littlebitesofcocoa.com/282-taming-the-keyboard-with-typist). It made my day.\n\n\n---\n\n## License\n\nTypist is released under the MIT license. See ``LICENSE`` for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftotocaster%2Ftypist","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftotocaster%2Ftypist","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftotocaster%2Ftypist/lists"}