A picker view controller for emoji.
- UTS#51 Specification-compliant Emoji Picker(Not Tested Yet)
- Segmented control for jumping an emoji section
- Search bar and search results
- Fully accessible
- Dark mode
- Recently used
- Select skin tones from popup
- State Restoration
import EmojiPickerViewController
// Specifying the maximum storage amount for recently used emoji.
EmojiContainer.main.storageAmountForRecentlyUsedEmoji = 30
var configuration = EmojiPickerConfiguration()
// Enabling animation changes.
configuration.animatingChanges = true
// Specifying the maximum number of recently used emojis.
configuration.numberOfItemsInRecentlyUsedSection = 30
// Changing header appearance.
configuration.headerAppearance.textAlignment = .center
// Changing cell appearance.
configuration.cellAppearance.size = .init(width: 30, height: 30)
let emojiPickerViewController = EmojiPickerViewController(configuration: configuration)
// Receiving events from the picker view controller.
emojiPickerViewController.delegate = self
vc.present(emojiPickerViewController, animated: true)You can specify the annotation's locale manually:
if EmojiLocale.availableIdentifiers.contains("ja") {
EmojiContainer.main.emojiLocale = EmojiLocale(localeIdentifier: "ja")!
}or enable an automatic update option:
configuration.automaticallyUpdatingAnnotationsFollowingCurrentInputModeChange = true
// Disable
// configuration.automaticallyUpdatingAnnotationsFollowingCurrentInputModeChange = falseThe option is true by default.
You can get an Emoji object by accessing a singleton EmojiContainer instance if you need them:
let bouncingBall = EmojiContainer.main.entireEmojiSet["⛹🏿♀"]!
print(bouncingBall)
// Prints "character: ⛹🏿♀, status: minimallyQualified, group: People & Body, subgroup: person-sport, cldrOrder: 2360, annotation: ball | dark skin tone | woman | woman bouncing ball, textToSpeech: woman bouncing ball: dark skin tone"
let grape = EmojiContainer.main.labeledEmojisForKeyboard[.foodDrink]![0]
print(grape)
// Prints "character: 🍇, status: fullyQualified, group: Food & Drink, subgroup: food-fruit, cldrOrder: 3323, annotation: fruit | grape | grapes, textToSpeech: grapes"See and run Example for checking usages.
Install this package via swift package manager. Add EmojiPickerViewController as a dependency to your Package.swift:
.package(url: "https://github.com/yosshi4486/EmojiPickerViewController", from: "1.0.0")
- iOS 15.0+
- Xcode 13.0+
en, ja, da
EmojiLocale.availableIdentifiers
I'm looking forward for your issues or pull requests😊
Proofreading is specifically welcome because I'm not a native English speaker, and some sentences may be strange.
EmojiPickerViewController is released under the Apache License Version 2.0, and also uses some licensed OSSs such as "unicode-org/cldr". See LICENSE for details.
In this library, since there are no particularly lengthy operations, adopting the MainActor provides sufficient concurrency guarantees. Using dedicated actor types would introduce unnecessary complexity without meaningful performance gains, especially given that efficient multi-core utilization isn’t a requirement here. Considering this trade-off carefully, we chose this simpler, MainActor-based design.
The longest time method is EmojiContainer.load, it takes at most 0.1sec.

