Swiftpack.co - Package - danielsaidi/Sheeeeeeeeet

Version Platform Swift 5.1 License Twitter: @danielsaidi

About Sheeeeeeeeet

Sheeeeeeeeet lets you create menus that can be presented as iOS 13 context menus, custom action sheets, alert controllers or in any way you like.

Sheeeeeeeeet comes with many item types (standard items, buttons, titles, toggles etc.) and can be extended with your own custom item types.

Sheeeeeeeeet's custom action sheets can be styled to look just like a UIAlertController or completely different. You can also customize how they are presented and dismissed.


Swift Package Manager



pod "Sheeeeeeeeet"

Creating a menu

With Sheeeeeeeeet, you start with creating a menu, like this:

let item1 = MenuItem(title: "Int", value: 1)
let item2 = MenuItem(title: "Car", value: Car())
let button = OkButton(title: "OK")
let items = [item1, item2, button]
let menu = Menu(title: "Select a type", items: items)

Sheeeeeeeeet has many built-in item types, e.g. buttons, select items, links etc. A complete list can be found here.

You can also create your own custom item types by inheriting any of the existing ones. For instance, if you build a car rental app, you can create a car-specific item that takes a Car model.

You can even create your own menu types by subclassing Menu. This makes it possible to create app-specific menus that provide specific functionality, handle specific tasks etc.

Present a menu as an action sheet

You can present menus as custom action sheets:

