├── .gitignore
├── CHANGELOG.md
├── CONTRIBUTING.md
├── Demo
├── AppDelegate.swift
├── Base.lproj
│ ├── LaunchScreen.xib
│ └── Main.storyboard
├── Images.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Info.plist
├── KeychainSwiftCBridge.swift
└── ViewController.swift
├── Distrib
└── KeychainSwiftDistrib.swift
├── ISSUE_TEMPLATE.md
├── KeychainSwift.podspec
├── KeychainSwift.xcodeproj
├── project.pbxproj
├── project.xcworkspace
│ ├── contents.xcworkspacedata
│ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
└── xcshareddata
│ └── xcschemes
│ ├── ConcatenateSwiftFiles.xcscheme
│ ├── Demo.xcscheme
│ ├── KeychainSwift-macOS.xcscheme
│ ├── KeychainSwift-tvOS.xcscheme
│ ├── KeychainSwift-watchOS.xcscheme
│ ├── KeychainSwift.xcscheme
│ ├── macOS Demo.xcscheme
│ └── macOS Tests.xcscheme
├── LICENSE
├── Package.swift
├── README.md
├── Sources
├── Info.plist
├── KeychainSwift.h
├── KeychainSwift.swift
├── KeychainSwiftAccessOptions.swift
├── PrivacyInfo.xcprivacy
└── TegKeychainConstants.swift
├── Tests
└── KeychainSwiftTests
│ ├── AccessGroupTests.swift
│ ├── AllKeysTests.swift
│ ├── ClearTests.swift
│ ├── ConcurrencyTests.swift
│ ├── Info.plist
│ ├── KeychainSwiftPrefixedTests.swift
│ ├── KeychainSwiftTests-Bridging-Header.h
│ ├── KeychainSwiftTests.swift
│ ├── SynchronizableTests.swift
│ └── macOS Tests
│ ├── Info.plist
│ └── macOS_Tests.swift
├── graphics
├── keychain-swift-demo-3.png
└── keychain_swift_video_tutorial.jpg
├── macOS Demo
├── AppDelegate.swift
├── Assets.xcassets
│ └── AppIcon.appiconset
│ │ └── Contents.json
├── Base.lproj
│ └── Main.storyboard
├── Info.plist
└── ViewController.swift
└── scripts
└── concatenate_swift_files.sh
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | ./build
4 | *.pbxuser
5 | !default.pbxuser
6 | *.mode1v3
7 | !default.mode1v3
8 | *.mode2v3
9 | !default.mode2v3
10 | *.perspectivev3
11 | !default.perspectivev3
12 | xcuserdata
13 | *.xccheckout
14 | *.moved-aside
15 | DerivedData
16 | *.hmap
17 | *.ipa
18 | *.xcuserstate
19 | .DS_Store
20 | Carthage/Checkouts
21 | Carthage/Build
22 |
23 | # Swift package manager
24 | .build/
25 | Packages/
26 |
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | # KeychainSwift version history
2 |
3 | ## 24.0.0 (2024-05-26)
4 |
5 | Added privacy manifest as a resource bundle to CocoaPods Podspec file.
6 |
7 | ## 23.0.0 (2024-05-26)
8 |
9 | Reverted PR #188 (https://github.com/evgenyneu/keychain-swift/pull/188) since it introduced the issue when installing the library with CocoaPods (https://github.com/evgenyneu/keychain-swift/issues/185#issuecomment-2078297077).
10 |
11 | ## 22.0.0 (2024-04-05)
12 |
13 | Added privacy manifest as a resource to CocoaPods Podspec file (https://github.com/evgenyneu/keychain-swift/pull/188).
14 |
15 | ## 21.0.0 (2024-01-20)
16 |
17 | Added privacy manifest (Sources/PrivacyInfo.xcprivacy).
18 |
19 | ## 20.0.0 (2021-01-04)
20 |
21 | Update to Xcode 13.
22 |
23 | ## 19.0.0 (2020-01-04)
24 |
25 | Added `allKeys` property that returns all key names ([lucasmpaim](https://github.com/lucasmpaim)).
26 |
27 |
28 | ## 18.0.0 (2019-11-03)
29 |
30 | Removed deprecated `kSecAttrAccessibleAlways` and `kSecAttrAccessibleAlwaysThisDeviceOnly` access options (https://github.com/evgenyneu/keychain-swift/pull/122).
31 |
32 |
33 | ## 17.0.0 (2019-10-02)
34 |
35 | Added ability to run unit test from Swift Package Manager (https://github.com/evgenyneu/keychain-swift/pull/113).
36 |
37 |
38 | ## 16.0.0 (2019-05-28)
39 |
40 | Made all methods (get, set, delete and clear) thread-safe to prevent crashing when called from different threads.
41 |
42 |
43 | ## 15.0.0 (2019-04-24)
44 |
45 | Added ability to return data as reference ([mediym41](https://github.com/mediym41)).
46 |
47 |
48 | ## 14.0.0 (2019-04-03)
49 |
50 | Update to Swift 5.0 ([schayes04](https://github.com/schayes04)).
51 |
52 |
53 | ## 13.0.0 (2018-10-23)
54 |
55 | Increased watchOS deployment target to 3.0 ([xuaninbox](https://github.com/xuaninbox)).
56 |
57 |
58 | ## 12.0.0 (2018-09-19)
59 |
60 | Update to Swift 4.2 ([beny](https://github.com/beny)).
61 |
62 |
63 | ## 11.0.0 (2018-03-31)
64 |
65 | Added Swift language version to the podspec file for CocoaPods.
66 |
67 |
68 | ## 10.0.0 (2017-10-30)
69 |
70 | Fixed a crash in `getData` when called simultaneously from different threads ([details](https://github.com/evgenyneu/keychain-swift/pull/68)).
71 |
72 |
73 | ## 9.0.0 (2017-09-23)
74 |
75 | Update to Swift 4.0.
76 |
77 | ## 8.0.3 (2017-04-08)
78 |
79 | Fixed Package Manager setup ([maxkramerbcgdv](https://github.com/maxkramerbcgdv)).
80 |
81 | ## 8.0.0 (2017-04-08)
82 |
83 | Added Swif 3.1 support ([CraigSiemens](https://github.com/CraigSiemens)).
84 |
85 |
86 | ## 7.0.0 (2016-10-08)
87 |
88 | Swift package manager support ([diogoguimaraes](https://github.com/diogoguimaraes)).
89 |
90 |
91 | ## 6.0.2 (2016-09-11)
92 |
93 | Change the `public` access modifier to `open` to allow subclassing of the `KeychainSwift` class and overriding its methods ([djensenius](https://github.com/djensenius)).
94 |
95 |
96 | ## 6.0.0 (2016-08-20)
97 |
98 | Update to Xcode 8 beta 6 (thanks, [Tulleb](https://github.com/Tulleb)).
99 |
100 |
101 | ## 5.0.0 (2016-08-13)
102 |
103 | Update to Xcode 8 beta 4/5.
104 |
105 |
106 | ## 3.0.15 (2016-05-19)
107 |
108 | Added the ability to sychronize items on multiple devices (thank you, [mikaoj](https://github.com/mikaoj)).
109 |
110 |
111 | ## 3.0.13 (2016-04-15)
112 |
113 | Added iOS 7 support (https://github.com/marketplacer/keychain-swift/blob/iOS7/Distrib/KeychainSwiftDistrib.swift)
114 |
115 |
116 | ## 3.0.11 (2016-01-24)
117 |
118 | Added methods for setting/getting booleans.
119 |
120 |
121 | ## 3.0.9 (2015-11-09)
122 |
123 | Moved repository to https://github.com/marketplacer/keychain-swift
124 |
125 |
126 | ## 3.0.8 (2015-11-02)
127 |
128 | Added `lastResultCode` property.
129 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing guidlines
2 |
3 | Thank you for contributing to Keychain Swift library. Feel free to create an issue if you notice a bug or need help.
4 |
5 |
6 | ## Useful things to mention in an issue message
7 |
8 | * Library setup method: file, Carthage, CocoaPods or Swift Package Manager.
9 | * Version of the library, if known. Example: 8.0.
10 | * Xcode version. Example: 8.3.3.
11 | * OS version. Example: iOS 10.3.2.
12 |
13 | ## Submitting a pull request
14 |
15 | Before extending the library please first consider creating an issue to discuss what you are planning to add. Please note that this library is not a full featured wrapper around Keychain API. The purpose of this project is to do few things and do them well. There are many excellent [alternative solutions](https://github.com/evgenyneu/keychain-swift#alternative-solutions) that provide additional features to people who need them. This project, in contrast, is a single-purpose tool that sacrifices functionality in favor of the ease of use.
16 |
--------------------------------------------------------------------------------
/Demo/AppDelegate.swift:
--------------------------------------------------------------------------------
1 |
2 | import UIKit
3 |
4 | @UIApplicationMain
5 | class AppDelegate: UIResponder, UIApplicationDelegate {
6 |
7 | var window: UIWindow?
8 |
9 |
10 | private func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
11 | // Override point for customization after application launch.
12 | return true
13 | }
14 |
15 | func applicationWillResignActive(_ application: UIApplication) {
16 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
17 | // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
18 | }
19 |
20 | func applicationDidEnterBackground(_ application: UIApplication) {
21 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
22 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
23 | }
24 |
25 | func applicationWillEnterForeground(_ application: UIApplication) {
26 | // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
27 | }
28 |
29 | func applicationDidBecomeActive(_ application: UIApplication) {
30 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
31 | }
32 |
33 | func applicationWillTerminate(_ application: UIApplication) {
34 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
35 | }
36 |
37 |
38 | }
39 |
40 |
--------------------------------------------------------------------------------
/Demo/Base.lproj/LaunchScreen.xib:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
24 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
--------------------------------------------------------------------------------
/Demo/Base.lproj/Main.storyboard:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
31 |
40 |
45 |
46 |
47 |
48 |
49 |
50 |
55 |
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 |
--------------------------------------------------------------------------------
/Demo/Images.xcassets/AppIcon.appiconset/Contents.json:
--------------------------------------------------------------------------------
1 | {
2 | "images" : [
3 | {
4 | "idiom" : "iphone",
5 | "size" : "29x29",
6 | "scale" : "2x"
7 | },
8 | {
9 | "idiom" : "iphone",
10 | "size" : "29x29",
11 | "scale" : "3x"
12 | },
13 | {
14 | "idiom" : "iphone",
15 | "size" : "40x40",
16 | "scale" : "2x"
17 | },
18 | {
19 | "idiom" : "iphone",
20 | "size" : "40x40",
21 | "scale" : "3x"
22 | },
23 | {
24 | "idiom" : "iphone",
25 | "size" : "60x60",
26 | "scale" : "2x"
27 | },
28 | {
29 | "idiom" : "iphone",
30 | "size" : "60x60",
31 | "scale" : "3x"
32 | },
33 | {
34 | "idiom" : "ipad",
35 | "size" : "29x29",
36 | "scale" : "1x"
37 | },
38 | {
39 | "idiom" : "ipad",
40 | "size" : "29x29",
41 | "scale" : "2x"
42 | },
43 | {
44 | "idiom" : "ipad",
45 | "size" : "40x40",
46 | "scale" : "1x"
47 | },
48 | {
49 | "idiom" : "ipad",
50 | "size" : "40x40",
51 | "scale" : "2x"
52 | },
53 | {
54 | "idiom" : "ipad",
55 | "size" : "76x76",
56 | "scale" : "1x"
57 | },
58 | {
59 | "idiom" : "ipad",
60 | "size" : "76x76",
61 | "scale" : "2x"
62 | }
63 | ],
64 | "info" : {
65 | "version" : 1,
66 | "author" : "xcode"
67 | }
68 | }
--------------------------------------------------------------------------------
/Demo/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 | APPL
17 | CFBundleShortVersionString
18 | 1.0
19 | CFBundleSignature
20 | ????
21 | CFBundleVersion
22 | 1
23 | LSRequiresIPhoneOS
24 |
25 | UILaunchStoryboardName
26 | LaunchScreen
27 | UIMainStoryboardFile
28 | Main
29 | UIRequiredDeviceCapabilities
30 |
31 | armv7
32 |
33 | UISupportedInterfaceOrientations
34 |
35 | UIInterfaceOrientationPortrait
36 | UIInterfaceOrientationLandscapeLeft
37 | UIInterfaceOrientationLandscapeRight
38 |
39 | UISupportedInterfaceOrientations~ipad
40 |
41 | UIInterfaceOrientationPortrait
42 | UIInterfaceOrientationPortraitUpsideDown
43 | UIInterfaceOrientationLandscapeLeft
44 | UIInterfaceOrientationLandscapeRight
45 |
46 |
47 |
48 |
--------------------------------------------------------------------------------
/Demo/KeychainSwiftCBridge.swift:
--------------------------------------------------------------------------------
1 | import Security
2 | import Foundation
3 | import KeychainSwift // You might need to remove this import in your project
4 |
5 | /**
6 |
7 | This file can be used in your ObjC project if you want to use KeychainSwift Swift library.
8 | Extend this file to add other functionality for your app.
9 |
10 | How to use
11 | ----------
12 |
13 | 1. Import swift code in your ObjC file:
14 |
15 | #import "YOUR_PRODUCT_MODULE_NAME-Swift.h"
16 |
17 | 2. Use KeychainSwift in your ObjC code:
18 |
19 | - (void)viewDidLoad {
20 | [super viewDidLoad];
21 |
22 | KeychainSwiftCBridge *keychain = [[KeychainSwiftCBridge alloc] init];
23 | [keychain set:@"Hello World" forKey:@"my key"];
24 | NSString *value = [keychain get:@"my key"];
25 |
26 | 3. You might need to remove `import KeychainSwift` import from this file in your project.
27 |
28 | */
29 | @objcMembers public class KeychainSwiftCBridge: NSObject {
30 | let keychain = KeychainSwift()
31 |
32 | open var lastResultCode: OSStatus {
33 | get { return keychain.lastResultCode }
34 | }
35 |
36 | open var accessGroup: String? {
37 | set { keychain.accessGroup = newValue }
38 | get { return keychain.accessGroup }
39 | }
40 |
41 | open var synchronizable: Bool {
42 | set { keychain.synchronizable = newValue }
43 | get { return keychain.synchronizable }
44 | }
45 |
46 |
47 | @discardableResult
48 | open func set(_ value: String, forKey key: String) -> Bool {
49 | return keychain.set(value, forKey: key)
50 | }
51 |
52 | @discardableResult
53 | open func setData(_ value: Data, forKey key: String) -> Bool {
54 | return keychain.set(value, forKey: key)
55 | }
56 |
57 | @discardableResult
58 | open func setBool(_ value: Bool, forKey key: String) -> Bool {
59 | return keychain.set(value, forKey: key)
60 | }
61 |
62 | open func get(_ key: String) -> String? {
63 | return keychain.get(key)
64 | }
65 |
66 | open func getData(_ key: String) -> Data? {
67 | return keychain.getData(key)
68 | }
69 |
70 | open func getBool(_ key: String) -> Bool? {
71 | return keychain.getBool(key)
72 | }
73 |
74 | @discardableResult
75 | open func delete(_ key: String) -> Bool {
76 | return keychain.delete(key);
77 | }
78 |
79 | @discardableResult
80 | open func clear() -> Bool {
81 | return keychain.clear()
82 | }
83 | }
84 |
--------------------------------------------------------------------------------
/Demo/ViewController.swift:
--------------------------------------------------------------------------------
1 | import UIKit
2 | import KeychainSwift
3 |
4 | let TegKeychainDemo_keyName = "my key"
5 |
6 | class ViewController: UIViewController {
7 |
8 | @IBOutlet weak var textField: UITextField!
9 |
10 | @IBOutlet weak var valueLabel: UILabel!
11 |
12 | @IBOutlet weak var synchronizableSwitch: UISwitch!
13 |
14 | let keychain = KeychainSwift()
15 |
16 | override func viewDidLoad() {
17 | super.viewDidLoad()
18 |
19 | updateValueLabel()
20 | }
21 |
22 | @IBAction func onSaveTapped(_ sender: AnyObject) {
23 | closeKeyboard()
24 |
25 | if let text = textField.text {
26 | keychain.synchronizable = synchronizableSwitch.isOn
27 | keychain.set(text, forKey: TegKeychainDemo_keyName)
28 | updateValueLabel()
29 | }
30 | }
31 |
32 | @IBAction func onDeleteTapped(_ sender: AnyObject) {
33 | closeKeyboard()
34 |
35 | keychain.synchronizable = synchronizableSwitch.isOn
36 | keychain.delete(TegKeychainDemo_keyName)
37 | updateValueLabel()
38 | }
39 |
40 | @IBAction func onGetTapped(_ sender: AnyObject) {
41 | closeKeyboard()
42 |
43 | updateValueLabel()
44 | }
45 |
46 | private func updateValueLabel() {
47 | keychain.synchronizable = synchronizableSwitch.isOn
48 |
49 | if let value = keychain.get(TegKeychainDemo_keyName) {
50 | valueLabel.text = "In Keychain: \(value)"
51 | } else {
52 | valueLabel.text = "no value in keychain"
53 | }
54 | }
55 |
56 | private func closeKeyboard() {
57 | textField.resignFirstResponder()
58 | }
59 |
60 | @IBAction func didTapView(_ sender: AnyObject) {
61 | closeKeyboard()
62 | }
63 | }
64 |
--------------------------------------------------------------------------------
/Distrib/KeychainSwiftDistrib.swift:
--------------------------------------------------------------------------------
1 | //
2 | // Keychain helper for iOS/Swift.
3 | //
4 | // https://github.com/evgenyneu/keychain-swift
5 | //
6 | // This file was automatically generated by combining multiple Swift source files.
7 | //
8 |
9 |
10 | // ----------------------------
11 | //
12 | // KeychainSwift.swift
13 | //
14 | // ----------------------------
15 |
16 | import Security
17 | import Foundation
18 |
19 | /**
20 |
21 | A collection of helper functions for saving text and data in the keychain.
22 |
23 | */
24 | open class KeychainSwift {
25 |
26 | var lastQueryParameters: [String: Any]? // Used by the unit tests
27 |
28 | /// Contains result code from the last operation. Value is noErr (0) for a successful result.
29 | open var lastResultCode: OSStatus = noErr
30 |
31 | var keyPrefix = "" // Can be useful in test.
32 |
33 | /**
34 |
35 | Specify an access group that will be used to access keychain items. Access groups can be used to share keychain items between applications. When access group value is nil all application access groups are being accessed. Access group name is used by all functions: set, get, delete and clear.
36 |
37 | */
38 | open var accessGroup: String?
39 |
40 |
41 | /**
42 |
43 | Specifies whether the items can be synchronized with other devices through iCloud. Setting this property to true will
44 | add the item to other devices with the `set` method and obtain synchronizable items with the `get` command. Deleting synchronizable items will remove them from all devices. In order for keychain synchronization to work the user must enable "Keychain" in iCloud settings.
45 |
46 | Does not work on macOS.
47 |
48 | */
49 | open var synchronizable: Bool = false
50 |
51 | private let lock = NSLock()
52 |
53 |
54 | /// Instantiate a KeychainSwift object
55 | public init() { }
56 |
57 | /**
58 |
59 | - parameter keyPrefix: a prefix that is added before the key in get/set methods. Note that `clear` method still clears everything from the Keychain.
60 |
61 | */
62 | public init(keyPrefix: String) {
63 | self.keyPrefix = keyPrefix
64 | }
65 |
66 | /**
67 |
68 | Stores the text value in the keychain item under the given key.
69 |
70 | - parameter key: Key under which the text value is stored in the keychain.
71 | - parameter value: Text string to be written to the keychain.
72 | - parameter withAccess: Value that indicates when your app needs access to the text in the keychain item. By default the .AccessibleWhenUnlocked option is used that permits the data to be accessed only while the device is unlocked by the user.
73 |
74 | - returns: True if the text was successfully written to the keychain.
75 |
76 | */
77 | @discardableResult
78 | open func set(_ value: String, forKey key: String,
79 | withAccess access: KeychainSwiftAccessOptions? = nil) -> Bool {
80 |
81 | if let value = value.data(using: String.Encoding.utf8) {
82 | return set(value, forKey: key, withAccess: access)
83 | }
84 |
85 | return false
86 | }
87 |
88 | /**
89 |
90 | Stores the data in the keychain item under the given key.
91 |
92 | - parameter key: Key under which the data is stored in the keychain.
93 | - parameter value: Data to be written to the keychain.
94 | - parameter withAccess: Value that indicates when your app needs access to the text in the keychain item. By default the .AccessibleWhenUnlocked option is used that permits the data to be accessed only while the device is unlocked by the user.
95 |
96 | - returns: True if the text was successfully written to the keychain.
97 |
98 | */
99 | @discardableResult
100 | open func set(_ value: Data, forKey key: String,
101 | withAccess access: KeychainSwiftAccessOptions? = nil) -> Bool {
102 |
103 | // The lock prevents the code to be run simultaneously
104 | // from multiple threads which may result in crashing
105 | lock.lock()
106 | defer { lock.unlock() }
107 |
108 | deleteNoLock(key) // Delete any existing key before saving it
109 |
110 | let accessible = access?.value ?? KeychainSwiftAccessOptions.defaultOption.value
111 |
112 | let prefixedKey = keyWithPrefix(key)
113 |
114 | var query: [String : Any] = [
115 | KeychainSwiftConstants.klass : kSecClassGenericPassword,
116 | KeychainSwiftConstants.attrAccount : prefixedKey,
117 | KeychainSwiftConstants.valueData : value,
118 | KeychainSwiftConstants.accessible : accessible
119 | ]
120 |
121 | query = addAccessGroupWhenPresent(query)
122 | query = addSynchronizableIfRequired(query, addingItems: true)
123 | lastQueryParameters = query
124 |
125 | lastResultCode = SecItemAdd(query as CFDictionary, nil)
126 |
127 | return lastResultCode == noErr
128 | }
129 |
130 | /**
131 |
132 | Stores the boolean value in the keychain item under the given key.
133 |
134 | - parameter key: Key under which the value is stored in the keychain.
135 | - parameter value: Boolean to be written to the keychain.
136 | - parameter withAccess: Value that indicates when your app needs access to the value in the keychain item. By default the .AccessibleWhenUnlocked option is used that permits the data to be accessed only while the device is unlocked by the user.
137 |
138 | - returns: True if the value was successfully written to the keychain.
139 |
140 | */
141 | @discardableResult
142 | open func set(_ value: Bool, forKey key: String,
143 | withAccess access: KeychainSwiftAccessOptions? = nil) -> Bool {
144 |
145 | let bytes: [UInt8] = value ? [1] : [0]
146 | let data = Data(bytes)
147 |
148 | return set(data, forKey: key, withAccess: access)
149 | }
150 |
151 | /**
152 |
153 | Retrieves the text value from the keychain that corresponds to the given key.
154 |
155 | - parameter key: The key that is used to read the keychain item.
156 | - returns: The text value from the keychain. Returns nil if unable to read the item.
157 |
158 | */
159 | open func get(_ key: String) -> String? {
160 | if let data = getData(key) {
161 |
162 | if let currentString = String(data: data, encoding: .utf8) {
163 | return currentString
164 | }
165 |
166 | lastResultCode = -67853 // errSecInvalidEncoding
167 | }
168 |
169 | return nil
170 | }
171 |
172 | /**
173 |
174 | Retrieves the data from the keychain that corresponds to the given key.
175 |
176 | - parameter key: The key that is used to read the keychain item.
177 | - parameter asReference: If true, returns the data as reference (needed for things like NEVPNProtocol).
178 | - returns: The text value from the keychain. Returns nil if unable to read the item.
179 |
180 | */
181 | open func getData(_ key: String, asReference: Bool = false) -> Data? {
182 | // The lock prevents the code to be run simultaneously
183 | // from multiple threads which may result in crashing
184 | lock.lock()
185 | defer { lock.unlock() }
186 |
187 | let prefixedKey = keyWithPrefix(key)
188 |
189 | var query: [String: Any] = [
190 | KeychainSwiftConstants.klass : kSecClassGenericPassword,
191 | KeychainSwiftConstants.attrAccount : prefixedKey,
192 | KeychainSwiftConstants.matchLimit : kSecMatchLimitOne
193 | ]
194 |
195 | if asReference {
196 | query[KeychainSwiftConstants.returnReference] = kCFBooleanTrue
197 | } else {
198 | query[KeychainSwiftConstants.returnData] = kCFBooleanTrue
199 | }
200 |
201 | query = addAccessGroupWhenPresent(query)
202 | query = addSynchronizableIfRequired(query, addingItems: false)
203 | lastQueryParameters = query
204 |
205 | var result: AnyObject?
206 |
207 | lastResultCode = withUnsafeMutablePointer(to: &result) {
208 | SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
209 | }
210 |
211 | if lastResultCode == noErr {
212 | return result as? Data
213 | }
214 |
215 | return nil
216 | }
217 |
218 | /**
219 |
220 | Retrieves the boolean value from the keychain that corresponds to the given key.
221 |
222 | - parameter key: The key that is used to read the keychain item.
223 | - returns: The boolean value from the keychain. Returns nil if unable to read the item.
224 |
225 | */
226 | open func getBool(_ key: String) -> Bool? {
227 | guard let data = getData(key) else { return nil }
228 | guard let firstBit = data.first else { return nil }
229 | return firstBit == 1
230 | }
231 |
232 | /**
233 |
234 | Deletes the single keychain item specified by the key.
235 |
236 | - parameter key: The key that is used to delete the keychain item.
237 | - returns: True if the item was successfully deleted.
238 |
239 | */
240 | @discardableResult
241 | open func delete(_ key: String) -> Bool {
242 | // The lock prevents the code to be run simultaneously
243 | // from multiple threads which may result in crashing
244 | lock.lock()
245 | defer { lock.unlock() }
246 |
247 | return deleteNoLock(key)
248 | }
249 |
250 | /**
251 | Return all keys from keychain
252 |
253 | - returns: An string array with all keys from the keychain.
254 |
255 | */
256 | public var allKeys: [String] {
257 | var query: [String: Any] = [
258 | KeychainSwiftConstants.klass : kSecClassGenericPassword,
259 | KeychainSwiftConstants.returnData : true,
260 | KeychainSwiftConstants.returnAttributes: true,
261 | KeychainSwiftConstants.returnReference: true,
262 | KeychainSwiftConstants.matchLimit: KeychainSwiftConstants.secMatchLimitAll
263 | ]
264 |
265 | query = addAccessGroupWhenPresent(query)
266 | query = addSynchronizableIfRequired(query, addingItems: false)
267 |
268 | var result: AnyObject?
269 |
270 | let lastResultCode = withUnsafeMutablePointer(to: &result) {
271 | SecItemCopyMatching(query as CFDictionary, UnsafeMutablePointer($0))
272 | }
273 |
274 | if lastResultCode == noErr {
275 | return (result as? [[String: Any]])?.compactMap {
276 | $0[KeychainSwiftConstants.attrAccount] as? String } ?? []
277 | }
278 |
279 | return []
280 | }
281 |
282 | /**
283 |
284 | Same as `delete` but is only accessed internally, since it is not thread safe.
285 |
286 | - parameter key: The key that is used to delete the keychain item.
287 | - returns: True if the item was successfully deleted.
288 |
289 | */
290 | @discardableResult
291 | func deleteNoLock(_ key: String) -> Bool {
292 | let prefixedKey = keyWithPrefix(key)
293 |
294 | var query: [String: Any] = [
295 | KeychainSwiftConstants.klass : kSecClassGenericPassword,
296 | KeychainSwiftConstants.attrAccount : prefixedKey
297 | ]
298 |
299 | query = addAccessGroupWhenPresent(query)
300 | query = addSynchronizableIfRequired(query, addingItems: false)
301 | lastQueryParameters = query
302 |
303 | lastResultCode = SecItemDelete(query as CFDictionary)
304 |
305 | return lastResultCode == noErr
306 | }
307 |
308 | /**
309 |
310 | Deletes all Keychain items used by the app. Note that this method deletes all items regardless of the prefix settings used for initializing the class.
311 |
312 | - returns: True if the keychain items were successfully deleted.
313 |
314 | */
315 | @discardableResult
316 | open func clear() -> Bool {
317 | // The lock prevents the code to be run simultaneously
318 | // from multiple threads which may result in crashing
319 | lock.lock()
320 | defer { lock.unlock() }
321 |
322 | var query: [String: Any] = [ kSecClass as String : kSecClassGenericPassword ]
323 | query = addAccessGroupWhenPresent(query)
324 | query = addSynchronizableIfRequired(query, addingItems: false)
325 | lastQueryParameters = query
326 |
327 | lastResultCode = SecItemDelete(query as CFDictionary)
328 |
329 | return lastResultCode == noErr
330 | }
331 |
332 | /// Returns the key with currently set prefix.
333 | func keyWithPrefix(_ key: String) -> String {
334 | return "\(keyPrefix)\(key)"
335 | }
336 |
337 | func addAccessGroupWhenPresent(_ items: [String: Any]) -> [String: Any] {
338 | guard let accessGroup = accessGroup else { return items }
339 |
340 | var result: [String: Any] = items
341 | result[KeychainSwiftConstants.accessGroup] = accessGroup
342 | return result
343 | }
344 |
345 | /**
346 |
347 | Adds kSecAttrSynchronizable: kSecAttrSynchronizableAny` item to the dictionary when the `synchronizable` property is true.
348 |
349 | - parameter items: The dictionary where the kSecAttrSynchronizable items will be added when requested.
350 | - parameter addingItems: Use `true` when the dictionary will be used with `SecItemAdd` method (adding a keychain item). For getting and deleting items, use `false`.
351 |
352 | - returns: the dictionary with kSecAttrSynchronizable item added if it was requested. Otherwise, it returns the original dictionary.
353 |
354 | */
355 | func addSynchronizableIfRequired(_ items: [String: Any], addingItems: Bool) -> [String: Any] {
356 | if !synchronizable { return items }
357 | var result: [String: Any] = items
358 | result[KeychainSwiftConstants.attrSynchronizable] = addingItems == true ? true : kSecAttrSynchronizableAny
359 | return result
360 | }
361 | }
362 |
363 |
364 | // ----------------------------
365 | //
366 | // TegKeychainConstants.swift
367 | //
368 | // ----------------------------
369 |
370 | import Foundation
371 | import Security
372 |
373 | /// Constants used by the library
374 | public struct KeychainSwiftConstants {
375 | /// Specifies a Keychain access group. Used for sharing Keychain items between apps.
376 | public static var accessGroup: String { return toString(kSecAttrAccessGroup) }
377 |
378 | /**
379 |
380 | A value that indicates when your app needs access to the data in a keychain item. The default value is AccessibleWhenUnlocked. For a list of possible values, see KeychainSwiftAccessOptions.
381 |
382 | */
383 | public static var accessible: String { return toString(kSecAttrAccessible) }
384 |
385 | /// Used for specifying a String key when setting/getting a Keychain value.
386 | public static var attrAccount: String { return toString(kSecAttrAccount) }
387 |
388 | /// Used for specifying synchronization of keychain items between devices.
389 | public static var attrSynchronizable: String { return toString(kSecAttrSynchronizable) }
390 |
391 | /// An item class key used to construct a Keychain search dictionary.
392 | public static var klass: String { return toString(kSecClass) }
393 |
394 | /// Specifies the number of values returned from the keychain. The library only supports single values.
395 | public static var matchLimit: String { return toString(kSecMatchLimit) }
396 |
397 | /// A return data type used to get the data from the Keychain.
398 | public static var returnData: String { return toString(kSecReturnData) }
399 |
400 | /// Used for specifying a value when setting a Keychain value.
401 | public static var valueData: String { return toString(kSecValueData) }
402 |
403 | /// Used for returning a reference to the data from the keychain
404 | public static var returnReference: String { return toString(kSecReturnPersistentRef) }
405 |
406 | /// A key whose value is a Boolean indicating whether or not to return item attributes
407 | public static var returnAttributes : String { return toString(kSecReturnAttributes) }
408 |
409 | /// A value that corresponds to matching an unlimited number of items
410 | public static var secMatchLimitAll : String { return toString(kSecMatchLimitAll) }
411 |
412 | static func toString(_ value: CFString) -> String {
413 | return value as String
414 | }
415 | }
416 |
417 |
418 | // ----------------------------
419 | //
420 | // KeychainSwiftAccessOptions.swift
421 | //
422 | // ----------------------------
423 |
424 | import Security
425 |
426 | /**
427 |
428 | These options are used to determine when a keychain item should be readable. The default value is AccessibleWhenUnlocked.
429 |
430 | */
431 | public enum KeychainSwiftAccessOptions {
432 |
433 | /**
434 |
435 | The data in the keychain item can be accessed only while the device is unlocked by the user.
436 |
437 | This is recommended for items that need to be accessible only while the application is in the foreground. Items with this attribute migrate to a new device when using encrypted backups.
438 |
439 | This is the default value for keychain items added without explicitly setting an accessibility constant.
440 |
441 | */
442 | case accessibleWhenUnlocked
443 |
444 | /**
445 |
446 | The data in the keychain item can be accessed only while the device is unlocked by the user.
447 |
448 | This is recommended for items that need to be accessible only while the application is in the foreground. Items with this attribute do not migrate to a new device. Thus, after restoring from a backup of a different device, these items will not be present.
449 |
450 | */
451 | case accessibleWhenUnlockedThisDeviceOnly
452 |
453 | /**
454 |
455 | The data in the keychain item cannot be accessed after a restart until the device has been unlocked once by the user.
456 |
457 | After the first unlock, the data remains accessible until the next restart. This is recommended for items that need to be accessed by background applications. Items with this attribute migrate to a new device when using encrypted backups.
458 |
459 | */
460 | case accessibleAfterFirstUnlock
461 |
462 | /**
463 |
464 | The data in the keychain item cannot be accessed after a restart until the device has been unlocked once by the user.
465 |
466 | After the first unlock, the data remains accessible until the next restart. This is recommended for items that need to be accessed by background applications. Items with this attribute do not migrate to a new device. Thus, after restoring from a backup of a different device, these items will not be present.
467 |
468 | */
469 | case accessibleAfterFirstUnlockThisDeviceOnly
470 |
471 | /**
472 |
473 | The data in the keychain can only be accessed when the device is unlocked. Only available if a passcode is set on the device.
474 |
475 | This is recommended for items that only need to be accessible while the application is in the foreground. Items with this attribute never migrate to a new device. After a backup is restored to a new device, these items are missing. No items can be stored in this class on devices without a passcode. Disabling the device passcode causes all items in this class to be deleted.
476 |
477 | */
478 | case accessibleWhenPasscodeSetThisDeviceOnly
479 |
480 | static var defaultOption: KeychainSwiftAccessOptions {
481 | return .accessibleWhenUnlocked
482 | }
483 |
484 | var value: String {
485 | switch self {
486 | case .accessibleWhenUnlocked:
487 | return toString(kSecAttrAccessibleWhenUnlocked)
488 |
489 | case .accessibleWhenUnlockedThisDeviceOnly:
490 | return toString(kSecAttrAccessibleWhenUnlockedThisDeviceOnly)
491 |
492 | case .accessibleAfterFirstUnlock:
493 | return toString(kSecAttrAccessibleAfterFirstUnlock)
494 |
495 | case .accessibleAfterFirstUnlockThisDeviceOnly:
496 | return toString(kSecAttrAccessibleAfterFirstUnlockThisDeviceOnly)
497 |
498 | case .accessibleWhenPasscodeSetThisDeviceOnly:
499 | return toString(kSecAttrAccessibleWhenPasscodeSetThisDeviceOnly)
500 | }
501 | }
502 |
503 | func toString(_ value: CFString) -> String {
504 | return KeychainSwiftConstants.toString(value)
505 | }
506 | }
507 |
508 |
509 |
--------------------------------------------------------------------------------
/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | Please consider submitting the following information (if relevant):
2 |
3 | * Library setup method: file, Carthage, CocoaPods or Swift Package Manager.
4 | * Version of the library. Example: 8.0.
5 | * Xcode version. Example: 8.3.3.
6 | * OS version. Example: iOS 10.3.2.
--------------------------------------------------------------------------------
/KeychainSwift.podspec:
--------------------------------------------------------------------------------
1 | Pod::Spec.new do |s|
2 | s.name = "KeychainSwift"
3 | s.version = "24.0.0"
4 | s.license = { :type => "MIT" }
5 | s.homepage = "https://github.com/evgenyneu/keychain-swift"
6 | s.summary = "A library for saving text and data in the Keychain with Swift."
7 | s.description = <<-DESC
8 | This is a collection of helper functions for saving text and data in the Keychain.
9 |
10 | * Write and read text and Data with simple functions.
11 | * Specify optional access rule for the keychain item.
12 | * Limit operations to a specific access group.
13 | DESC
14 | s.authors = { "Evgenii Neumerzhitckii" => "sausageskin@gmail.com" }
15 | s.source = { :git => "https://github.com/evgenyneu/keychain-swift.git", :tag => s.version }
16 | s.screenshots = "https://raw.githubusercontent.com/evgenyneu/keychain-swift/master/graphics/keychain-swift-demo-3.png"
17 | s.source_files = "Sources/*.swift"
18 | s.resource_bundles = {"KeychainSwift" => ["Sources/PrivacyInfo.xcprivacy"]}
19 | s.ios.deployment_target = "12.0"
20 | s.osx.deployment_target = "10.13"
21 | s.watchos.deployment_target = "4.0"
22 | s.tvos.deployment_target = "12.0"
23 | s.swift_version = "5.0"
24 | end
25 |
--------------------------------------------------------------------------------
/KeychainSwift.xcodeproj/project.pbxproj:
--------------------------------------------------------------------------------
1 | // !$*UTF8*$!
2 | {
3 | archiveVersion = 1;
4 | classes = {
5 | };
6 | objectVersion = 46;
7 | objects = {
8 |
9 | /* Begin PBXBuildFile section */
10 | 232B4C821BC2995D001F2B7A /* KeychainSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ED6C98D1B1C128100FE8090 /* KeychainSwift.swift */; };
11 | 232B4C831BC2995D001F2B7A /* KeychainSwiftAccessOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ED6C98E1B1C128100FE8090 /* KeychainSwiftAccessOptions.swift */; };
12 | 232B4C841BC2995D001F2B7A /* TegKeychainConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ED6C98F1B1C128100FE8090 /* TegKeychainConstants.swift */; };
13 | 232B4C921BC29991001F2B7A /* KeychainSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ED6C98D1B1C128100FE8090 /* KeychainSwift.swift */; };
14 | 232B4C931BC29991001F2B7A /* KeychainSwiftAccessOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ED6C98E1B1C128100FE8090 /* KeychainSwiftAccessOptions.swift */; };
15 | 232B4C941BC29991001F2B7A /* TegKeychainConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ED6C98F1B1C128100FE8090 /* TegKeychainConstants.swift */; };
16 | 23E785681BDA415000B7564A /* KeychainSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ED6C98D1B1C128100FE8090 /* KeychainSwift.swift */; };
17 | 23E785691BDA415000B7564A /* KeychainSwiftAccessOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ED6C98E1B1C128100FE8090 /* KeychainSwiftAccessOptions.swift */; };
18 | 23E7856A1BDA415000B7564A /* TegKeychainConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ED6C98F1B1C128100FE8090 /* TegKeychainConstants.swift */; };
19 | 5085669B1FA34EB1004208ED /* AccessGroupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 508566911FA34EB1004208ED /* AccessGroupTests.swift */; };
20 | 5085669C1FA34EB1004208ED /* AccessGroupTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 508566911FA34EB1004208ED /* AccessGroupTests.swift */; };
21 | 5085669D1FA34EB1004208ED /* ClearTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 508566921FA34EB1004208ED /* ClearTests.swift */; };
22 | 508566A11FA34EB1004208ED /* KeychainSwiftPrefixedTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 508566941FA34EB1004208ED /* KeychainSwiftPrefixedTests.swift */; };
23 | 508566A21FA34EB1004208ED /* KeychainSwiftPrefixedTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 508566941FA34EB1004208ED /* KeychainSwiftPrefixedTests.swift */; };
24 | 508566A31FA34EB1004208ED /* KeychainSwiftTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 508566961FA34EB1004208ED /* KeychainSwiftTests.swift */; };
25 | 508566A41FA34EB1004208ED /* KeychainSwiftTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 508566961FA34EB1004208ED /* KeychainSwiftTests.swift */; };
26 | 508566A71FA34EB1004208ED /* macOS_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 508566991FA34EB1004208ED /* macOS_Tests.swift */; };
27 | 508566A81FA34EB1004208ED /* macOS_Tests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 508566991FA34EB1004208ED /* macOS_Tests.swift */; };
28 | 508566A91FA34EB1004208ED /* SynchronizableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5085669A1FA34EB1004208ED /* SynchronizableTests.swift */; };
29 | 508566AA1FA34EB1004208ED /* SynchronizableTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5085669A1FA34EB1004208ED /* SynchronizableTests.swift */; };
30 | 7E3A6B7E1D3F6779007C5B1F /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E3A6B7D1D3F6779007C5B1F /* AppDelegate.swift */; };
31 | 7E3A6B801D3F6779007C5B1F /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7E3A6B7F1D3F6779007C5B1F /* ViewController.swift */; };
32 | 7E3A6B821D3F6779007C5B1F /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7E3A6B811D3F6779007C5B1F /* Assets.xcassets */; };
33 | 7E3A6B851D3F6779007C5B1F /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7E3A6B831D3F6779007C5B1F /* Main.storyboard */; };
34 | 7E3A6B8A1D3F67B1007C5B1F /* KeychainSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 232B4C7A1BC29950001F2B7A /* KeychainSwift.framework */; };
35 | 7E3A6B8B1D3F67B1007C5B1F /* KeychainSwift.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 232B4C7A1BC29950001F2B7A /* KeychainSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
36 | 7ED6C9721B1C118F00FE8090 /* KeychainSwift.h in Headers */ = {isa = PBXBuildFile; fileRef = 7ED6C9711B1C118F00FE8090 /* KeychainSwift.h */; settings = {ATTRIBUTES = (Public, ); }; };
37 | 7ED6C9781B1C118F00FE8090 /* KeychainSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7ED6C96C1B1C118F00FE8090 /* KeychainSwift.framework */; };
38 | 7ED6C9901B1C128100FE8090 /* KeychainSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ED6C98D1B1C128100FE8090 /* KeychainSwift.swift */; };
39 | 7ED6C9911B1C128100FE8090 /* KeychainSwiftAccessOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ED6C98E1B1C128100FE8090 /* KeychainSwiftAccessOptions.swift */; };
40 | 7ED6C9921B1C128100FE8090 /* TegKeychainConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ED6C98F1B1C128100FE8090 /* TegKeychainConstants.swift */; };
41 | 7ED6C9961B1C12B100FE8090 /* KeychainSwift.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ED6C98D1B1C128100FE8090 /* KeychainSwift.swift */; };
42 | 7ED6C9971B1C12B300FE8090 /* KeychainSwiftAccessOptions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ED6C98E1B1C128100FE8090 /* KeychainSwiftAccessOptions.swift */; };
43 | 7ED6C9981B1C12B500FE8090 /* TegKeychainConstants.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ED6C98F1B1C128100FE8090 /* TegKeychainConstants.swift */; };
44 | 7ED6C9A21B1C133500FE8090 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ED6C9A11B1C133500FE8090 /* AppDelegate.swift */; };
45 | 7ED6C9A41B1C133500FE8090 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7ED6C9A31B1C133500FE8090 /* ViewController.swift */; };
46 | 7ED6C9A71B1C133500FE8090 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 7ED6C9A51B1C133500FE8090 /* Main.storyboard */; };
47 | 7ED6C9A91B1C133500FE8090 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 7ED6C9A81B1C133500FE8090 /* Images.xcassets */; };
48 | 7ED6C9AC1B1C133500FE8090 /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 7ED6C9AA1B1C133500FE8090 /* LaunchScreen.xib */; };
49 | 7ED6C9BF1B1C13AA00FE8090 /* KeychainSwift.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7ED6C96C1B1C118F00FE8090 /* KeychainSwift.framework */; };
50 | 7ED6C9C01B1C13AA00FE8090 /* KeychainSwift.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 7ED6C96C1B1C118F00FE8090 /* KeychainSwift.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; };
51 | 7EE5B9A11E32F6D400AA56FF /* KeychainSwiftCBridge.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7EE5B9A01E32F6D400AA56FF /* KeychainSwiftCBridge.swift */; };
52 | C7E1DE4C1E4B7C9F003818F6 /* ConcurrencyTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = C7E1DE4A1E4B7C9F003818F6 /* ConcurrencyTests.swift */; };
53 | F271A1AE23BE071800FCC3B9 /* AllKeysTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F271A1AD23BE071800FCC3B9 /* AllKeysTests.swift */; };
54 | F271A1AF23BE082500FCC3B9 /* AllKeysTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = F271A1AD23BE071800FCC3B9 /* AllKeysTests.swift */; };
55 | /* End PBXBuildFile section */
56 |
57 | /* Begin PBXContainerItemProxy section */
58 | 7E3A6B8C1D3F67B1007C5B1F /* PBXContainerItemProxy */ = {
59 | isa = PBXContainerItemProxy;
60 | containerPortal = 7ED6C9631B1C118F00FE8090 /* Project object */;
61 | proxyType = 1;
62 | remoteGlobalIDString = 232B4C791BC29950001F2B7A;
63 | remoteInfo = "KeychainSwift-macOS";
64 | };
65 | 7EC243561E3301D600C771BE /* PBXContainerItemProxy */ = {
66 | isa = PBXContainerItemProxy;
67 | containerPortal = 7ED6C9631B1C118F00FE8090 /* Project object */;
68 | proxyType = 1;
69 | remoteGlobalIDString = 7ED6C99C1B1C133500FE8090;
70 | remoteInfo = Demo;
71 | };
72 | 7ED6C9791B1C118F00FE8090 /* PBXContainerItemProxy */ = {
73 | isa = PBXContainerItemProxy;
74 | containerPortal = 7ED6C9631B1C118F00FE8090 /* Project object */;
75 | proxyType = 1;
76 | remoteGlobalIDString = 7ED6C96B1B1C118F00FE8090;
77 | remoteInfo = KeychainSwift;
78 | };
79 | 7ED6C9C11B1C13AA00FE8090 /* PBXContainerItemProxy */ = {
80 | isa = PBXContainerItemProxy;
81 | containerPortal = 7ED6C9631B1C118F00FE8090 /* Project object */;
82 | proxyType = 1;
83 | remoteGlobalIDString = 7ED6C96B1B1C118F00FE8090;
84 | remoteInfo = KeychainSwift;
85 | };
86 | BF4250102343FE8400F7B44C /* PBXContainerItemProxy */ = {
87 | isa = PBXContainerItemProxy;
88 | containerPortal = 7ED6C9631B1C118F00FE8090 /* Project object */;
89 | proxyType = 1;
90 | remoteGlobalIDString = 232B4C791BC29950001F2B7A;
91 | remoteInfo = "KeychainSwift-macOS";
92 | };
93 | /* End PBXContainerItemProxy section */
94 |
95 | /* Begin PBXCopyFilesBuildPhase section */
96 | 7E3A6B8E1D3F67B1007C5B1F /* Embed Frameworks */ = {
97 | isa = PBXCopyFilesBuildPhase;
98 | buildActionMask = 2147483647;
99 | dstPath = "";
100 | dstSubfolderSpec = 10;
101 | files = (
102 | 7E3A6B8B1D3F67B1007C5B1F /* KeychainSwift.framework in Embed Frameworks */,
103 | );
104 | name = "Embed Frameworks";
105 | runOnlyForDeploymentPostprocessing = 0;
106 | };
107 | 7ED6C9C31B1C13AA00FE8090 /* Embed Frameworks */ = {
108 | isa = PBXCopyFilesBuildPhase;
109 | buildActionMask = 2147483647;
110 | dstPath = "";
111 | dstSubfolderSpec = 10;
112 | files = (
113 | 7ED6C9C01B1C13AA00FE8090 /* KeychainSwift.framework in Embed Frameworks */,
114 | );
115 | name = "Embed Frameworks";
116 | runOnlyForDeploymentPostprocessing = 0;
117 | };
118 | /* End PBXCopyFilesBuildPhase section */
119 |
120 | /* Begin PBXFileReference section */
121 | 232B4C7A1BC29950001F2B7A /* KeychainSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = KeychainSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
122 | 232B4C8A1BC29984001F2B7A /* KeychainSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = KeychainSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
123 | 23E785601BDA410C00B7564A /* KeychainSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = KeychainSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
124 | 508566911FA34EB1004208ED /* AccessGroupTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AccessGroupTests.swift; sourceTree = ""; };
125 | 508566921FA34EB1004208ED /* ClearTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ClearTests.swift; sourceTree = ""; };
126 | 508566931FA34EB1004208ED /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
127 | 508566941FA34EB1004208ED /* KeychainSwiftPrefixedTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeychainSwiftPrefixedTests.swift; sourceTree = ""; };
128 | 508566951FA34EB1004208ED /* KeychainSwiftTests-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "KeychainSwiftTests-Bridging-Header.h"; sourceTree = ""; };
129 | 508566961FA34EB1004208ED /* KeychainSwiftTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeychainSwiftTests.swift; sourceTree = ""; };
130 | 508566981FA34EB1004208ED /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
131 | 508566991FA34EB1004208ED /* macOS_Tests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = macOS_Tests.swift; sourceTree = ""; };
132 | 5085669A1FA34EB1004208ED /* SynchronizableTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SynchronizableTests.swift; sourceTree = ""; };
133 | 7E3A6B601D3F62C2007C5B1F /* macOS Tests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "macOS Tests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
134 | 7E3A6B7B1D3F6779007C5B1F /* macOS Demo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "macOS Demo.app"; sourceTree = BUILT_PRODUCTS_DIR; };
135 | 7E3A6B7D1D3F6779007C5B1F /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
136 | 7E3A6B7F1D3F6779007C5B1F /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
137 | 7E3A6B811D3F6779007C5B1F /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; };
138 | 7E3A6B841D3F6779007C5B1F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
139 | 7E3A6B861D3F6779007C5B1F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
140 | 7E6EC4402B4900CC0064B6B1 /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; lastKnownFileType = text.xml; path = PrivacyInfo.xcprivacy; sourceTree = ""; };
141 | 7ED6C96C1B1C118F00FE8090 /* KeychainSwift.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = KeychainSwift.framework; sourceTree = BUILT_PRODUCTS_DIR; };
142 | 7ED6C9701B1C118F00FE8090 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
143 | 7ED6C9711B1C118F00FE8090 /* KeychainSwift.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KeychainSwift.h; sourceTree = ""; };
144 | 7ED6C9771B1C118F00FE8090 /* KeychainSwiftTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = KeychainSwiftTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
145 | 7ED6C9881B1C125000FE8090 /* README.md */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = net.daringfireball.markdown; path = README.md; sourceTree = ""; };
146 | 7ED6C98B1B1C126D00FE8090 /* keychain-swift-demo-3.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "keychain-swift-demo-3.png"; sourceTree = ""; };
147 | 7ED6C98D1B1C128100FE8090 /* KeychainSwift.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeychainSwift.swift; sourceTree = ""; };
148 | 7ED6C98E1B1C128100FE8090 /* KeychainSwiftAccessOptions.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeychainSwiftAccessOptions.swift; sourceTree = ""; };
149 | 7ED6C98F1B1C128100FE8090 /* TegKeychainConstants.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TegKeychainConstants.swift; sourceTree = ""; };
150 | 7ED6C99D1B1C133500FE8090 /* Keychain Swift.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Keychain Swift.app"; sourceTree = BUILT_PRODUCTS_DIR; };
151 | 7ED6C9A01B1C133500FE8090 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; };
152 | 7ED6C9A11B1C133500FE8090 /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; };
153 | 7ED6C9A31B1C133500FE8090 /* ViewController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; };
154 | 7ED6C9A61B1C133500FE8090 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; };
155 | 7ED6C9A81B1C133500FE8090 /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; };
156 | 7ED6C9AB1B1C133500FE8090 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; };
157 | 7ED6C9C61B1C16BC00FE8090 /* concatenate_swift_files.sh */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.script.sh; path = concatenate_swift_files.sh; sourceTree = ""; };
158 | 7ED6C9C91B1C16EE00FE8090 /* KeychainSwiftDistrib.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeychainSwiftDistrib.swift; sourceTree = ""; };
159 | 7EE5B9A01E32F6D400AA56FF /* KeychainSwiftCBridge.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeychainSwiftCBridge.swift; sourceTree = ""; };
160 | C7E1DE4A1E4B7C9F003818F6 /* ConcurrencyTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ConcurrencyTests.swift; sourceTree = ""; };
161 | F271A1AD23BE071800FCC3B9 /* AllKeysTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AllKeysTests.swift; sourceTree = ""; };
162 | /* End PBXFileReference section */
163 |
164 | /* Begin PBXFrameworksBuildPhase section */
165 | 232B4C761BC29950001F2B7A /* Frameworks */ = {
166 | isa = PBXFrameworksBuildPhase;
167 | buildActionMask = 2147483647;
168 | files = (
169 | );
170 | runOnlyForDeploymentPostprocessing = 0;
171 | };
172 | 232B4C861BC29984001F2B7A /* Frameworks */ = {
173 | isa = PBXFrameworksBuildPhase;
174 | buildActionMask = 2147483647;
175 | files = (
176 | );
177 | runOnlyForDeploymentPostprocessing = 0;
178 | };
179 | 23E7855C1BDA410C00B7564A /* Frameworks */ = {
180 | isa = PBXFrameworksBuildPhase;
181 | buildActionMask = 2147483647;
182 | files = (
183 | );
184 | runOnlyForDeploymentPostprocessing = 0;
185 | };
186 | 7E3A6B5D1D3F62C2007C5B1F /* Frameworks */ = {
187 | isa = PBXFrameworksBuildPhase;
188 | buildActionMask = 2147483647;
189 | files = (
190 | );
191 | runOnlyForDeploymentPostprocessing = 0;
192 | };
193 | 7E3A6B781D3F6779007C5B1F /* Frameworks */ = {
194 | isa = PBXFrameworksBuildPhase;
195 | buildActionMask = 2147483647;
196 | files = (
197 | 7E3A6B8A1D3F67B1007C5B1F /* KeychainSwift.framework in Frameworks */,
198 | );
199 | runOnlyForDeploymentPostprocessing = 0;
200 | };
201 | 7ED6C9681B1C118F00FE8090 /* Frameworks */ = {
202 | isa = PBXFrameworksBuildPhase;
203 | buildActionMask = 2147483647;
204 | files = (
205 | );
206 | runOnlyForDeploymentPostprocessing = 0;
207 | };
208 | 7ED6C9741B1C118F00FE8090 /* Frameworks */ = {
209 | isa = PBXFrameworksBuildPhase;
210 | buildActionMask = 2147483647;
211 | files = (
212 | 7ED6C9781B1C118F00FE8090 /* KeychainSwift.framework in Frameworks */,
213 | );
214 | runOnlyForDeploymentPostprocessing = 0;
215 | };
216 | 7ED6C99A1B1C133500FE8090 /* Frameworks */ = {
217 | isa = PBXFrameworksBuildPhase;
218 | buildActionMask = 2147483647;
219 | files = (
220 | 7ED6C9BF1B1C13AA00FE8090 /* KeychainSwift.framework in Frameworks */,
221 | );
222 | runOnlyForDeploymentPostprocessing = 0;
223 | };
224 | /* End PBXFrameworksBuildPhase section */
225 |
226 | /* Begin PBXGroup section */
227 | 508566901FA34EB1004208ED /* KeychainSwiftTests */ = {
228 | isa = PBXGroup;
229 | children = (
230 | 508566911FA34EB1004208ED /* AccessGroupTests.swift */,
231 | 508566921FA34EB1004208ED /* ClearTests.swift */,
232 | C7E1DE4A1E4B7C9F003818F6 /* ConcurrencyTests.swift */,
233 | 508566931FA34EB1004208ED /* Info.plist */,
234 | 508566941FA34EB1004208ED /* KeychainSwiftPrefixedTests.swift */,
235 | 508566951FA34EB1004208ED /* KeychainSwiftTests-Bridging-Header.h */,
236 | 508566961FA34EB1004208ED /* KeychainSwiftTests.swift */,
237 | 508566971FA34EB1004208ED /* macOS Tests */,
238 | 5085669A1FA34EB1004208ED /* SynchronizableTests.swift */,
239 | F271A1AD23BE071800FCC3B9 /* AllKeysTests.swift */,
240 | );
241 | path = KeychainSwiftTests;
242 | sourceTree = "";
243 | };
244 | 508566971FA34EB1004208ED /* macOS Tests */ = {
245 | isa = PBXGroup;
246 | children = (
247 | 508566981FA34EB1004208ED /* Info.plist */,
248 | 508566991FA34EB1004208ED /* macOS_Tests.swift */,
249 | );
250 | path = "macOS Tests";
251 | sourceTree = "";
252 | };
253 | 7E3A6B7C1D3F6779007C5B1F /* macOS Demo */ = {
254 | isa = PBXGroup;
255 | children = (
256 | 7E3A6B7D1D3F6779007C5B1F /* AppDelegate.swift */,
257 | 7E3A6B7F1D3F6779007C5B1F /* ViewController.swift */,
258 | 7E3A6B811D3F6779007C5B1F /* Assets.xcassets */,
259 | 7E3A6B831D3F6779007C5B1F /* Main.storyboard */,
260 | 7E3A6B861D3F6779007C5B1F /* Info.plist */,
261 | );
262 | path = "macOS Demo";
263 | sourceTree = "";
264 | };
265 | 7ED6C9621B1C118F00FE8090 = {
266 | isa = PBXGroup;
267 | children = (
268 | 7ED6C96E1B1C118F00FE8090 /* Sources */,
269 | 7ED6C97B1B1C118F00FE8090 /* Tests */,
270 | 7ED6C99E1B1C133500FE8090 /* Demo */,
271 | 7ED6C98A1B1C126D00FE8090 /* graphics */,
272 | 7ED6C9C81B1C16EE00FE8090 /* Distrib */,
273 | 7ED6C9C51B1C16BC00FE8090 /* scripts */,
274 | 7E3A6B7C1D3F6779007C5B1F /* macOS Demo */,
275 | 7ED6C96D1B1C118F00FE8090 /* Products */,
276 | 7ED6C9881B1C125000FE8090 /* README.md */,
277 | );
278 | sourceTree = "";
279 | };
280 | 7ED6C96D1B1C118F00FE8090 /* Products */ = {
281 | isa = PBXGroup;
282 | children = (
283 | 7ED6C96C1B1C118F00FE8090 /* KeychainSwift.framework */,
284 | 7ED6C9771B1C118F00FE8090 /* KeychainSwiftTests.xctest */,
285 | 7ED6C99D1B1C133500FE8090 /* Keychain Swift.app */,
286 | 232B4C7A1BC29950001F2B7A /* KeychainSwift.framework */,
287 | 232B4C8A1BC29984001F2B7A /* KeychainSwift.framework */,
288 | 23E785601BDA410C00B7564A /* KeychainSwift.framework */,
289 | 7E3A6B601D3F62C2007C5B1F /* macOS Tests.xctest */,
290 | 7E3A6B7B1D3F6779007C5B1F /* macOS Demo.app */,
291 | );
292 | name = Products;
293 | sourceTree = "";
294 | };
295 | 7ED6C96E1B1C118F00FE8090 /* Sources */ = {
296 | isa = PBXGroup;
297 | children = (
298 | 7ED6C98D1B1C128100FE8090 /* KeychainSwift.swift */,
299 | 7ED6C98E1B1C128100FE8090 /* KeychainSwiftAccessOptions.swift */,
300 | 7ED6C98F1B1C128100FE8090 /* TegKeychainConstants.swift */,
301 | 7ED6C9711B1C118F00FE8090 /* KeychainSwift.h */,
302 | 7ED6C96F1B1C118F00FE8090 /* Supporting Files */,
303 | 7E6EC4402B4900CC0064B6B1 /* PrivacyInfo.xcprivacy */,
304 | );
305 | path = Sources;
306 | sourceTree = "";
307 | };
308 | 7ED6C96F1B1C118F00FE8090 /* Supporting Files */ = {
309 | isa = PBXGroup;
310 | children = (
311 | 7ED6C9701B1C118F00FE8090 /* Info.plist */,
312 | );
313 | name = "Supporting Files";
314 | sourceTree = "";
315 | };
316 | 7ED6C97B1B1C118F00FE8090 /* Tests */ = {
317 | isa = PBXGroup;
318 | children = (
319 | 508566901FA34EB1004208ED /* KeychainSwiftTests */,
320 | );
321 | path = Tests;
322 | sourceTree = "";
323 | };
324 | 7ED6C98A1B1C126D00FE8090 /* graphics */ = {
325 | isa = PBXGroup;
326 | children = (
327 | 7ED6C98B1B1C126D00FE8090 /* keychain-swift-demo-3.png */,
328 | );
329 | path = graphics;
330 | sourceTree = "";
331 | };
332 | 7ED6C99E1B1C133500FE8090 /* Demo */ = {
333 | isa = PBXGroup;
334 | children = (
335 | 7ED6C9A11B1C133500FE8090 /* AppDelegate.swift */,
336 | 7ED6C9A31B1C133500FE8090 /* ViewController.swift */,
337 | 7EE5B9A01E32F6D400AA56FF /* KeychainSwiftCBridge.swift */,
338 | 7ED6C9A51B1C133500FE8090 /* Main.storyboard */,
339 | 7ED6C9A81B1C133500FE8090 /* Images.xcassets */,
340 | 7ED6C9AA1B1C133500FE8090 /* LaunchScreen.xib */,
341 | 7ED6C99F1B1C133500FE8090 /* Supporting Files */,
342 | );
343 | path = Demo;
344 | sourceTree = "";
345 | };
346 | 7ED6C99F1B1C133500FE8090 /* Supporting Files */ = {
347 | isa = PBXGroup;
348 | children = (
349 | 7ED6C9A01B1C133500FE8090 /* Info.plist */,
350 | );
351 | name = "Supporting Files";
352 | sourceTree = "";
353 | };
354 | 7ED6C9C51B1C16BC00FE8090 /* scripts */ = {
355 | isa = PBXGroup;
356 | children = (
357 | 7ED6C9C61B1C16BC00FE8090 /* concatenate_swift_files.sh */,
358 | );
359 | path = scripts;
360 | sourceTree = "";
361 | };
362 | 7ED6C9C81B1C16EE00FE8090 /* Distrib */ = {
363 | isa = PBXGroup;
364 | children = (
365 | 7ED6C9C91B1C16EE00FE8090 /* KeychainSwiftDistrib.swift */,
366 | );
367 | path = Distrib;
368 | sourceTree = "";
369 | };
370 | /* End PBXGroup section */
371 |
372 | /* Begin PBXHeadersBuildPhase section */
373 | 232B4C771BC29950001F2B7A /* Headers */ = {
374 | isa = PBXHeadersBuildPhase;
375 | buildActionMask = 2147483647;
376 | files = (
377 | );
378 | runOnlyForDeploymentPostprocessing = 0;
379 | };
380 | 232B4C871BC29984001F2B7A /* Headers */ = {
381 | isa = PBXHeadersBuildPhase;
382 | buildActionMask = 2147483647;
383 | files = (
384 | );
385 | runOnlyForDeploymentPostprocessing = 0;
386 | };
387 | 23E7855D1BDA410C00B7564A /* Headers */ = {
388 | isa = PBXHeadersBuildPhase;
389 | buildActionMask = 2147483647;
390 | files = (
391 | );
392 | runOnlyForDeploymentPostprocessing = 0;
393 | };
394 | 7ED6C9691B1C118F00FE8090 /* Headers */ = {
395 | isa = PBXHeadersBuildPhase;
396 | buildActionMask = 2147483647;
397 | files = (
398 | 7ED6C9721B1C118F00FE8090 /* KeychainSwift.h in Headers */,
399 | );
400 | runOnlyForDeploymentPostprocessing = 0;
401 | };
402 | /* End PBXHeadersBuildPhase section */
403 |
404 | /* Begin PBXLegacyTarget section */
405 | 7ED51A751B7734AF005B39C2 /* ConcatenateSwiftFiles */ = {
406 | isa = PBXLegacyTarget;
407 | buildArgumentsString = "$PROJECT_DIR/Sources $PROJECT_DIR/Distrib/KeychainSwiftDistrib.swift \"//\n// Keychain helper for iOS/Swift.\n//\n// https://github.com/evgenyneu/keychain-swift\n//\n// This file was automatically generated by combining multiple Swift source files.\n//\"";
408 | buildConfigurationList = 7ED51A781B7734AF005B39C2 /* Build configuration list for PBXLegacyTarget "ConcatenateSwiftFiles" */;
409 | buildPhases = (
410 | );
411 | buildToolPath = $PROJECT_DIR/scripts/concatenate_swift_files.sh;
412 | buildWorkingDirectory = "";
413 | dependencies = (
414 | );
415 | name = ConcatenateSwiftFiles;
416 | passBuildSettingsInEnvironment = 1;
417 | productName = ConcatenateSwiftFiles;
418 | };
419 | /* End PBXLegacyTarget section */
420 |
421 | /* Begin PBXNativeTarget section */
422 | 232B4C791BC29950001F2B7A /* KeychainSwift-macOS */ = {
423 | isa = PBXNativeTarget;
424 | buildConfigurationList = 232B4C7F1BC29950001F2B7A /* Build configuration list for PBXNativeTarget "KeychainSwift-macOS" */;
425 | buildPhases = (
426 | 232B4C751BC29950001F2B7A /* Sources */,
427 | 232B4C761BC29950001F2B7A /* Frameworks */,
428 | 232B4C771BC29950001F2B7A /* Headers */,
429 | 232B4C781BC29950001F2B7A /* Resources */,
430 | );
431 | buildRules = (
432 | );
433 | dependencies = (
434 | );
435 | name = "KeychainSwift-macOS";
436 | productName = "KeychainSwift-OSX";
437 | productReference = 232B4C7A1BC29950001F2B7A /* KeychainSwift.framework */;
438 | productType = "com.apple.product-type.framework";
439 | };
440 | 232B4C891BC29984001F2B7A /* KeychainSwift-watchOS */ = {
441 | isa = PBXNativeTarget;
442 | buildConfigurationList = 232B4C8F1BC29984001F2B7A /* Build configuration list for PBXNativeTarget "KeychainSwift-watchOS" */;
443 | buildPhases = (
444 | 232B4C851BC29984001F2B7A /* Sources */,
445 | 232B4C861BC29984001F2B7A /* Frameworks */,
446 | 232B4C871BC29984001F2B7A /* Headers */,
447 | 232B4C881BC29984001F2B7A /* Resources */,
448 | );
449 | buildRules = (
450 | );
451 | dependencies = (
452 | );
453 | name = "KeychainSwift-watchOS";
454 | productName = "KeychainSwift-watchOS";
455 | productReference = 232B4C8A1BC29984001F2B7A /* KeychainSwift.framework */;
456 | productType = "com.apple.product-type.framework";
457 | };
458 | 23E7855F1BDA410C00B7564A /* KeychainSwift-tvOS */ = {
459 | isa = PBXNativeTarget;
460 | buildConfigurationList = 23E785651BDA410C00B7564A /* Build configuration list for PBXNativeTarget "KeychainSwift-tvOS" */;
461 | buildPhases = (
462 | 23E7855B1BDA410C00B7564A /* Sources */,
463 | 23E7855C1BDA410C00B7564A /* Frameworks */,
464 | 23E7855D1BDA410C00B7564A /* Headers */,
465 | 23E7855E1BDA410C00B7564A /* Resources */,
466 | );
467 | buildRules = (
468 | );
469 | dependencies = (
470 | );
471 | name = "KeychainSwift-tvOS";
472 | productName = "KeychainSwift-tvOS";
473 | productReference = 23E785601BDA410C00B7564A /* KeychainSwift.framework */;
474 | productType = "com.apple.product-type.framework";
475 | };
476 | 7E3A6B5F1D3F62C2007C5B1F /* macOS Tests */ = {
477 | isa = PBXNativeTarget;
478 | buildConfigurationList = 7E3A6B671D3F62C2007C5B1F /* Build configuration list for PBXNativeTarget "macOS Tests" */;
479 | buildPhases = (
480 | 7E3A6B5C1D3F62C2007C5B1F /* Sources */,
481 | 7E3A6B5D1D3F62C2007C5B1F /* Frameworks */,
482 | 7E3A6B5E1D3F62C2007C5B1F /* Resources */,
483 | );
484 | buildRules = (
485 | );
486 | dependencies = (
487 | BF4250112343FE8400F7B44C /* PBXTargetDependency */,
488 | );
489 | name = "macOS Tests";
490 | productName = "macOS Tests";
491 | productReference = 7E3A6B601D3F62C2007C5B1F /* macOS Tests.xctest */;
492 | productType = "com.apple.product-type.bundle.ui-testing";
493 | };
494 | 7E3A6B7A1D3F6779007C5B1F /* macOS Demo */ = {
495 | isa = PBXNativeTarget;
496 | buildConfigurationList = 7E3A6B891D3F6779007C5B1F /* Build configuration list for PBXNativeTarget "macOS Demo" */;
497 | buildPhases = (
498 | 7E3A6B771D3F6779007C5B1F /* Sources */,
499 | 7E3A6B781D3F6779007C5B1F /* Frameworks */,
500 | 7E3A6B791D3F6779007C5B1F /* Resources */,
501 | 7E3A6B8E1D3F67B1007C5B1F /* Embed Frameworks */,
502 | );
503 | buildRules = (
504 | );
505 | dependencies = (
506 | 7E3A6B8D1D3F67B1007C5B1F /* PBXTargetDependency */,
507 | );
508 | name = "macOS Demo";
509 | productName = "macOS Demo";
510 | productReference = 7E3A6B7B1D3F6779007C5B1F /* macOS Demo.app */;
511 | productType = "com.apple.product-type.application";
512 | };
513 | 7ED6C96B1B1C118F00FE8090 /* KeychainSwift */ = {
514 | isa = PBXNativeTarget;
515 | buildConfigurationList = 7ED6C9821B1C118F00FE8090 /* Build configuration list for PBXNativeTarget "KeychainSwift" */;
516 | buildPhases = (
517 | 7ED6C9671B1C118F00FE8090 /* Sources */,
518 | 7ED6C9681B1C118F00FE8090 /* Frameworks */,
519 | 7ED6C9691B1C118F00FE8090 /* Headers */,
520 | 7ED6C96A1B1C118F00FE8090 /* Resources */,
521 | );
522 | buildRules = (
523 | );
524 | dependencies = (
525 | );
526 | name = KeychainSwift;
527 | productName = KeychainSwift;
528 | productReference = 7ED6C96C1B1C118F00FE8090 /* KeychainSwift.framework */;
529 | productType = "com.apple.product-type.framework";
530 | };
531 | 7ED6C9761B1C118F00FE8090 /* KeychainSwiftTests */ = {
532 | isa = PBXNativeTarget;
533 | buildConfigurationList = 7ED6C9851B1C118F00FE8090 /* Build configuration list for PBXNativeTarget "KeychainSwiftTests" */;
534 | buildPhases = (
535 | 7ED6C9731B1C118F00FE8090 /* Sources */,
536 | 7ED6C9741B1C118F00FE8090 /* Frameworks */,
537 | 7ED6C9751B1C118F00FE8090 /* Resources */,
538 | );
539 | buildRules = (
540 | );
541 | dependencies = (
542 | 7ED6C97A1B1C118F00FE8090 /* PBXTargetDependency */,
543 | 7EC243571E3301D600C771BE /* PBXTargetDependency */,
544 | );
545 | name = KeychainSwiftTests;
546 | productName = KeychainSwiftTests;
547 | productReference = 7ED6C9771B1C118F00FE8090 /* KeychainSwiftTests.xctest */;
548 | productType = "com.apple.product-type.bundle.unit-test";
549 | };
550 | 7ED6C99C1B1C133500FE8090 /* Demo */ = {
551 | isa = PBXNativeTarget;
552 | buildConfigurationList = 7ED6C9B91B1C133500FE8090 /* Build configuration list for PBXNativeTarget "Demo" */;
553 | buildPhases = (
554 | 7ED6C9991B1C133500FE8090 /* Sources */,
555 | 7ED6C99A1B1C133500FE8090 /* Frameworks */,
556 | 7ED6C99B1B1C133500FE8090 /* Resources */,
557 | 7ED6C9C31B1C13AA00FE8090 /* Embed Frameworks */,
558 | );
559 | buildRules = (
560 | );
561 | dependencies = (
562 | 7ED6C9C21B1C13AA00FE8090 /* PBXTargetDependency */,
563 | );
564 | name = Demo;
565 | productName = Demo;
566 | productReference = 7ED6C99D1B1C133500FE8090 /* Keychain Swift.app */;
567 | productType = "com.apple.product-type.application";
568 | };
569 | /* End PBXNativeTarget section */
570 |
571 | /* Begin PBXProject section */
572 | 7ED6C9631B1C118F00FE8090 /* Project object */ = {
573 | isa = PBXProject;
574 | attributes = {
575 | LastSwiftUpdateCheck = 0800;
576 | LastUpgradeCheck = 1320;
577 | ORGANIZATIONNAME = "Evgenii Neumerzhitckii";
578 | TargetAttributes = {
579 | 232B4C791BC29950001F2B7A = {
580 | CreatedOnToolsVersion = 7.0.1;
581 | DevelopmentTeam = BS677JRE62;
582 | DevelopmentTeamName = "Evgenii Neumerzhitckii";
583 | LastSwiftMigration = 0900;
584 | };
585 | 232B4C891BC29984001F2B7A = {
586 | CreatedOnToolsVersion = 7.0.1;
587 | LastSwiftMigration = 0900;
588 | };
589 | 23E7855F1BDA410C00B7564A = {
590 | CreatedOnToolsVersion = 7.1;
591 | LastSwiftMigration = 0900;
592 | };
593 | 7E3A6B5F1D3F62C2007C5B1F = {
594 | CreatedOnToolsVersion = 8.0;
595 | DevelopmentTeam = BS677JRE62;
596 | DevelopmentTeamName = "Evgenii Neumerzhitckii";
597 | LastSwiftMigration = 0900;
598 | ProvisioningStyle = Automatic;
599 | };
600 | 7E3A6B7A1D3F6779007C5B1F = {
601 | CreatedOnToolsVersion = 8.0;
602 | DevelopmentTeam = BS677JRE62;
603 | DevelopmentTeamName = "Evgenii Neumerzhitckii";
604 | LastSwiftMigration = 0900;
605 | ProvisioningStyle = Automatic;
606 | };
607 | 7ED51A751B7734AF005B39C2 = {
608 | CreatedOnToolsVersion = 7.0;
609 | };
610 | 7ED6C96B1B1C118F00FE8090 = {
611 | CreatedOnToolsVersion = 6.4;
612 | LastSwiftMigration = 1020;
613 | };
614 | 7ED6C9761B1C118F00FE8090 = {
615 | CreatedOnToolsVersion = 6.4;
616 | LastSwiftMigration = 1020;
617 | ProvisioningStyle = Manual;
618 | TestTargetID = 7ED6C99C1B1C133500FE8090;
619 | };
620 | 7ED6C99C1B1C133500FE8090 = {
621 | CreatedOnToolsVersion = 6.4;
622 | LastSwiftMigration = 1020;
623 | };
624 | };
625 | };
626 | buildConfigurationList = 7ED6C9661B1C118F00FE8090 /* Build configuration list for PBXProject "KeychainSwift" */;
627 | compatibilityVersion = "Xcode 3.2";
628 | developmentRegion = en;
629 | hasScannedForEncodings = 0;
630 | knownRegions = (
631 | en,
632 | Base,
633 | );
634 | mainGroup = 7ED6C9621B1C118F00FE8090;
635 | productRefGroup = 7ED6C96D1B1C118F00FE8090 /* Products */;
636 | projectDirPath = "";
637 | projectRoot = "";
638 | targets = (
639 | 7ED6C96B1B1C118F00FE8090 /* KeychainSwift */,
640 | 232B4C791BC29950001F2B7A /* KeychainSwift-macOS */,
641 | 232B4C891BC29984001F2B7A /* KeychainSwift-watchOS */,
642 | 23E7855F1BDA410C00B7564A /* KeychainSwift-tvOS */,
643 | 7ED6C9761B1C118F00FE8090 /* KeychainSwiftTests */,
644 | 7ED6C99C1B1C133500FE8090 /* Demo */,
645 | 7ED51A751B7734AF005B39C2 /* ConcatenateSwiftFiles */,
646 | 7E3A6B5F1D3F62C2007C5B1F /* macOS Tests */,
647 | 7E3A6B7A1D3F6779007C5B1F /* macOS Demo */,
648 | );
649 | };
650 | /* End PBXProject section */
651 |
652 | /* Begin PBXResourcesBuildPhase section */
653 | 232B4C781BC29950001F2B7A /* Resources */ = {
654 | isa = PBXResourcesBuildPhase;
655 | buildActionMask = 2147483647;
656 | files = (
657 | );
658 | runOnlyForDeploymentPostprocessing = 0;
659 | };
660 | 232B4C881BC29984001F2B7A /* Resources */ = {
661 | isa = PBXResourcesBuildPhase;
662 | buildActionMask = 2147483647;
663 | files = (
664 | );
665 | runOnlyForDeploymentPostprocessing = 0;
666 | };
667 | 23E7855E1BDA410C00B7564A /* Resources */ = {
668 | isa = PBXResourcesBuildPhase;
669 | buildActionMask = 2147483647;
670 | files = (
671 | );
672 | runOnlyForDeploymentPostprocessing = 0;
673 | };
674 | 7E3A6B5E1D3F62C2007C5B1F /* Resources */ = {
675 | isa = PBXResourcesBuildPhase;
676 | buildActionMask = 2147483647;
677 | files = (
678 | );
679 | runOnlyForDeploymentPostprocessing = 0;
680 | };
681 | 7E3A6B791D3F6779007C5B1F /* Resources */ = {
682 | isa = PBXResourcesBuildPhase;
683 | buildActionMask = 2147483647;
684 | files = (
685 | 7E3A6B821D3F6779007C5B1F /* Assets.xcassets in Resources */,
686 | 7E3A6B851D3F6779007C5B1F /* Main.storyboard in Resources */,
687 | );
688 | runOnlyForDeploymentPostprocessing = 0;
689 | };
690 | 7ED6C96A1B1C118F00FE8090 /* Resources */ = {
691 | isa = PBXResourcesBuildPhase;
692 | buildActionMask = 2147483647;
693 | files = (
694 | );
695 | runOnlyForDeploymentPostprocessing = 0;
696 | };
697 | 7ED6C9751B1C118F00FE8090 /* Resources */ = {
698 | isa = PBXResourcesBuildPhase;
699 | buildActionMask = 2147483647;
700 | files = (
701 | );
702 | runOnlyForDeploymentPostprocessing = 0;
703 | };
704 | 7ED6C99B1B1C133500FE8090 /* Resources */ = {
705 | isa = PBXResourcesBuildPhase;
706 | buildActionMask = 2147483647;
707 | files = (
708 | 7ED6C9A71B1C133500FE8090 /* Main.storyboard in Resources */,
709 | 7ED6C9AC1B1C133500FE8090 /* LaunchScreen.xib in Resources */,
710 | 7ED6C9A91B1C133500FE8090 /* Images.xcassets in Resources */,
711 | );
712 | runOnlyForDeploymentPostprocessing = 0;
713 | };
714 | /* End PBXResourcesBuildPhase section */
715 |
716 | /* Begin PBXSourcesBuildPhase section */
717 | 232B4C751BC29950001F2B7A /* Sources */ = {
718 | isa = PBXSourcesBuildPhase;
719 | buildActionMask = 2147483647;
720 | files = (
721 | 232B4C821BC2995D001F2B7A /* KeychainSwift.swift in Sources */,
722 | 232B4C831BC2995D001F2B7A /* KeychainSwiftAccessOptions.swift in Sources */,
723 | 232B4C841BC2995D001F2B7A /* TegKeychainConstants.swift in Sources */,
724 | );
725 | runOnlyForDeploymentPostprocessing = 0;
726 | };
727 | 232B4C851BC29984001F2B7A /* Sources */ = {
728 | isa = PBXSourcesBuildPhase;
729 | buildActionMask = 2147483647;
730 | files = (
731 | 232B4C921BC29991001F2B7A /* KeychainSwift.swift in Sources */,
732 | 232B4C931BC29991001F2B7A /* KeychainSwiftAccessOptions.swift in Sources */,
733 | 232B4C941BC29991001F2B7A /* TegKeychainConstants.swift in Sources */,
734 | );
735 | runOnlyForDeploymentPostprocessing = 0;
736 | };
737 | 23E7855B1BDA410C00B7564A /* Sources */ = {
738 | isa = PBXSourcesBuildPhase;
739 | buildActionMask = 2147483647;
740 | files = (
741 | 23E785681BDA415000B7564A /* KeychainSwift.swift in Sources */,
742 | 23E785691BDA415000B7564A /* KeychainSwiftAccessOptions.swift in Sources */,
743 | 23E7856A1BDA415000B7564A /* TegKeychainConstants.swift in Sources */,
744 | );
745 | runOnlyForDeploymentPostprocessing = 0;
746 | };
747 | 7E3A6B5C1D3F62C2007C5B1F /* Sources */ = {
748 | isa = PBXSourcesBuildPhase;
749 | buildActionMask = 2147483647;
750 | files = (
751 | 508566AA1FA34EB1004208ED /* SynchronizableTests.swift in Sources */,
752 | F271A1AF23BE082500FCC3B9 /* AllKeysTests.swift in Sources */,
753 | 508566A41FA34EB1004208ED /* KeychainSwiftTests.swift in Sources */,
754 | 508566A21FA34EB1004208ED /* KeychainSwiftPrefixedTests.swift in Sources */,
755 | 508566A81FA34EB1004208ED /* macOS_Tests.swift in Sources */,
756 | 5085669C1FA34EB1004208ED /* AccessGroupTests.swift in Sources */,
757 | );
758 | runOnlyForDeploymentPostprocessing = 0;
759 | };
760 | 7E3A6B771D3F6779007C5B1F /* Sources */ = {
761 | isa = PBXSourcesBuildPhase;
762 | buildActionMask = 2147483647;
763 | files = (
764 | 7E3A6B801D3F6779007C5B1F /* ViewController.swift in Sources */,
765 | 7E3A6B7E1D3F6779007C5B1F /* AppDelegate.swift in Sources */,
766 | );
767 | runOnlyForDeploymentPostprocessing = 0;
768 | };
769 | 7ED6C9671B1C118F00FE8090 /* Sources */ = {
770 | isa = PBXSourcesBuildPhase;
771 | buildActionMask = 2147483647;
772 | files = (
773 | 7ED6C9911B1C128100FE8090 /* KeychainSwiftAccessOptions.swift in Sources */,
774 | 7ED6C9901B1C128100FE8090 /* KeychainSwift.swift in Sources */,
775 | 7ED6C9921B1C128100FE8090 /* TegKeychainConstants.swift in Sources */,
776 | );
777 | runOnlyForDeploymentPostprocessing = 0;
778 | };
779 | 7ED6C9731B1C118F00FE8090 /* Sources */ = {
780 | isa = PBXSourcesBuildPhase;
781 | buildActionMask = 2147483647;
782 | files = (
783 | 508566A11FA34EB1004208ED /* KeychainSwiftPrefixedTests.swift in Sources */,
784 | 508566A71FA34EB1004208ED /* macOS_Tests.swift in Sources */,
785 | 7ED6C9971B1C12B300FE8090 /* KeychainSwiftAccessOptions.swift in Sources */,
786 | C7E1DE4C1E4B7C9F003818F6 /* ConcurrencyTests.swift in Sources */,
787 | 7ED6C9961B1C12B100FE8090 /* KeychainSwift.swift in Sources */,
788 | 508566A91FA34EB1004208ED /* SynchronizableTests.swift in Sources */,
789 | 5085669B1FA34EB1004208ED /* AccessGroupTests.swift in Sources */,
790 | 7ED6C9981B1C12B500FE8090 /* TegKeychainConstants.swift in Sources */,
791 | 5085669D1FA34EB1004208ED /* ClearTests.swift in Sources */,
792 | F271A1AE23BE071800FCC3B9 /* AllKeysTests.swift in Sources */,
793 | 508566A31FA34EB1004208ED /* KeychainSwiftTests.swift in Sources */,
794 | );
795 | runOnlyForDeploymentPostprocessing = 0;
796 | };
797 | 7ED6C9991B1C133500FE8090 /* Sources */ = {
798 | isa = PBXSourcesBuildPhase;
799 | buildActionMask = 2147483647;
800 | files = (
801 | 7ED6C9A41B1C133500FE8090 /* ViewController.swift in Sources */,
802 | 7EE5B9A11E32F6D400AA56FF /* KeychainSwiftCBridge.swift in Sources */,
803 | 7ED6C9A21B1C133500FE8090 /* AppDelegate.swift in Sources */,
804 | );
805 | runOnlyForDeploymentPostprocessing = 0;
806 | };
807 | /* End PBXSourcesBuildPhase section */
808 |
809 | /* Begin PBXTargetDependency section */
810 | 7E3A6B8D1D3F67B1007C5B1F /* PBXTargetDependency */ = {
811 | isa = PBXTargetDependency;
812 | target = 232B4C791BC29950001F2B7A /* KeychainSwift-macOS */;
813 | targetProxy = 7E3A6B8C1D3F67B1007C5B1F /* PBXContainerItemProxy */;
814 | };
815 | 7EC243571E3301D600C771BE /* PBXTargetDependency */ = {
816 | isa = PBXTargetDependency;
817 | target = 7ED6C99C1B1C133500FE8090 /* Demo */;
818 | targetProxy = 7EC243561E3301D600C771BE /* PBXContainerItemProxy */;
819 | };
820 | 7ED6C97A1B1C118F00FE8090 /* PBXTargetDependency */ = {
821 | isa = PBXTargetDependency;
822 | target = 7ED6C96B1B1C118F00FE8090 /* KeychainSwift */;
823 | targetProxy = 7ED6C9791B1C118F00FE8090 /* PBXContainerItemProxy */;
824 | };
825 | 7ED6C9C21B1C13AA00FE8090 /* PBXTargetDependency */ = {
826 | isa = PBXTargetDependency;
827 | target = 7ED6C96B1B1C118F00FE8090 /* KeychainSwift */;
828 | targetProxy = 7ED6C9C11B1C13AA00FE8090 /* PBXContainerItemProxy */;
829 | };
830 | BF4250112343FE8400F7B44C /* PBXTargetDependency */ = {
831 | isa = PBXTargetDependency;
832 | target = 232B4C791BC29950001F2B7A /* KeychainSwift-macOS */;
833 | targetProxy = BF4250102343FE8400F7B44C /* PBXContainerItemProxy */;
834 | };
835 | /* End PBXTargetDependency section */
836 |
837 | /* Begin PBXVariantGroup section */
838 | 7E3A6B831D3F6779007C5B1F /* Main.storyboard */ = {
839 | isa = PBXVariantGroup;
840 | children = (
841 | 7E3A6B841D3F6779007C5B1F /* Base */,
842 | );
843 | name = Main.storyboard;
844 | sourceTree = "";
845 | };
846 | 7ED6C9A51B1C133500FE8090 /* Main.storyboard */ = {
847 | isa = PBXVariantGroup;
848 | children = (
849 | 7ED6C9A61B1C133500FE8090 /* Base */,
850 | );
851 | name = Main.storyboard;
852 | sourceTree = "";
853 | };
854 | 7ED6C9AA1B1C133500FE8090 /* LaunchScreen.xib */ = {
855 | isa = PBXVariantGroup;
856 | children = (
857 | 7ED6C9AB1B1C133500FE8090 /* Base */,
858 | );
859 | name = LaunchScreen.xib;
860 | sourceTree = "";
861 | };
862 | /* End PBXVariantGroup section */
863 |
864 | /* Begin XCBuildConfiguration section */
865 | 232B4C801BC29950001F2B7A /* Debug */ = {
866 | isa = XCBuildConfiguration;
867 | buildSettings = {
868 | APPLICATION_EXTENSION_API_ONLY = YES;
869 | CODE_SIGN_IDENTITY = "-";
870 | COMBINE_HIDPI_IMAGES = YES;
871 | DEBUG_INFORMATION_FORMAT = dwarf;
872 | DEFINES_MODULE = YES;
873 | DYLIB_COMPATIBILITY_VERSION = 1;
874 | DYLIB_CURRENT_VERSION = 1;
875 | DYLIB_INSTALL_NAME_BASE = "@rpath";
876 | FRAMEWORK_VERSION = A;
877 | INFOPLIST_FILE = Sources/Info.plist;
878 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
879 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
880 | MACOSX_DEPLOYMENT_TARGET = 10.13;
881 | PRODUCT_BUNDLE_IDENTIFIER = "com.marketplacer.KeychainSwift-macOS";
882 | PRODUCT_NAME = KeychainSwift;
883 | SDKROOT = macosx;
884 | SKIP_INSTALL = YES;
885 | SWIFT_SWIFT3_OBJC_INFERENCE = Off;
886 | SWIFT_VERSION = 5.0;
887 | };
888 | name = Debug;
889 | };
890 | 232B4C811BC29950001F2B7A /* Release */ = {
891 | isa = XCBuildConfiguration;
892 | buildSettings = {
893 | APPLICATION_EXTENSION_API_ONLY = YES;
894 | CODE_SIGN_IDENTITY = "-";
895 | COMBINE_HIDPI_IMAGES = YES;
896 | DEFINES_MODULE = YES;
897 | DYLIB_COMPATIBILITY_VERSION = 1;
898 | DYLIB_CURRENT_VERSION = 1;
899 | DYLIB_INSTALL_NAME_BASE = "@rpath";
900 | FRAMEWORK_VERSION = A;
901 | INFOPLIST_FILE = Sources/Info.plist;
902 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
903 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
904 | MACOSX_DEPLOYMENT_TARGET = 10.13;
905 | PRODUCT_BUNDLE_IDENTIFIER = "com.marketplacer.KeychainSwift-macOS";
906 | PRODUCT_NAME = KeychainSwift;
907 | SDKROOT = macosx;
908 | SKIP_INSTALL = YES;
909 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
910 | SWIFT_SWIFT3_OBJC_INFERENCE = Off;
911 | SWIFT_VERSION = 5.0;
912 | };
913 | name = Release;
914 | };
915 | 232B4C901BC29984001F2B7A /* Debug */ = {
916 | isa = XCBuildConfiguration;
917 | buildSettings = {
918 | APPLICATION_EXTENSION_API_ONLY = YES;
919 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
920 | DEBUG_INFORMATION_FORMAT = dwarf;
921 | DEFINES_MODULE = YES;
922 | DYLIB_COMPATIBILITY_VERSION = 1;
923 | DYLIB_CURRENT_VERSION = 1;
924 | DYLIB_INSTALL_NAME_BASE = "@rpath";
925 | INFOPLIST_FILE = Sources/Info.plist;
926 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
927 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
928 | PRODUCT_BUNDLE_IDENTIFIER = "com.marketplacer.KeychainSwift-watchOS";
929 | PRODUCT_NAME = KeychainSwift;
930 | SDKROOT = watchos;
931 | SKIP_INSTALL = YES;
932 | SWIFT_SWIFT3_OBJC_INFERENCE = Off;
933 | SWIFT_VERSION = 5.0;
934 | TARGETED_DEVICE_FAMILY = 4;
935 | WATCHOS_DEPLOYMENT_TARGET = 4.0;
936 | };
937 | name = Debug;
938 | };
939 | 232B4C911BC29984001F2B7A /* Release */ = {
940 | isa = XCBuildConfiguration;
941 | buildSettings = {
942 | APPLICATION_EXTENSION_API_ONLY = YES;
943 | "CODE_SIGN_IDENTITY[sdk=watchos*]" = "";
944 | DEFINES_MODULE = YES;
945 | DYLIB_COMPATIBILITY_VERSION = 1;
946 | DYLIB_CURRENT_VERSION = 1;
947 | DYLIB_INSTALL_NAME_BASE = "@rpath";
948 | INFOPLIST_FILE = Sources/Info.plist;
949 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
950 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
951 | PRODUCT_BUNDLE_IDENTIFIER = "com.marketplacer.KeychainSwift-watchOS";
952 | PRODUCT_NAME = KeychainSwift;
953 | SDKROOT = watchos;
954 | SKIP_INSTALL = YES;
955 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
956 | SWIFT_SWIFT3_OBJC_INFERENCE = Off;
957 | SWIFT_VERSION = 5.0;
958 | TARGETED_DEVICE_FAMILY = 4;
959 | WATCHOS_DEPLOYMENT_TARGET = 4.0;
960 | };
961 | name = Release;
962 | };
963 | 23E785661BDA410C00B7564A /* Debug */ = {
964 | isa = XCBuildConfiguration;
965 | buildSettings = {
966 | APPLICATION_EXTENSION_API_ONLY = YES;
967 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
968 | DEBUG_INFORMATION_FORMAT = dwarf;
969 | DEFINES_MODULE = YES;
970 | DYLIB_COMPATIBILITY_VERSION = 1;
971 | DYLIB_CURRENT_VERSION = 1;
972 | DYLIB_INSTALL_NAME_BASE = "@rpath";
973 | INFOPLIST_FILE = Sources/Info.plist;
974 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
975 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
976 | PRODUCT_BUNDLE_IDENTIFIER = "com.marketplacer.KeychainSwift-tvOS";
977 | PRODUCT_NAME = KeychainSwift;
978 | SDKROOT = appletvos;
979 | SKIP_INSTALL = YES;
980 | SWIFT_SWIFT3_OBJC_INFERENCE = Off;
981 | SWIFT_VERSION = 5.0;
982 | TARGETED_DEVICE_FAMILY = 3;
983 | TVOS_DEPLOYMENT_TARGET = 12.0;
984 | };
985 | name = Debug;
986 | };
987 | 23E785671BDA410C00B7564A /* Release */ = {
988 | isa = XCBuildConfiguration;
989 | buildSettings = {
990 | APPLICATION_EXTENSION_API_ONLY = YES;
991 | "CODE_SIGN_IDENTITY[sdk=appletvos*]" = "";
992 | DEFINES_MODULE = YES;
993 | DYLIB_COMPATIBILITY_VERSION = 1;
994 | DYLIB_CURRENT_VERSION = 1;
995 | DYLIB_INSTALL_NAME_BASE = "@rpath";
996 | INFOPLIST_FILE = Sources/Info.plist;
997 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
998 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
999 | PRODUCT_BUNDLE_IDENTIFIER = "com.marketplacer.KeychainSwift-tvOS";
1000 | PRODUCT_NAME = KeychainSwift;
1001 | SDKROOT = appletvos;
1002 | SKIP_INSTALL = YES;
1003 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
1004 | SWIFT_SWIFT3_OBJC_INFERENCE = Off;
1005 | SWIFT_VERSION = 5.0;
1006 | TARGETED_DEVICE_FAMILY = 3;
1007 | TVOS_DEPLOYMENT_TARGET = 12.0;
1008 | };
1009 | name = Release;
1010 | };
1011 | 7E3A6B651D3F62C2007C5B1F /* Debug */ = {
1012 | isa = XCBuildConfiguration;
1013 | buildSettings = {
1014 | CLANG_ANALYZER_NONNULL = YES;
1015 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
1016 | CODE_SIGN_IDENTITY = "-";
1017 | COMBINE_HIDPI_IMAGES = YES;
1018 | DEBUG_INFORMATION_FORMAT = dwarf;
1019 | INFOPLIST_FILE = "Tests/KeychainSwiftTests/macOS Tests/Info.plist";
1020 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
1021 | MACOSX_DEPLOYMENT_TARGET = 10.13;
1022 | PRODUCT_BUNDLE_IDENTIFIER = "com.evgenii.macOS-Tests";
1023 | PRODUCT_NAME = "$(TARGET_NAME)";
1024 | SDKROOT = macosx;
1025 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
1026 | SWIFT_SWIFT3_OBJC_INFERENCE = Off;
1027 | SWIFT_VERSION = 5.0;
1028 | };
1029 | name = Debug;
1030 | };
1031 | 7E3A6B661D3F62C2007C5B1F /* Release */ = {
1032 | isa = XCBuildConfiguration;
1033 | buildSettings = {
1034 | CLANG_ANALYZER_NONNULL = YES;
1035 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
1036 | CODE_SIGN_IDENTITY = "-";
1037 | COMBINE_HIDPI_IMAGES = YES;
1038 | INFOPLIST_FILE = "Tests/KeychainSwiftTests/macOS Tests/Info.plist";
1039 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
1040 | MACOSX_DEPLOYMENT_TARGET = 10.13;
1041 | PRODUCT_BUNDLE_IDENTIFIER = "com.evgenii.macOS-Tests";
1042 | PRODUCT_NAME = "$(TARGET_NAME)";
1043 | SDKROOT = macosx;
1044 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
1045 | SWIFT_SWIFT3_OBJC_INFERENCE = Off;
1046 | SWIFT_VERSION = 5.0;
1047 | };
1048 | name = Release;
1049 | };
1050 | 7E3A6B871D3F6779007C5B1F /* Debug */ = {
1051 | isa = XCBuildConfiguration;
1052 | buildSettings = {
1053 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
1054 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
1055 | CLANG_ANALYZER_NONNULL = YES;
1056 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
1057 | CODE_SIGN_IDENTITY = "-";
1058 | COMBINE_HIDPI_IMAGES = YES;
1059 | DEBUG_INFORMATION_FORMAT = dwarf;
1060 | INFOPLIST_FILE = "macOS Demo/Info.plist";
1061 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
1062 | MACOSX_DEPLOYMENT_TARGET = 10.13;
1063 | PRODUCT_BUNDLE_IDENTIFIER = "com.evgenii.macOS-Demo";
1064 | PRODUCT_NAME = "$(TARGET_NAME)";
1065 | SDKROOT = macosx;
1066 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
1067 | SWIFT_SWIFT3_OBJC_INFERENCE = Off;
1068 | SWIFT_VERSION = 5.0;
1069 | };
1070 | name = Debug;
1071 | };
1072 | 7E3A6B881D3F6779007C5B1F /* Release */ = {
1073 | isa = XCBuildConfiguration;
1074 | buildSettings = {
1075 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
1076 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
1077 | CLANG_ANALYZER_NONNULL = YES;
1078 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
1079 | CODE_SIGN_IDENTITY = "-";
1080 | COMBINE_HIDPI_IMAGES = YES;
1081 | INFOPLIST_FILE = "macOS Demo/Info.plist";
1082 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks";
1083 | MACOSX_DEPLOYMENT_TARGET = 10.13;
1084 | PRODUCT_BUNDLE_IDENTIFIER = "com.evgenii.macOS-Demo";
1085 | PRODUCT_NAME = "$(TARGET_NAME)";
1086 | SDKROOT = macosx;
1087 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
1088 | SWIFT_SWIFT3_OBJC_INFERENCE = Off;
1089 | SWIFT_VERSION = 5.0;
1090 | };
1091 | name = Release;
1092 | };
1093 | 7ED51A761B7734AF005B39C2 /* Debug */ = {
1094 | isa = XCBuildConfiguration;
1095 | buildSettings = {
1096 | DEBUGGING_SYMBOLS = YES;
1097 | DEBUG_INFORMATION_FORMAT = dwarf;
1098 | GCC_GENERATE_DEBUGGING_SYMBOLS = YES;
1099 | GCC_OPTIMIZATION_LEVEL = 0;
1100 | OTHER_CFLAGS = "";
1101 | OTHER_LDFLAGS = "";
1102 | PRODUCT_NAME = "$(TARGET_NAME)";
1103 | };
1104 | name = Debug;
1105 | };
1106 | 7ED51A771B7734AF005B39C2 /* Release */ = {
1107 | isa = XCBuildConfiguration;
1108 | buildSettings = {
1109 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
1110 | OTHER_CFLAGS = "";
1111 | OTHER_LDFLAGS = "";
1112 | PRODUCT_NAME = "$(TARGET_NAME)";
1113 | };
1114 | name = Release;
1115 | };
1116 | 7ED6C9801B1C118F00FE8090 /* Debug */ = {
1117 | isa = XCBuildConfiguration;
1118 | buildSettings = {
1119 | ALWAYS_SEARCH_USER_PATHS = NO;
1120 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
1121 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
1122 | CLANG_CXX_LIBRARY = "libc++";
1123 | CLANG_ENABLE_MODULES = YES;
1124 | CLANG_ENABLE_OBJC_ARC = YES;
1125 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
1126 | CLANG_WARN_BOOL_CONVERSION = YES;
1127 | CLANG_WARN_COMMA = YES;
1128 | CLANG_WARN_CONSTANT_CONVERSION = YES;
1129 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
1130 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
1131 | CLANG_WARN_EMPTY_BODY = YES;
1132 | CLANG_WARN_ENUM_CONVERSION = YES;
1133 | CLANG_WARN_INFINITE_RECURSION = YES;
1134 | CLANG_WARN_INT_CONVERSION = YES;
1135 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
1136 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
1137 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
1138 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
1139 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
1140 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
1141 | CLANG_WARN_STRICT_PROTOTYPES = YES;
1142 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
1143 | CLANG_WARN_UNREACHABLE_CODE = YES;
1144 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
1145 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
1146 | COPY_PHASE_STRIP = NO;
1147 | CURRENT_PROJECT_VERSION = 1;
1148 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
1149 | ENABLE_STRICT_OBJC_MSGSEND = YES;
1150 | ENABLE_TESTABILITY = YES;
1151 | GCC_C_LANGUAGE_STANDARD = gnu99;
1152 | GCC_DYNAMIC_NO_PIC = NO;
1153 | GCC_NO_COMMON_BLOCKS = YES;
1154 | GCC_OPTIMIZATION_LEVEL = 0;
1155 | GCC_PREPROCESSOR_DEFINITIONS = (
1156 | "DEBUG=1",
1157 | "$(inherited)",
1158 | );
1159 | GCC_SYMBOLS_PRIVATE_EXTERN = NO;
1160 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
1161 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
1162 | GCC_WARN_UNDECLARED_SELECTOR = YES;
1163 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
1164 | GCC_WARN_UNUSED_FUNCTION = YES;
1165 | GCC_WARN_UNUSED_VARIABLE = YES;
1166 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
1167 | MTL_ENABLE_DEBUG_INFO = YES;
1168 | ONLY_ACTIVE_ARCH = YES;
1169 | SDKROOT = iphoneos;
1170 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
1171 | SWIFT_VERSION = 5.0;
1172 | TARGETED_DEVICE_FAMILY = "1,2";
1173 | VERSIONING_SYSTEM = "apple-generic";
1174 | VERSION_INFO_PREFIX = "";
1175 | };
1176 | name = Debug;
1177 | };
1178 | 7ED6C9811B1C118F00FE8090 /* Release */ = {
1179 | isa = XCBuildConfiguration;
1180 | buildSettings = {
1181 | ALWAYS_SEARCH_USER_PATHS = NO;
1182 | CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
1183 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
1184 | CLANG_CXX_LIBRARY = "libc++";
1185 | CLANG_ENABLE_MODULES = YES;
1186 | CLANG_ENABLE_OBJC_ARC = YES;
1187 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
1188 | CLANG_WARN_BOOL_CONVERSION = YES;
1189 | CLANG_WARN_COMMA = YES;
1190 | CLANG_WARN_CONSTANT_CONVERSION = YES;
1191 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
1192 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
1193 | CLANG_WARN_EMPTY_BODY = YES;
1194 | CLANG_WARN_ENUM_CONVERSION = YES;
1195 | CLANG_WARN_INFINITE_RECURSION = YES;
1196 | CLANG_WARN_INT_CONVERSION = YES;
1197 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
1198 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
1199 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
1200 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
1201 | CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
1202 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
1203 | CLANG_WARN_STRICT_PROTOTYPES = YES;
1204 | CLANG_WARN_SUSPICIOUS_MOVE = YES;
1205 | CLANG_WARN_UNREACHABLE_CODE = YES;
1206 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
1207 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer";
1208 | COPY_PHASE_STRIP = NO;
1209 | CURRENT_PROJECT_VERSION = 1;
1210 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
1211 | ENABLE_NS_ASSERTIONS = NO;
1212 | ENABLE_STRICT_OBJC_MSGSEND = YES;
1213 | GCC_C_LANGUAGE_STANDARD = gnu99;
1214 | GCC_NO_COMMON_BLOCKS = YES;
1215 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
1216 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
1217 | GCC_WARN_UNDECLARED_SELECTOR = YES;
1218 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
1219 | GCC_WARN_UNUSED_FUNCTION = YES;
1220 | GCC_WARN_UNUSED_VARIABLE = YES;
1221 | IPHONEOS_DEPLOYMENT_TARGET = 12.0;
1222 | MTL_ENABLE_DEBUG_INFO = NO;
1223 | SDKROOT = iphoneos;
1224 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
1225 | SWIFT_VERSION = 5.0;
1226 | TARGETED_DEVICE_FAMILY = "1,2";
1227 | VALIDATE_PRODUCT = YES;
1228 | VERSIONING_SYSTEM = "apple-generic";
1229 | VERSION_INFO_PREFIX = "";
1230 | };
1231 | name = Release;
1232 | };
1233 | 7ED6C9831B1C118F00FE8090 /* Debug */ = {
1234 | isa = XCBuildConfiguration;
1235 | buildSettings = {
1236 | APPLICATION_EXTENSION_API_ONLY = YES;
1237 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
1238 | DEFINES_MODULE = YES;
1239 | DYLIB_COMPATIBILITY_VERSION = 1;
1240 | DYLIB_CURRENT_VERSION = 1;
1241 | DYLIB_INSTALL_NAME_BASE = "@rpath";
1242 | INFOPLIST_FILE = "$(SRCROOT)/Sources/Info.plist";
1243 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
1244 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
1245 | PRODUCT_BUNDLE_IDENTIFIER = "com.marketplacer.$(PRODUCT_NAME:rfc1034identifier)";
1246 | PRODUCT_NAME = "$(TARGET_NAME)";
1247 | SKIP_INSTALL = YES;
1248 | SWIFT_VERSION = 5.0;
1249 | };
1250 | name = Debug;
1251 | };
1252 | 7ED6C9841B1C118F00FE8090 /* Release */ = {
1253 | isa = XCBuildConfiguration;
1254 | buildSettings = {
1255 | APPLICATION_EXTENSION_API_ONLY = YES;
1256 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "";
1257 | DEFINES_MODULE = YES;
1258 | DYLIB_COMPATIBILITY_VERSION = 1;
1259 | DYLIB_CURRENT_VERSION = 1;
1260 | DYLIB_INSTALL_NAME_BASE = "@rpath";
1261 | INFOPLIST_FILE = "$(SRCROOT)/Sources/Info.plist";
1262 | INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
1263 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
1264 | PRODUCT_BUNDLE_IDENTIFIER = "com.marketplacer.$(PRODUCT_NAME:rfc1034identifier)";
1265 | PRODUCT_NAME = "$(TARGET_NAME)";
1266 | SKIP_INSTALL = YES;
1267 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
1268 | SWIFT_VERSION = 5.0;
1269 | };
1270 | name = Release;
1271 | };
1272 | 7ED6C9861B1C118F00FE8090 /* Debug */ = {
1273 | isa = XCBuildConfiguration;
1274 | buildSettings = {
1275 | CLANG_ENABLE_MODULES = YES;
1276 | FRAMEWORK_SEARCH_PATHS = "$(inherited)";
1277 | GCC_PREPROCESSOR_DEFINITIONS = (
1278 | "DEBUG=1",
1279 | "$(inherited)",
1280 | );
1281 | INFOPLIST_FILE = Tests/KeychainSwiftTests/Info.plist;
1282 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
1283 | PRODUCT_BUNDLE_IDENTIFIER = "com.marketplacer.$(PRODUCT_NAME:rfc1034identifier)";
1284 | PRODUCT_NAME = "$(TARGET_NAME)";
1285 | SWIFT_OBJC_BRIDGING_HEADER = "Tests/KeychainSwiftTests/KeychainSwiftTests-Bridging-Header.h";
1286 | SWIFT_OPTIMIZATION_LEVEL = "-Onone";
1287 | SWIFT_VERSION = 5.0;
1288 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Keychain Swift.app/Keychain Swift";
1289 | };
1290 | name = Debug;
1291 | };
1292 | 7ED6C9871B1C118F00FE8090 /* Release */ = {
1293 | isa = XCBuildConfiguration;
1294 | buildSettings = {
1295 | CLANG_ENABLE_MODULES = YES;
1296 | FRAMEWORK_SEARCH_PATHS = "$(inherited)";
1297 | INFOPLIST_FILE = Tests/KeychainSwiftTests/Info.plist;
1298 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
1299 | PRODUCT_BUNDLE_IDENTIFIER = "com.marketplacer.$(PRODUCT_NAME:rfc1034identifier)";
1300 | PRODUCT_NAME = "$(TARGET_NAME)";
1301 | SWIFT_OBJC_BRIDGING_HEADER = "Tests/KeychainSwiftTests/KeychainSwiftTests-Bridging-Header.h";
1302 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
1303 | SWIFT_VERSION = 5.0;
1304 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Keychain Swift.app/Keychain Swift";
1305 | };
1306 | name = Release;
1307 | };
1308 | 7ED6C9BA1B1C133500FE8090 /* Debug */ = {
1309 | isa = XCBuildConfiguration;
1310 | buildSettings = {
1311 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
1312 | GCC_PREPROCESSOR_DEFINITIONS = (
1313 | "DEBUG=1",
1314 | "$(inherited)",
1315 | );
1316 | INFOPLIST_FILE = Demo/Info.plist;
1317 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
1318 | PRODUCT_BUNDLE_IDENTIFIER = com.marketplacer.KeychainSwiftDemo;
1319 | PRODUCT_NAME = "Keychain Swift";
1320 | SWIFT_VERSION = 5.0;
1321 | };
1322 | name = Debug;
1323 | };
1324 | 7ED6C9BB1B1C133500FE8090 /* Release */ = {
1325 | isa = XCBuildConfiguration;
1326 | buildSettings = {
1327 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
1328 | INFOPLIST_FILE = Demo/Info.plist;
1329 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks";
1330 | PRODUCT_BUNDLE_IDENTIFIER = com.marketplacer.KeychainSwiftDemo;
1331 | PRODUCT_NAME = "Keychain Swift";
1332 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
1333 | SWIFT_VERSION = 5.0;
1334 | };
1335 | name = Release;
1336 | };
1337 | /* End XCBuildConfiguration section */
1338 |
1339 | /* Begin XCConfigurationList section */
1340 | 232B4C7F1BC29950001F2B7A /* Build configuration list for PBXNativeTarget "KeychainSwift-macOS" */ = {
1341 | isa = XCConfigurationList;
1342 | buildConfigurations = (
1343 | 232B4C801BC29950001F2B7A /* Debug */,
1344 | 232B4C811BC29950001F2B7A /* Release */,
1345 | );
1346 | defaultConfigurationIsVisible = 0;
1347 | defaultConfigurationName = Release;
1348 | };
1349 | 232B4C8F1BC29984001F2B7A /* Build configuration list for PBXNativeTarget "KeychainSwift-watchOS" */ = {
1350 | isa = XCConfigurationList;
1351 | buildConfigurations = (
1352 | 232B4C901BC29984001F2B7A /* Debug */,
1353 | 232B4C911BC29984001F2B7A /* Release */,
1354 | );
1355 | defaultConfigurationIsVisible = 0;
1356 | defaultConfigurationName = Release;
1357 | };
1358 | 23E785651BDA410C00B7564A /* Build configuration list for PBXNativeTarget "KeychainSwift-tvOS" */ = {
1359 | isa = XCConfigurationList;
1360 | buildConfigurations = (
1361 | 23E785661BDA410C00B7564A /* Debug */,
1362 | 23E785671BDA410C00B7564A /* Release */,
1363 | );
1364 | defaultConfigurationIsVisible = 0;
1365 | defaultConfigurationName = Release;
1366 | };
1367 | 7E3A6B671D3F62C2007C5B1F /* Build configuration list for PBXNativeTarget "macOS Tests" */ = {
1368 | isa = XCConfigurationList;
1369 | buildConfigurations = (
1370 | 7E3A6B651D3F62C2007C5B1F /* Debug */,
1371 | 7E3A6B661D3F62C2007C5B1F /* Release */,
1372 | );
1373 | defaultConfigurationIsVisible = 0;
1374 | defaultConfigurationName = Release;
1375 | };
1376 | 7E3A6B891D3F6779007C5B1F /* Build configuration list for PBXNativeTarget "macOS Demo" */ = {
1377 | isa = XCConfigurationList;
1378 | buildConfigurations = (
1379 | 7E3A6B871D3F6779007C5B1F /* Debug */,
1380 | 7E3A6B881D3F6779007C5B1F /* Release */,
1381 | );
1382 | defaultConfigurationIsVisible = 0;
1383 | defaultConfigurationName = Release;
1384 | };
1385 | 7ED51A781B7734AF005B39C2 /* Build configuration list for PBXLegacyTarget "ConcatenateSwiftFiles" */ = {
1386 | isa = XCConfigurationList;
1387 | buildConfigurations = (
1388 | 7ED51A761B7734AF005B39C2 /* Debug */,
1389 | 7ED51A771B7734AF005B39C2 /* Release */,
1390 | );
1391 | defaultConfigurationIsVisible = 0;
1392 | defaultConfigurationName = Release;
1393 | };
1394 | 7ED6C9661B1C118F00FE8090 /* Build configuration list for PBXProject "KeychainSwift" */ = {
1395 | isa = XCConfigurationList;
1396 | buildConfigurations = (
1397 | 7ED6C9801B1C118F00FE8090 /* Debug */,
1398 | 7ED6C9811B1C118F00FE8090 /* Release */,
1399 | );
1400 | defaultConfigurationIsVisible = 0;
1401 | defaultConfigurationName = Release;
1402 | };
1403 | 7ED6C9821B1C118F00FE8090 /* Build configuration list for PBXNativeTarget "KeychainSwift" */ = {
1404 | isa = XCConfigurationList;
1405 | buildConfigurations = (
1406 | 7ED6C9831B1C118F00FE8090 /* Debug */,
1407 | 7ED6C9841B1C118F00FE8090 /* Release */,
1408 | );
1409 | defaultConfigurationIsVisible = 0;
1410 | defaultConfigurationName = Release;
1411 | };
1412 | 7ED6C9851B1C118F00FE8090 /* Build configuration list for PBXNativeTarget "KeychainSwiftTests" */ = {
1413 | isa = XCConfigurationList;
1414 | buildConfigurations = (
1415 | 7ED6C9861B1C118F00FE8090 /* Debug */,
1416 | 7ED6C9871B1C118F00FE8090 /* Release */,
1417 | );
1418 | defaultConfigurationIsVisible = 0;
1419 | defaultConfigurationName = Release;
1420 | };
1421 | 7ED6C9B91B1C133500FE8090 /* Build configuration list for PBXNativeTarget "Demo" */ = {
1422 | isa = XCConfigurationList;
1423 | buildConfigurations = (
1424 | 7ED6C9BA1B1C133500FE8090 /* Debug */,
1425 | 7ED6C9BB1B1C133500FE8090 /* Release */,
1426 | );
1427 | defaultConfigurationIsVisible = 0;
1428 | defaultConfigurationName = Release;
1429 | };
1430 | /* End XCConfigurationList section */
1431 | };
1432 | rootObject = 7ED6C9631B1C118F00FE8090 /* Project object */;
1433 | }
1434 |
--------------------------------------------------------------------------------
/KeychainSwift.xcodeproj/project.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/KeychainSwift.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/KeychainSwift.xcodeproj/xcshareddata/xcschemes/ConcatenateSwiftFiles.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 |
--------------------------------------------------------------------------------
/KeychainSwift.xcodeproj/xcshareddata/xcschemes/Demo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
52 |
54 |
60 |
61 |
62 |
63 |
69 |
71 |
77 |
78 |
79 |
80 |
82 |
83 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/KeychainSwift.xcodeproj/xcshareddata/xcschemes/KeychainSwift-macOS.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
53 |
54 |
60 |
61 |
62 |
63 |
69 |
70 |
76 |
77 |
78 |
79 |
81 |
82 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/KeychainSwift.xcodeproj/xcshareddata/xcschemes/KeychainSwift-tvOS.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 |
--------------------------------------------------------------------------------
/KeychainSwift.xcodeproj/xcshareddata/xcschemes/KeychainSwift-watchOS.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 |
--------------------------------------------------------------------------------
/KeychainSwift.xcodeproj/xcshareddata/xcschemes/KeychainSwift.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 |
63 |
69 |
70 |
71 |
72 |
78 |
79 |
85 |
86 |
87 |
88 |
90 |
91 |
94 |
95 |
96 |
--------------------------------------------------------------------------------
/KeychainSwift.xcodeproj/xcshareddata/xcschemes/macOS Demo.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
37 |
38 |
39 |
40 |
41 |
42 |
52 |
54 |
60 |
61 |
62 |
63 |
69 |
71 |
77 |
78 |
79 |
80 |
82 |
83 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/KeychainSwift.xcodeproj/xcshareddata/xcschemes/macOS Tests.xcscheme:
--------------------------------------------------------------------------------
1 |
2 |
5 |
8 |
9 |
15 |
21 |
22 |
23 |
24 |
25 |
30 |
31 |
33 |
39 |
40 |
41 |
42 |
43 |
53 |
54 |
60 |
61 |
62 |
63 |
69 |
70 |
76 |
77 |
78 |
79 |
81 |
82 |
85 |
86 |
87 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | The MIT License
2 |
3 | Copyright (c) 2015 - 2024 Evgenii Neumerzhitckii
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
13 | all 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
21 | THE SOFTWARE.
22 |
--------------------------------------------------------------------------------
/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version:5.7.1
2 | import PackageDescription
3 |
4 | let package = Package(
5 | name: "KeychainSwift",
6 | products: [
7 | .library(name: "KeychainSwift", targets: ["KeychainSwift"]),
8 | ],
9 | dependencies: [
10 | ],
11 | targets: [
12 | .target(
13 | name: "KeychainSwift",
14 | dependencies: [],
15 | path: "Sources",
16 | exclude: ["Info.plist"]
17 | ),
18 | .testTarget(
19 | name: "KeychainSwiftTests",
20 | dependencies: ["KeychainSwift"],
21 | exclude: ["ClearTests.swift"]
22 | )
23 | ]
24 | )
25 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Helper functions for storing text in Keychain for iOS, macOS, tvOS and WatchOS
2 |
3 | [](https://github.com/Carthage/Carthage)
4 | [](http://cocoadocs.org/docsets/KeychainSwift)
5 | [](https://github.com/apple/swift-package-manager)
6 | [](http://cocoadocs.org/docsets/KeychainSwift)
7 | [](http://cocoadocs.org/docsets/KeychainSwift)
8 |
9 | This is a collection of helper functions for saving text and data in the Keychain.
10 | As you probably noticed Apple's keychain API is a bit verbose. This library was designed to provide shorter syntax for accomplishing a simple task: reading/writing text values for specified keys:
11 |
12 | ```Swift
13 | let keychain = KeychainSwift()
14 | keychain.set("hello world", forKey: "my key")
15 | keychain.get("my key")
16 | ```
17 |
18 | The Keychain library includes the following features:
19 |
20 | * Get, set and delete string, boolean and Data Keychain items
21 | * Specify item access security level
22 | * Synchronize items through iCloud
23 | * Share Keychain items with other apps
24 |
25 | ## What's Keychain?
26 |
27 | Keychain is a secure storage. You can store all kind of sensitive data in it: user passwords, credit card numbers, secret tokens etc. Once stored in Keychain this information is only available to your app, other apps can't see it. Besides that, operating system makes sure this information is kept and processed securely. For example, text stored in Keychain can not be extracted from iPhone backup or from its file system. Apple recommends storing only small amount of data in the Keychain. If you need to secure something big you can encrypt it manually, save to a file and store the key in the Keychain.
28 |
29 |
30 | ## Setup
31 |
32 | There are four ways you can add KeychainSwift to your project.
33 |
34 | #### Add source (iOS 7+)
35 |
36 | Simply add [KeychainSwiftDistrib.swift](https://github.com/evgenyneu/keychain-swift/blob/master/Distrib/KeychainSwiftDistrib.swift) file into your Xcode project.
37 |
38 | #### Setup with Carthage (iOS 8+)
39 |
40 | Alternatively, add `github "evgenyneu/keychain-swift" ~> 24.0` to your Cartfile and run `carthage update`.
41 |
42 | #### Setup with CocoaPods (iOS 8+)
43 |
44 | If you are using CocoaPods add this text to your Podfile and run `pod install`.
45 |
46 | ```
47 | use_frameworks!
48 | target 'Your target name'
49 | pod 'KeychainSwift', '~> 24.0'
50 | ```
51 |
52 |
53 | #### Setup with Swift Package Manager (in project)
54 |
55 | * In Xcode select *File > Add Packages*.
56 | * Enter this project's URL: https://github.com/evgenyneu/keychain-swift.git
57 |
58 | #### Setup with Swift Package Manager (in Swift Package)
59 |
60 | If you're using KeychainSwift in a Swift package, make sure to specify a `name`. This is because SPM cannot automatically resolve a name for a package that has a different Target name in its `Package.swift` (namely `KeychainSwift`) that differs from the repo link (`keychain-swift`).
61 |
62 | ```
63 | .package(name: "KeychainSwift", url: "https://github.com/evgenyneu/keychain-swift.git", from: "24.0.0")
64 | ```
65 |
66 | ## Legacy Swift versions
67 |
68 | Setup a [previous version](https://github.com/evgenyneu/keychain-swift/wiki/Legacy-Swift-versions) of the library if you use an older version of Swift.
69 |
70 |
71 | ## Usage
72 |
73 | Add `import KeychainSwift` to your source code unless you used the file setup method.
74 |
75 | #### String values
76 |
77 | ```Swift
78 | let keychain = KeychainSwift()
79 | keychain.set("hello world", forKey: "my key")
80 | keychain.get("my key")
81 | ```
82 |
83 | #### Boolean values
84 |
85 |
86 | ```Swift
87 | let keychain = KeychainSwift()
88 | keychain.set(true, forKey: "my key")
89 | keychain.getBool("my key")
90 | ```
91 |
92 | #### Data values
93 |
94 | ```Swift
95 | let keychain = KeychainSwift()
96 | keychain.set(dataObject, forKey: "my key")
97 | keychain.getData("my key")
98 | ```
99 |
100 | #### Removing keys from Keychain
101 |
102 | ```Swift
103 | keychain.delete("my key") // Remove single key
104 | keychain.clear() // Delete everything from app's Keychain. Does not work on macOS.
105 | ```
106 |
107 | #### Return all keys
108 |
109 | ```Swift
110 | let keychain = KeychainSwift()
111 | keychain.allKeys // Returns the names of all keys
112 | ```
113 |
114 | ## Advanced options
115 |
116 |
Keychain item access
117 |
118 | Use `withAccess` parameter to specify the security level of the keychain storage.
119 | By default the `.accessibleWhenUnlocked` option is used. It is one of the most restrictive options and provides good data protection.
120 |
121 | ```
122 | let keychain = KeychainSwift()
123 | keychain.set("Hello world", forKey: "key 1", withAccess: .accessibleWhenUnlocked)
124 | ```
125 |
126 | You can use `.accessibleAfterFirstUnlock` if you need your app to access the keychain item while in the background. Note that it is less secure than the `.accessibleWhenUnlocked` option.
127 |
128 | See the list of all available [access options](https://github.com/evgenyneu/keychain-swift/blob/master/Sources/KeychainSwiftAccessOptions.swift).
129 |
130 |
131 |
Synchronizing keychain items with other devices
132 |
133 | Set `synchronizable` property to `true` to enable keychain items synchronization across user's multiple devices. The synchronization will work for users who have the "Keychain" enabled in the iCloud settings on their devices.
134 |
135 | Setting `synchronizable` property to `true` will add the item to other devices with the `set` method and obtain synchronizable items with the `get` command. Deleting a synchronizable item will remove it from all devices.
136 |
137 | Note that you do NOT need to enable iCloud or Keychain Sharing capabilities in your app's target for this feature to work.
138 |
139 |
140 | ```Swift
141 | // First device
142 | let keychain = KeychainSwift()
143 | keychain.synchronizable = true
144 | keychain.set("hello world", forKey: "my key")
145 |
146 | // Second device
147 | let keychain = KeychainSwift()
148 | keychain.synchronizable = true
149 | keychain.get("my key") // Returns "hello world"
150 | ```
151 |
152 | We could not get the Keychain synchronization work on macOS.
153 |
154 |
155 |