🧳 Library that makes it easy to create multiple environments within a single app. You can switch environments without deleting the application.

What's New



What's Changed

Full Changelog: 0.3.0...0.3.1


This library allows you to create and manage multiple environments with a single application, just as if you were swapping containers.

This is useful when you want to test multiple accounts in a staging application.

Github issues Github forks Github stars Github top language

Language Switch: 日本語.


Normally there is one environment (Directory, UserDefaults, Cookies, Cache, ...) for one app. To have multiple environments for debugging or to handle multiple accounts, multiple identical apps must be installed. (with different bundle IDs). In debugging, there may be cases where accounts are repeatedly checked by logging in and logging out.
Therefore, we thought it would be possible to create multiple environments within the same app and switch between them easily. This is why we created this library called AppContainer.


Default Debug1
Default Debug1
Selet Container Container List Container Info
Select List Info



extension AppContainer {
    static let group = .init(groupIdentifier: "YOUR APP GROUP IDENTIFIER")


Create New Container

let container = try AppContainer.standard.createNewContainer(name: "Debug1")

Get Container List

The original container is named DEFAULT and has a UUID of 00000000-0000-0000-0000-0000-0000-00000000000000000000. You can check it with the property isDefault.

let containers: [Container] = AppContainer.standard.containers

Get Active Container

let activeContainer: Container? = AppContainer.standard.activeContainer

Activate Contrainer

It is recommended to restart the application after calling this method.

try AppContainer.standard.activate(container: container)
try AppContainer.standard.activateContainer(uuid: uuid)

Delete Container

If the container you are deleting is in use, activate the Default container before deleting it.

try AppContainer.standard.delete(container: container)
try AppContainer.standard.deleteContainer(uuid: uuid)

Clean Container

try AppContainer.standard.clean(container: container)
try AppContainer.standard.cleanContainer(uuid: uuid)


Revert to the state before this library was used. Specifically, the DEFAULT container will be enabled and all other AppContainer-related files will be removed.

try AppContainer.standard.reset()


You can receive notifications when switching containers. If you want to add additional processing to be done strictly before and after the switch, use delegate as described below.

  • containerWillChangeNotification Before container switching
  • containerDidChangeNotification After container change


Delegate can be used to add optional processing when switching containers. The actions are performed in the following order.

// the `activate` method is called

// ↓↓↓↓↓↓↓↓↓↓

func appContainer(_ appContainer: AppContainer, willChangeTo toContainer: Container, from fromContainer: Container?) // Delegate(before container switch)

// ↓↓↓↓↓↓↓↓↓↓

// Container switching process (library)

// ↓↓↓↓↓↓↓↓↓↓

func appContainer(_ appContainer: AppContainer, didChangeTo toContainer: Container, from fromContainer: Container?) // Delegate (after container switch)

This library allows multiple delegates to be set. Add the following.

AppContainer.standard.delegates.add(self) // if self is AppContainerDelegate compliant

It is held in a weak reference and will be automatically released when the object is freed. If you want to unset the delegate, write the following.

AppContainer.standard.delegates.remove(self) // if self conforms to AppContainerDelegate

Set files not to be moved when switching containers

When switching containers, almost all files except for some system files are saved and restored to the container directory. You can set files to be excluded from these moves.

For example, the following is an example of a case where you want to use UserDefault commonly in all containers. This file will not be saved or restored when switching containers.

appcontainer.customExcludeFiles = [
    "Library/Preferences/<Bundle Identifier>.plist"

All file paths that end with the contents of customExcludeFiles will be excluded from the move. For example, the following configuration will exclude the file named XXX.yy under all directories.

appcontainer.customExcludeFiles = [


Provides UI for using AppContainer. SwiftUI and UIKit are supported.


import AppContainerUI

// show Container List
ContainerListView(appContainer: .standard, title: String = "Containers")

// container info view
ContainerInfoView(appContainer: .standard, container: container)


import AppContainerUI

// show Container List
ContainerListViewController(appContainer: .standard, title: String = "Containers")

// container info view
ContainerInfoViewController(appContainer: .standard, container: container)


MIT License


  • Swift Tools 5.9.0
View More Packages from this Author


Last updated: Sun Dec 03 2023 21:51:36 GMT-1000 (Hawaii-Aleutian Standard Time)