This is the 10th day of my participation in Gwen Challenge

KeychainAccess is a simple Swift wrapper for Keychain for iOS and OS X. In Swift, it makes it very easy and convenient to use the Keychain API.

Here are some tips I learned while reading the KeychainAccess source code.

And and or on the OptionSet

When bitmasks are used in Swift, option sets, or option sets, are used. In my previous use of OptionSet, I only considered piecing together several options as a new option. In KeychainAccess’s AuthenticationPolicy, the AND and OR options are also added to indicate whether all conditions must be met or just one of them.

public struct AuthenticationPolicy: OptionSet {
   
    public static let or = AuthenticationPolicy(rawValue: 1 << 14)
    public static let and = AuthenticationPolicy(rawValue: 1 << 15)

    #if swift(> =2.3)
    public let rawValue: UInt

    public init(rawValue: UInt) {
        self.rawValue = rawValue
    }
    #else
    public let rawValue: Int

    public init(rawValue: Int) {
        self.rawValue = rawValue
    }
    #endif
}
Copy the code

When used, you can add and or OR to indicate richer possibilities. For example, the code in the test case provided by the author:

let policy: AuthenticationPolicy = [.touchIDAny, .or, .devicePasscode]
let flags = SecAccessControlCreateFlags(rawValue: policy.rawValue)
Copy the code

Keep only the critical code.

Subscript Subscript

KeychainAccess uses subscripts, or subscripts, in many places. Because I don’t use it very often, I often forget it. Subscript can quickly access objects, collections, or sequences without invoking the instance’s specific assignment and access methods.

For example, Attributes in KeychainAccess encapsulates a dictionary of type [String: Any]. Users can use Attributes to access and set the corresponding dictionary, effectively avoiding errors caused by incorrect keys. You can also support access or setting through a custom string when the defined attributes are not sufficient.

Key code:

public struct Attributes {
    fileprivate let attributes: [String: Any]

    public var path: String? {
        return attributes[AttributePath] as? String
    }
    
    init(attributes: [String: Any]) {
        self.attributes = attributes
    }

    public subscript(key: String) -> Any? {
        get {
            return attributes[key]
        }
    }
}
Copy the code

Tests

A secure and reliable framework is inseparable from a complete set of test cases. Similarly, KeychainAccess provides a wealth of test cases. In a test method, the author can break up a test into smaller units by doing {}, which makes the code clearer.

func testGenericPassword(a) {
    do {
        // Add Keychain items
    }
    
    do {
        // Update Keychain items
    }

    do {
        // Remove Keychain items}}Copy the code