let sheet = menu.toActionSheet(...) { sheet, item in ... }
sheet.present(in: vc, from: view) { sheet, item in ...
    print("You selected \(item.title)")

You can find more information in this action sheet guide.

Add a menu as a context menu

You can add menus as iOS 13 context menus to any view you like:

menu.addAsContextMenu(to: view) { sheet, item in ...
    print("You selected \(item.title)")

You can find more information in this context menu guide.

Present the menu as an alert controller

You can present menus as UIAlertControllers:

let delegate = menu.presentAsAlertController(in: self, from: view) { sheet, item in ...
    print("You selected \(item.title)")

You can find more information in this alert controller guide.

Demo App

This repository contains a demo app that demonstrates different menus and menu items, including subclassing and appearance adjustments.

To try it out, open and run the Sheeeeeeeeet.xcodeproj project.

Contact me

Feel free to reach out if you have questions or if you want to contribute in any way:


Sheeeeeeeeet is available under the MIT license. See LICENSE file for more info.


Stars: 1088

Used By

Total: 0


- 2020-04-01 11:43:19

This version prepares the library for Xcode 11.4 and Swift 5.2 and upgrades external dependencies.

- 2019-12-09 10:03:07

Thanks to @BinaryDennis, this version adds support for auto dismissing context menus and action sheets when an app is sent to the background.

New stuff:

  • ActionSheet has a new ActionSheet.Configuration that replaces Menu.Configuration. You specify it when you create an action sheet.
  • There is a new ActionSheetPresenterBase base class that you can use when creating custom presenters.
  • ActionSheetStandardPresenter and ActionSheetPopoverPresenter inherits ActionSheetPresenterBase.
  • ActionSheetPopoverPresenter has moved its popover delegate logic to another class and no longer inherits NSObject.
  • There is a new DestructiveItem type that makes it possible to have destructive options in a menu, not just destructive buttons.
  • DestructiveItem is automatically styled by the ActionSheetAppearance base class.
  • DestructiveItem is automatically annotated when it's converted to a context menu item.


  • Menu.Configuration is deprecated and have no affect anymore.
  • Menu.presentAsActionSheet is deprecated. Use toActionSheet instead, then present it.
  • ActionSheet.HeaderViewConfiguration is renamed to ActionSheet.HeaderConfiguration
  • ActionSheet.headerViewConfiguration is renamed to ActionSheet.headerConfiguration
  • ActionSheetDangerItemCell is renamed to ActionSheetDestructiveItemCell

Breaking changes:

I tried but couldn't avoiding breaking changes, since some protocols had to change. Hopefully, you can easily work around these changes:

  • ActionSheetPresenter no longer has an isDismissable property. Instead, use a .nonDismissable configuration when creating an action sheet.
  • ActionSheetPresenter convenience presenters are now part of ActionSheetPresenterBase no longer open for extension.

- 2019-11-05 11:51:56

This version adjusts the secondary action signature to also provide the affected item. It's a breaking change, but a small one, so deal with it I guess ¯\_(ツ)_/¯

This version also makes the ActionSheetItemHandler protocol implementations open so they're possible to override.

- 2019-11-01 16:03:34

This version changes ContextMenuDelegateRetainer's contextMenuDelegate to an Any instead of its concrete type, to make it possible to use it on older iOS versions.

This should not have any side-effects, since it's only used to retain the instance, never use it.

- 2019-11-01 16:03:19

This version solves an App Store submission rejection that occurred when an app pulled in Sheeeeeeeeet with Carthage.

- 2019-11-01 16:02:59

This version adds a new SecondaryActionItem which lets you specify a secondary action for an item.

It also adds a new MenuCreator protocol that can be implemented to postpone the creation of a menu, which may be good for prestanda when adding a context menu to every item in a large view collection.

- 2019-10-20 08:10:43

This version makes the ActionSheet's backgroundView property public.

- 2019-10-12 07:35:26

This version fixes some subtitle problems, where section titles and mutli select toggles didn't display their subtitles. It also fixes some behavior issues, where subtitles were incorrectly tinted.

- 2019-10-10 22:37:35

This version adjusts the popover height calculations to include the height of a visible header. This solves the problem where the popover content would always scroll when a header was used.

The version also adjusts the item height calculations, so that you no longer have to register a height for each item. This solves the problem with all items getting a zero size by default. Now, height is recursively resolved to the closest parent height if you haven't overridden appearance().height for your custom item.

- 2019-10-10 06:57:09

This version adjusts the subtitle style to use subtitle instead of value1.

It also adds a new preferredActionSheetCellStyle property to MenuItem, which you can override for your custom items.

- 2019-09-30 20:47:36

This version separates the menu data model from the custom action sheet implementation, so that you can create menus without caring about how they will be presented.

The new Menu type and all MenuItem types are decoupled from the presentation. This means that you can use them in more ways, for instance in custom and native action sheets, context menus etc.

With these changes, you now create an ActionSheet with a Menu instead of with a list of ActionSheetItem. Due to this, the 3.0 release of Sheeeeeeeeet has many breaking changes:

  • All ActionSheetItem have been replaced by the new MenuItem types. Most of these items have the same name as the old ones, but without the ActionSheet prefix.
  • ActionSheetDangerButton corresponds to the new DestructiveButton class.
  • ActionSheetCustomItemContentCell has been moved and renamed to CustomItemType.
  • ActionSheetCollectionItemContentCell has been moved and renamed to CollectionItemType.

There are also some breaking changes that involve how you work with action sheets:

  • Item heights are no longer static, but an action sheet cell appearance proxy property.
  • The action sheet header behavior is now specified in a headerViewConfiguration property.
  • CustomItem (ActionSheetCustomItem) has been made non-generic.
  • isOkButton and isCancelButton is gone. Use type checking instead, e.g. is OkButton.

Bonus features:

  • The popover presenter now supports header views. It no longer hides the header by default.
  • Menu can be presented as a custom action sheet, without creating an ActionSheet.
  • Menu can be used to create action sheets, which you then present and configure like before.
  • Menu can be added as an iOS 13 context menu to any view.
  • Menu can be presented as a native UIAlertController.

Some of the presentations above require that all items in the menu can be represented in that context.

- 2019-09-25 08:59:54

This version makes Package use https references instead of ssh.

- 2019-09-25 08:58:57

This version adjusts removes StandardActionSheetAppearance - the standard appearance is instead applied by the base class. Sheeeeeeeeet will also automatically apply the standard appearance if you do not.

- 2019-09-16 09:22:24

This version adds Xcode 11 and iOS 13 support, including support for dark mode and high contrast color variants.

There is a new ActionSheetColor enum with sheet-specific semantic colors. It uses the new, adaptive system colors in iOS 13 and falls back to older, non-adaptive colors in iOS 12 and below. You can either use the enum directly or use the static UIColor extension .sheetColor(...).

The appearance model has been extended with new a appearance type, which you can use to style your sheets. There is an ActionSheetAppearance base class as well as a standard StandardActionSheetAppearance appearance which applies a standard look, including dark mode support, high contrast color variants and SFSymbol icons on iOS 13.

There are adjustments to how sheets can be dismissed. The isDismissableWithTapOnBackground has been renamed to isDismissable, since it also affects if the system can dismiss the action sheet.

- 2019-05-29 06:48:26

This version makes table view footer view sizes smaller to avoid a scroll offset issue that could occur when rotating devices that displayed sheets with a single custom item.

- 2019-05-29 06:47:13

This version adjusts accessibility traits for selected select items and improves the overall accessibility experience when working with selectable items.

- 2019-05-29 06:46:56

This version upgrades Sheeeeeeeeet and its unit test dependencies to Swift 5. It contains no breaking changes.

- 2019-03-25 08:46:20

This version makes currentContext the default presentation mode for the default presenter. This is due to accessibility issues with using keyWindow while being in a modal presentation. I will change how the default presenteras presents action sheets, but that is a future improvement.

- 2019-03-25 08:33:23

This version removes the old deprecated appearance model, so if your app uses it, it's time to start using the appearance proxy model. Just follow the readme, and you'll be done in no time.

This version also change which presenter to use, so that apps behaves correct on iPads in split screen. We still have to come up with a way to switch between the default and popover presenters when the split screen size changes, but that is a future improvement.

- 2019-03-04 13:03:03

This version adds a new headerViewLandscapeMode property to ActionSheet. You can set it to .hidden to let action sheets hide their header view in landscape orientation. This will free up more screen estate for the action sheet's options.

- 2019-03-04 12:57:05

This version makes the ActionSheet backgroundView outlet public, so that you can add your own custom effects to it. The other outlets are still internal.

The version also fixes a bug that caused action sheets to be misplaced when they were presented from a custom presentation controller. This fix also adds a brand new presentationStyle property to StandardActionSheetPresenter, which can be either keyWindow (default) or currentContext. Setting it to keyWindow will present the action sheet in the app's key window (full screen), while setting it to currentContext will present it in the presenting view controller's view (it looks strange, but perhaps you can find a nice use case for it).

- 2019-02-12 21:23:17

I obviously don't use iOS 9 anymore. Some really nasty bugs appeared as I did 🙃

This version fixes an iOS 9 bug that caused the popover to become square with no arrow. It was caused by the popover presenter, that set the background color for the popover after it had been presented, which is not supported in iOS 9. It now sets the bg color for all iOS versions before it presents the popover, then only refreshes it for iOS 10 and later.

It also fixes an iOS 9 bug that caused the item cell separator line to behave strangely and not honor the insets set using the appearance proxy. I have added a fix to the item cell class, that only runs for iOS 9.

- 2019-02-12 10:56:22

This version removes the last separator line from the item and button table view.

This version also changes the default behavior of the popover presenter. It used to keep the popover presented as the device orientation changed, but this can be wrong in many cases. For instance, in collection or table views, the orientation change may cause cells to shuffle around as they are reused. If a reused cell is used as the popover source view, and the popover is still presented, the popover will point to the cell, but the cell model will have changed. In this case, your action sheet will appear to point to a specific object, but will be contextually bound to another one.

Another way that orientation changes may mess with popovers are if a source view is removed from the view hierarchy when the orientation changes. If your popover is still presented, but the source view is removed, the popover arrow will point to a random point, e.g. the top-left part of the screen.

To solve these bugs, I have added new orientation change handling in the popover presenter. It has a new isListeningToOrientationChanges property, as well as a handleOrientationChange and setupOrientationChangeDetection function. If you want to, you can override these functions to customize their behavior, otherwise just set isListeningToOrientationChanges to false to make the popover behave like before.

- 2019-01-17 11:55:24

This hotfix adds two new properties to ActionSheetSelectItem, that can be used to style the selected fonts: selectedTitleFont and selectedSubtitleFont.

Complete 1.2.0 release notes

- 2019-01-17 11:55:01

This hotfix fixes a font bug in the title item and color bugs in the select item.

Complete 1.2.0 release notes

1.2.0 - 2019-01-16 16:04:18

This is a huge update, that completely rewrites how action sheet appearances are handled. Instead of the old appearance model, Sheeeeeeeeet now relies on the iOS appearance proxy model as much as possible.

The old appearance model is still around, but has been marked as deprecated, and will be removed in 1.4.0. Make sure that you switch over to the new appearance model as soon as possible. Have a look at the example app and [here][Appearance] to see how you should customize the action sheet appearance from now on.

In short, item appearance customizations are handled in three different ways now:

  • Item appearances such as colors and fonts, are customized with cell properties, for instance: ActionSheetSelectItemCell.appearance().titleColor = .green.
  • Item heights are now customized by setting the height property of every item type you want to customize, for instance: ActionSheetTitle.height = 22.
  • Action sheet margins, insets etc. are now customized by setting the properties of each ActionSheet instance. If you want to change the default values for all action sheets in your app, you have to subclass ActionSheet.

All built-in action sheet items now have their own cells. Your custom items only have to use custom cells if you want to apply custom item appearances to them.

Sheeeeeeeeet now contains several new views, which are used by the action sheets:

  • ActionSheetTableView
  • ActionSheetItemTableView
  • ActionSheetButtonTableView
  • ActionSheetBackgroundView
  • ActionSheetStackView

The new classes make it easy to modify the appearance of these views, since they have appearance properties as well. For instance, to change the corner radius of the table views, just type: ActionSheetTableView.appearance().cornerRadius = 8.

ActionSheet has two new extensions:

  • items<T>(ofType:)
  • scrollToFirstSelectedItem(at:)

This new version has also rebuilt all unit tests from scratch. They are now more robust and easier to maintain.

- 2019-01-10 14:57:37

This version increases the action sheet integrity by restricting what you can do with it. This involves some breaking changes, but they should not affect you. If you think any new rule is bad or affect you, please let me know.

New Features

@sebbo176 has added support for subtitles in the various select items, which now also changes the cell style of an item if the subtitle is set. He has also added an unselected icon to the select items, which means that you can now have images for unselected items as well (e.g. an unchecked checkbox).

Breaking Changes - ActionSheet:

  • The items and buttons properties are now internal(set), which means that they can only be set with init(...) or with setup(items:). This protects the integrity of the item and button separation logic.

  • The code no longer contains any didSet events, since these events called the same functionality many times. Call refresh if you change any outlets manually from now on.

  • Since the didSet events have been removed, refreshHeaderVisibility is only called once and has therefore been moved into refreshHeader.

  • Since the didSet events have been removed, refreshButtonsVisibility is now only called once and has therefore been moved into refreshButtons.

  • A small delay in handleTap(on:), that should not be needed, has been removed. Let me know if it causes any side-effects.

- 2018-11-24 22:07:59

This version adds new background color properties to the action sheet appearance, to make it possible to set the background color of the table views. The properties are called backgroundColor, itemsBackgroundColor and buttonsBackgroundColor. Note that the items still have their own background colors, which will overlap the table view background color.

This version also fixes a bug, where the background color behind an action sheet went black when the action sheet was presented in a split view.

- 2018-11-05 12:57:33

This version fixes a bug, where the presenters incorrectly updated the scrolling behavior of the action sheet when rotating the device.

- 2018-10-19 07:53:12

Sheeeeeeeeet 1.0.0 is finally here, with many internal changes and some external ones.

This version decouples action sheets from their presentation to great extent. An action sheet still styles its items and components, but the presenters now takes care of a lot more than before. The sheet setup is now also based on constraints instead of manual calculations, which means that popover scrolling etc. works by how the constraints are setup, instead of relying on manual calculations.

This should result in much more robust action sheets, but it requires testing on a wide range of devices and orientations before it can be released as a 1.0.

IMPORTANT The button item values have changed. Insted of true and nil they now have a strong ButtonType value. You can still create custom buttons with a custom value, though. You can also use the new isOkButton and isCancelButton extensions to quickly see if a user tapped "OK" or "Cancel".

Breaking changes

Since the presentation logic has been rewritten from scratch, you have to adjust your code to fit the new structure, if you have subclassed any presenter or made presentation tweaks in your sheets. The changes are too many and extensive to be listed here, so please have a look at the new structure. There is much less code, so changing your code to the new standard should be easy.

  • ActionSheetButton and its sublasses has new values.
  • ActionSheet.itemTapAction has been removed
  • ActionSheet.handleTap(on:) is now called when an item is tapped
  • ActionSheetAppearance.viewMargins is renamed to groupMargins
  • ActionSheetItem.itemType has been removed; just check the raw type
  • ActionSheetItem.handleTap(in:) no longer has a cell parameter
  • ActionSheetStandardPresenter is renamed to ActionSheetStandardPresenter

New features

  • ActionSheetAppearance has new properties, which adds new way to style sheets.
  • ActionSheetButton adds isOkButton and isCancelButton extension functions to ActionSheetItem. They can be used to quickly check if a cancel or ok button was tapped, instead of having to check if the item can be cast to a button type.

Bug fixes

  • The big presentation adjustments solves the scrolling issues that occured with popovers and many items.
  • The hideSeparator() function is adjusted to behave correctly when the device is rotated.

Deprecated logic

Instead of deprecating presentation-related properties and functions that are no longer used or available, I removed them completely. Let me know if you used any properties that are no longer available.

  • ActionSheetItem.setupItemsAndButtons(with:) is renamed to setup(items:)
  • ActionSheetItem.itemSelectAction is renamed to selectAction

Perform the deprecation warnings, and you should be all good. Deprecated members will be removed in the next minor version.