Parcourir la source

Use exception handling in Swift 2.0

kishikawa katsumi il y a 10 ans
Parent
commit
eb4dfb2f46
3 fichiers modifiés avec 406 ajouts et 615 suppressions
  1. 69 171
      Lib/KeychainAccess/Keychain.swift
  2. 275 343
      Lib/KeychainAccessTests/KeychainAccessTests.swift
  3. 62 101
      README.md

+ 69 - 171
Lib/KeychainAccess/Keychain.swift

@@ -75,55 +75,6 @@ public enum AuthenticationPolicy : Int {
     case UserPresence
 }
 
-public enum FailableOf<T> {
-    case Success(T?)
-    case Failure(NSError)
-    
-    init(_ value: T?) {
-        self = .Success(value)
-    }
-    
-    init(_ error: NSError) {
-        self = .Failure(error)
-    }
-    
-    public var succeeded: Bool {
-        switch self {
-        case .Success:
-            return true
-        default:
-            return false
-        }
-    }
-    
-    public var failed: Bool {
-        switch self {
-        case .Failure:
-            return true
-        default:
-            return false
-        }
-    }
-    
-    public var error: NSError? {
-        switch self {
-        case .Failure(let error):
-            return error
-        default:
-            return nil
-        }
-    }
-    
-    public var value: T? {
-        switch self {
-        case .Success(let success):
-            return success
-        default:
-            return nil
-        }
-    }
-}
-
 public class Keychain {
     public var itemClass: ItemClass {
         return options.itemClass
@@ -286,72 +237,54 @@ public class Keychain {
     
     // MARK:
     
-    public func get(key: String) -> String? {
-        return getString(key)
-    }
-    
-    public func getString(key: String) -> String? {
-        let failable = getStringOrError(key)
-        return failable.value
-    }
-    
-    public func getData(key: String) -> NSData? {
-        let failable = getDataOrError(key)
-        return failable.value
+    public func get(key: String) throws -> String? {
+        return try getString(key)
     }
     
-    public func getStringOrError(key: String) -> FailableOf<String> {
-        let failable = getDataOrError(key)
-        switch failable {
-        case .Success:
-            if let data = failable.value {
-                if let string = NSString(data: data, encoding: NSUTF8StringEncoding) as? String {
-                    return FailableOf(string)
-                }
-                return FailableOf(conversionError(message: "failed to convert data to string"))
-            } else {
-                return FailableOf(nil)
-            }
-        case .Failure(let error):
-            return FailableOf(error)
+    public func getString(key: String) throws -> String? {
+        guard let data = try getData(key) else  {
+            return nil
+        }
+        guard let string = NSString(data: data, encoding: NSUTF8StringEncoding) as? String else {
+            throw conversionError(message: "failed to convert data to string")
         }
+        return string
     }
-    
-    public func getDataOrError(key: String) -> FailableOf<NSData> {
+
+    public func getData(key: String) throws -> NSData? {
         var query = options.query()
-        
+
         query[kSecMatchLimit as String] = kSecMatchLimitOne
         query[kSecReturnData as String] = kCFBooleanTrue
-        
+
         query[kSecAttrAccount as String] = key
-        
+
         var result: AnyObject?
         let status = withUnsafeMutablePointer(&result) { SecItemCopyMatching(query, UnsafeMutablePointer($0)) }
-        
+
         switch status {
         case errSecSuccess:
-            if let data = result as? NSData {
-                return FailableOf(data)
+            guard let data = result as? NSData else {
+                throw Status.UnexpectedError
             }
-            return FailableOf(securityError(status: Status.UnexpectedError.rawValue))
+            return data
         case errSecItemNotFound:
-            return FailableOf(nil)
-        default: ()
+            return nil
+        default:
+            throw securityError(status: status)
         }
-        
-        return FailableOf(securityError(status: status))
     }
-    
+
     // MARK:
     
-    public func set(value: String, key: String) -> NSError? {
-        if let data = value.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) {
-            return set(data, key: key)
+    public func set(value: String, key: String) throws {
+        guard let data = value.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) else {
+            throw conversionError(message: "failed to convert string to data")
         }
-        return conversionError(message: "failed to convert string to data")
+        try set(data, key: key)
     }
     
-    public func set(value: NSData, key: String) -> NSError? {
+    public func set(value: NSData, key: String) throws {
         var query = options.query()
         
         query[kSecAttrAccount as String] = key
@@ -370,53 +303,47 @@ public class Keychain {
             let (attributes, error) = options.attributes(key: nil, value: value)
             if let error = error {
                 print("error:[\(error.code)] \(error.localizedDescription)")
-                return error
+                throw error
+            }
+
+            if status == errSecInteractionNotAllowed && floor(NSFoundationVersionNumber) <= floor(NSFoundationVersionNumber_iOS_8_0) {
+                try remove(key)
+                try set(value, key: key)
             } else {
-                if status == errSecInteractionNotAllowed && floor(NSFoundationVersionNumber) <= floor(NSFoundationVersionNumber_iOS_8_0) {
-                    let error = remove(key)
-                    if error != nil {
-                        return error
-                    } else {
-                        return set(value, key: key)
-                    }
-                } else {
-                    status = SecItemUpdate(query, attributes)
-                }
+                status = SecItemUpdate(query, attributes)
                 if status != errSecSuccess {
-                    return securityError(status: status)
+                    throw securityError(status: status)
                 }
             }
         case errSecItemNotFound:
             let (attributes, error) = options.attributes(key: key, value: value)
             if let error = error {
                 print("error:[\(error.code)] \(error.localizedDescription)")
-                return error
-            } else {
-                status = SecItemAdd(attributes, nil)
-                if status != errSecSuccess {
-                    return securityError(status: status)
-                }
+                throw error
+            }
+
+            status = SecItemAdd(attributes, nil)
+            if status != errSecSuccess {
+                throw securityError(status: status)
             }
         default:
-            return securityError(status: status)
+            throw securityError(status: status)
         }
-        return nil
     }
     
     // MARK:
     
-    public func remove(key: String) -> NSError? {
+    public func remove(key: String) throws {
         var query = options.query()
         query[kSecAttrAccount as String] = key
         
         let status = SecItemDelete(query)
         if status != errSecSuccess && status != errSecItemNotFound {
-            return securityError(status: status)
+            throw securityError(status: status)
         }
-        return nil
     }
     
-    public func removeAll() -> NSError? {
+    public func removeAll() throws {
         var query = options.query()
         #if !os(iOS)
         query[kSecMatchLimit as String] = kSecMatchLimitAll
@@ -424,27 +351,24 @@ public class Keychain {
         
         let status = SecItemDelete(query)
         if status != errSecSuccess && status != errSecItemNotFound {
-            return securityError(status: status)
+            throw securityError(status: status)
         }
-        return nil
     }
     
     // MARK:
     
-    public func contains(key: String) -> Bool {
+    public func contains(key: String) throws -> Bool {
         var query = options.query()
         query[kSecAttrAccount as String] = key
         
         let status = SecItemCopyMatching(query, nil)
-        
         switch status {
         case errSecSuccess:
             return true
         case errSecItemNotFound:
             return false
         default:
-            securityError(status: status)
-            return false
+            throw securityError(status: status)
         }
     }
     
@@ -452,42 +376,46 @@ public class Keychain {
     
     public subscript(key: String) -> String? {
         get {
-            return get(key)
+            return (try? get(key)).flatMap { $0 }
         }
         
         set {
             if let value = newValue {
-                set(value, key: key)
+                do {
+                    try set(value, key: key)
+                } catch {}
             } else {
-                remove(key)
+                do {
+                    try remove(key)
+                } catch {}
             }
         }
     }
 
     public subscript(string key: String) -> String? {
         get {
-            return get(key)
+            return self[key]
         }
 
         set {
-            if let value = newValue {
-                set(value, key: key)
-            } else {
-                remove(key)
-            }
+            self[key] = newValue
         }
     }
 
     public subscript(data key: String) -> NSData? {
         get {
-            return getData(key)
+            return (try? getData(key))?.flatMap { $0 }
         }
 
         set {
             if let value = newValue {
-                set(value, key: key)
+                do {
+                    try set(value, key: key)
+                } catch {}
             } else {
-                remove(key)
+                do {
+                    try remove(key)
+                } catch {}
             }
         }
     }
@@ -897,17 +825,10 @@ extension Options {
         if let policy = authenticationPolicy {
             if #available(OSX 10.10, *) {
                 var error: Unmanaged<CFError>?
-                let accessControl = SecAccessControlCreateWithFlags(
-                    kCFAllocatorDefault,
-                    accessibility.rawValue,
-                    SecAccessControlCreateFlags(rawValue: policy.rawValue),
-                    &error
-                )
-
-                if let error = error?.takeUnretainedValue() {
-                    return (attributes, error.error)
-                }
-                if accessControl == nil {
+                guard let accessControl = SecAccessControlCreateWithFlags(kCFAllocatorDefault, accessibility.rawValue, SecAccessControlCreateFlags(rawValue: policy.rawValue), &error) else {
+                    if let error = error?.takeUnretainedValue() {
+                        return (attributes, error.error)
+                    }
                     let message = Status.UnexpectedError.description
                     return (attributes, NSError(domain: KeychainAccessErrorDomain, code: Int(Status.UnexpectedError.rawValue), userInfo: [NSLocalizedDescriptionKey: message]))
                 }
@@ -1337,29 +1258,6 @@ extension AuthenticationPolicy : RawRepresentable, CustomStringConvertible {
     }
 }
 
-extension FailableOf: CustomStringConvertible, CustomDebugStringConvertible {
-    public var description: String {
-        switch self {
-        case .Success(let success):
-            if let value = success {
-                return "\(value)"
-            }
-            return "nil"
-        case .Failure(let error):
-            return "\(error.localizedDescription)"
-        }
-    }
-    
-    public var debugDescription: String {
-        switch self {
-        case .Success(let success):
-            return "\(success)"
-        case .Failure(let error):
-            return "\(error)"
-        }
-    }
-}
-
 extension CFError {
     var error: NSError {
         let domain = CFErrorGetDomain(self) as String
@@ -1370,7 +1268,7 @@ extension CFError {
     }
 }
 
-public enum Status : OSStatus {
+public enum Status : OSStatus, ErrorType {
     case Success
     case Unimplemented
     case Param

+ 275 - 343
Lib/KeychainAccessTests/KeychainAccessTests.swift

@@ -15,68 +15,64 @@ class KeychainAccessTests: XCTestCase {
     
     override func setUp() {
         super.setUp()
+
+        do { try Keychain(service: "Twitter", accessGroup: "12ABCD3E4F.shared").removeAll() } catch {}
+        do { try Keychain(service: "Twitter").removeAll() } catch {}
         
-        Keychain(service: "Twitter", accessGroup: "12ABCD3E4F.shared").removeAll()
-        Keychain(service: "Twitter").removeAll()
-        
-        Keychain(server: NSURL(string: "https://example.com")!, protocolType: .HTTPS).removeAll()
+        do { try Keychain(server: NSURL(string: "https://example.com")!, protocolType: .HTTPS).removeAll() } catch {}
         
-        Keychain().removeAll()
+        do { try Keychain().removeAll() } catch {}
     }
     
     override func tearDown() {
         super.tearDown()
     }
     
-    func locally(x: () -> ()) {
-        x()
-    }
-    
     // MARK:
     
     func testGenericPassword() {
-        locally {
+        do {
             // Add Keychain items
             let keychain = Keychain(service: "Twitter")
             
-            keychain.set("kishikawa_katsumi", key: "username")
-            keychain.set("password_1234", key: "password")
+            do { try keychain.set("kishikawa_katsumi", key: "username") } catch {}
+            do { try keychain.set("password_1234", key: "password") } catch {}
             
-            let username = keychain.get("username")
+            let username = try! keychain.get("username")
             XCTAssertEqual(username!, "kishikawa_katsumi")
             
-            let password = keychain.get("password")
+            let password = try! keychain.get("password")
             XCTAssertEqual(password!, "password_1234")
         }
         
-        locally {
+        do {
             // Update Keychain items
             let keychain = Keychain(service: "Twitter")
             
-            keychain.set("katsumi_kishikawa", key: "username")
-            keychain.set("1234_password", key: "password")
+            do { try keychain.set("katsumi_kishikawa", key: "username") } catch {}
+            do { try keychain.set("1234_password", key: "password") } catch {}
             
-            let username = keychain.get("username")
+            let username = try! keychain.get("username")
             XCTAssertEqual(username!, "katsumi_kishikawa")
             
-            let password = keychain.get("password")
+            let password = try! keychain.get("password")
             XCTAssertEqual(password!, "1234_password")
         }
         
-        locally {
+        do {
             // Remove Keychain items
             let keychain = Keychain(service: "Twitter")
             
-            keychain.remove("username")
-            keychain.remove("password")
+            do { try keychain.remove("username") } catch {}
+            do { try keychain.remove("password") } catch {}
             
-            XCTAssertNil(keychain.get("username"))
-            XCTAssertNil(keychain.get("password"))
+            XCTAssertNil(try! keychain.get("username"))
+            XCTAssertNil(try! keychain.get("password"))
         }
     }
     
     func testGenericPasswordSubscripting() {
-        locally {
+        do {
             // Add Keychain items
             let keychain = Keychain(service: "Twitter", accessGroup: "12ABCD3E4F.shared")
             
@@ -90,7 +86,7 @@ class KeychainAccessTests: XCTestCase {
             XCTAssertEqual(password!, "password_1234")
         }
         
-        locally {
+        do {
             // Update Keychain items
             let keychain = Keychain(service: "Twitter", accessGroup: "12ABCD3E4F.shared")
             
@@ -104,7 +100,7 @@ class KeychainAccessTests: XCTestCase {
             XCTAssertEqual(password!, "1234_password")
         }
         
-        locally {
+        do {
             // Remove Keychain items
             let keychain = Keychain(service: "Twitter", accessGroup: "12ABCD3E4F.shared")
             
@@ -119,48 +115,48 @@ class KeychainAccessTests: XCTestCase {
     // MARK:
     
     func testInternetPassword() {
-        locally {
+        do {
             // Add Keychain items
             let keychain = Keychain(server: NSURL(string: "https://kishikawakatsumi.com")!, protocolType: .HTTPS)
             
-            keychain.set("kishikawa_katsumi", key: "username")
-            keychain.set("password_1234", key: "password")
+            do { try keychain.set("kishikawa_katsumi", key: "username") } catch {}
+            do { try keychain.set("password_1234", key: "password") } catch {}
             
-            let username = keychain.get("username")
+            let username = try! keychain.get("username")
             XCTAssertEqual(username!, "kishikawa_katsumi")
             
-            let password = keychain.get("password")
+            let password = try! keychain.get("password")
             XCTAssertEqual(password!, "password_1234")
         }
         
-        locally {
+        do {
             // Update Keychain items
             let keychain = Keychain(server: NSURL(string: "https://kishikawakatsumi.com")!, protocolType: .HTTPS)
             
-            keychain.set("katsumi_kishikawa", key: "username")
-            keychain.set("1234_password", key: "password")
+            do { try keychain.set("katsumi_kishikawa", key: "username") } catch {}
+            do { try keychain.set("1234_password", key: "password") } catch {}
             
-            let username = keychain.get("username")
+            let username = try! keychain.get("username")
             XCTAssertEqual(username!, "katsumi_kishikawa")
             
-            let password = keychain.get("password")
+            let password = try! keychain.get("password")
             XCTAssertEqual(password!, "1234_password")
         }
         
-        locally {
+        do {
             // Remove Keychain items
             let keychain = Keychain(server: NSURL(string: "https://kishikawakatsumi.com")!, protocolType: .HTTPS)
             
-            keychain.remove("username")
-            keychain.remove("password")
+            do { try keychain.remove("username") } catch {}
+            do { try keychain.remove("password") } catch {}
             
-            XCTAssertNil(keychain.get("username"))
-            XCTAssertNil(keychain.get("password"))
+            XCTAssertNil(try! keychain.get("username"))
+            XCTAssertNil(try! keychain.get("password"))
         }
     }
     
     func testInternetPasswordSubscripting() {
-        locally {
+        do {
             // Add Keychain items
             let keychain = Keychain(server: NSURL(string: "https://kishikawakatsumi.com")!, protocolType: .HTTPS)
             
@@ -174,7 +170,7 @@ class KeychainAccessTests: XCTestCase {
             XCTAssertEqual(password!, "password_1234")
         }
         
-        locally {
+        do {
             // Update Keychain items
             let keychain = Keychain(server: NSURL(string: "https://kishikawakatsumi.com")!, protocolType: .HTTPS)
             
@@ -188,7 +184,7 @@ class KeychainAccessTests: XCTestCase {
             XCTAssertEqual(password!, "1234_password")
         }
         
-        locally {
+        do {
             // Remove Keychain items
             let keychain = Keychain(server: NSURL(string: "https://kishikawakatsumi.com")!, protocolType: .HTTPS)
             
@@ -249,16 +245,16 @@ class KeychainAccessTests: XCTestCase {
     func testContains() {
         let keychain = Keychain(service: "Twitter")
         
-        XCTAssertFalse(keychain.contains("username"), "not stored username")
-        XCTAssertFalse(keychain.contains("password"), "not stored password")
+        XCTAssertFalse(try! keychain.contains("username"), "not stored username")
+        XCTAssertFalse(try! keychain.contains("password"), "not stored password")
         
-        keychain.set("kishikawakatsumi", key: "username")
-        XCTAssertTrue(keychain.contains("username"), "stored username")
-        XCTAssertFalse(keychain.contains("password"), "not stored password")
+        do { try keychain.set("kishikawakatsumi", key: "username") } catch {}
+        XCTAssertTrue(try! keychain.contains("username"), "stored username")
+        XCTAssertFalse(try! keychain.contains("password"), "not stored password")
         
-        keychain.set("password1234", key: "password")
-        XCTAssertTrue(keychain.contains("username"), "stored username")
-        XCTAssertTrue(keychain.contains("password"), "stored password")
+        do { try keychain.set("password1234", key: "password") } catch {}
+        XCTAssertTrue(try! keychain.contains("username"), "stored username")
+        XCTAssertTrue(try! keychain.contains("password"), "stored password")
     }
     
     // MARK:
@@ -266,74 +262,64 @@ class KeychainAccessTests: XCTestCase {
     func testSetString() {
         let keychain = Keychain(service: "Twitter")
         
-        XCTAssertNil(keychain.get("username"), "not stored username")
-        XCTAssertNil(keychain.get("password"), "not stored password")
+        XCTAssertNil(try! keychain.get("username"), "not stored username")
+        XCTAssertNil(try! keychain.get("password"), "not stored password")
         
-        keychain.set("kishikawakatsumi", key: "username")
-        XCTAssertEqual(keychain.get("username")!, "kishikawakatsumi", "stored username")
-        XCTAssertNil(keychain.get("password"), "not stored password")
+        do { try keychain.set("kishikawakatsumi", key: "username") } catch {}
+        XCTAssertEqual(try! keychain.get("username")!, "kishikawakatsumi", "stored username")
+        XCTAssertNil(try! keychain.get("password"), "not stored password")
         
-        keychain.set("password1234", key: "password")
-        XCTAssertEqual(keychain.get("username")!, "kishikawakatsumi", "stored username")
-        XCTAssertEqual(keychain.get("password")!, "password1234", "stored password")
+        do { try keychain.set("password1234", key: "password") } catch {}
+        XCTAssertEqual(try! keychain.get("username")!, "kishikawakatsumi", "stored username")
+        XCTAssertEqual(try! keychain.get("password")!, "password1234", "stored password")
     }
     
     func testSetData() {
         let JSONObject = ["username": "kishikawakatsumi", "password": "password1234"]
-        let JSONData: NSData?
-        do {
-            JSONData = try NSJSONSerialization.dataWithJSONObject(JSONObject, options: [])
-        } catch _ {
-            JSONData = nil
-        }
+        let JSONData = try! NSJSONSerialization.dataWithJSONObject(JSONObject, options: [])
         
         let keychain = Keychain(service: "Twitter")
         
-        XCTAssertNil(keychain.getData("JSONData"), "not stored JSON data")
+        XCTAssertNil(try! keychain.getData("JSONData"), "not stored JSON data")
         
-        keychain.set(JSONData!, key: "JSONData")
-        XCTAssertEqual(keychain.getData("JSONData")!, JSONData!, "stored JSON data")
+        do { try keychain.set(JSONData, key: "JSONData") } catch {}
+        XCTAssertEqual(try! keychain.getData("JSONData")!, JSONData, "stored JSON data")
     }
     
     func testRemoveString() {
         let keychain = Keychain(service: "Twitter")
         
-        XCTAssertNil(keychain.get("username"), "not stored username")
-        XCTAssertNil(keychain.get("password"), "not stored password")
+        XCTAssertNil(try! keychain.get("username"), "not stored username")
+        XCTAssertNil(try! keychain.get("password"), "not stored password")
         
-        keychain.set("kishikawakatsumi", key: "username")
-        XCTAssertEqual(keychain.get("username")!, "kishikawakatsumi", "stored username")
+        do { try keychain.set("kishikawakatsumi", key: "username") } catch {}
+        XCTAssertEqual(try! keychain.get("username")!, "kishikawakatsumi", "stored username")
         
-        keychain.set("password1234", key: "password")
-        XCTAssertEqual(keychain.get("password")!, "password1234", "stored password")
+        do { try keychain.set("password1234", key: "password") } catch {}
+        XCTAssertEqual(try! keychain.get("password")!, "password1234", "stored password")
         
-        keychain.remove("username")
-        XCTAssertNil(keychain.get("username"), "removed username")
-        XCTAssertEqual(keychain.get("password")!, "password1234", "left password")
+        do { try keychain.remove("username") } catch {}
+        XCTAssertNil(try! keychain.get("username"), "removed username")
+        XCTAssertEqual(try! keychain.get("password")!, "password1234", "left password")
         
-        keychain.remove("password")
-        XCTAssertNil(keychain.get("username"), "removed username")
-        XCTAssertNil(keychain.get("password"), "removed password")
+        do { try keychain.remove("password") } catch {}
+        XCTAssertNil(try! keychain.get("username"), "removed username")
+        XCTAssertNil(try! keychain.get("password"), "removed password")
     }
     
     func testRemoveData() {
         let JSONObject = ["username": "kishikawakatsumi", "password": "password1234"]
-        let JSONData: NSData?
-        do {
-            JSONData = try NSJSONSerialization.dataWithJSONObject(JSONObject, options: [])
-        } catch _ {
-            JSONData = nil
-        }
+        let JSONData = try! NSJSONSerialization.dataWithJSONObject(JSONObject, options: [])
         
         let keychain = Keychain(service: "Twitter")
         
-        XCTAssertNil(keychain.getData("JSONData"), "not stored JSON data")
+        XCTAssertNil(try! keychain.getData("JSONData"), "not stored JSON data")
         
-        keychain.set(JSONData!, key: "JSONData")
-        XCTAssertEqual(keychain.getData("JSONData")!, JSONData!, "stored JSON data")
+        do { try keychain.set(JSONData, key: "JSONData") } catch {}
+        XCTAssertEqual(try! keychain.getData("JSONData")!, JSONData, "stored JSON data")
         
-        keychain.remove("JSONData")
-        XCTAssertNil(keychain.getData("JSONData"), "removed JSON data")
+        do { try keychain.remove("JSONData") } catch {}
+        XCTAssertNil(try! keychain.getData("JSONData"), "removed JSON data")
     }
     
     // MARK:
@@ -367,182 +353,128 @@ class KeychainAccessTests: XCTestCase {
         XCTAssertNil(keychain[string: "password"], "removed password")
 
         let JSONObject = ["username": "kishikawakatsumi", "password": "password1234"]
-        let JSONData: NSData?
-        do {
-            JSONData = try NSJSONSerialization.dataWithJSONObject(JSONObject, options: [])
-        } catch _ {
-            JSONData = nil
-        }
+        let JSONData = try! NSJSONSerialization.dataWithJSONObject(JSONObject, options: [])
 
         XCTAssertNil(keychain[data:"JSONData"], "not stored JSON data")
 
         keychain[data: "JSONData"] = JSONData
-        XCTAssertEqual(keychain[data:"JSONData"]!, JSONData!, "stored JSON data")
+        XCTAssertEqual(keychain[data:"JSONData"]!, JSONData, "stored JSON data")
     }
     
     // MARK:
     
     #if os(iOS)
     func testErrorHandling() {
-        if let error = Keychain(service: "Twitter", accessGroup: "12ABCD3E4F.shared").removeAll() {
-            XCTAssertNil(error, "no error occurred")
+        do {
+            let keychain = Keychain(service: "Twitter", accessGroup: "12ABCD3E4F.shared")
+            try keychain.removeAll()
+            XCTAssertTrue(true, "no error occurred")
+        } catch {
+            XCTFail("error occurred")
         }
-        if let error = Keychain(service: "Twitter").removeAll() {
-            XCTAssertNil(error, "no error occurred")
+
+        do {
+            let keychain = Keychain(service: "Twitter")
+            try keychain.removeAll()
+            XCTAssertTrue(true, "no error occurred")
+        } catch {
+            XCTFail("error occurred")
         }
-        if let error = Keychain(server: NSURL(string: "https://kishikawakatsumi.com")!, protocolType: .HTTPS).removeAll() {
-            XCTAssertNil(error, "no error occurred")
+
+        do {
+            let keychain = Keychain(server: NSURL(string: "https://kishikawakatsumi.com")!, protocolType: .HTTPS)
+            try keychain.removeAll()
+            XCTAssertTrue(true, "no error occurred")
+        } catch {
+            XCTFail("error occurred")
         }
-        if let error = Keychain().removeAll() {
-            XCTAssertNil(error, "no error occurred")
+
+        do {
+            let keychain = Keychain()
+            try keychain.removeAll()
+            XCTAssertTrue(true, "no error occurred")
+        } catch {
+            XCTFail("error occurred")
         }
         
-        locally {
+        do {
             // Add Keychain items
             let keychain = Keychain(service: "Twitter")
-            
-            if let error = keychain.set("kishikawa_katsumi", key: "username") {
-                XCTAssertNil(error, "no error occurred")
-            }
-            if let error = keychain.set("password_1234", key: "password") {
-                XCTAssertNil(error, "no error occurred")
-            }
-            
-            let username = keychain.getStringOrError("username")
-    
-            switch username { // enum
-            case .Success:
-                XCTAssertEqual(username.value!, "kishikawa_katsumi")
-            case .Failure:
-                XCTFail("unknown error occurred")
-            }
-            
-            if let error = username.error { // error object
-                XCTAssertNotNil(error)
-                XCTFail("unknown error occurred")
-            } else {
-                XCTAssertEqual(username.value!, "kishikawa_katsumi")
-            }
-            
-            if username.succeeded { // check succeeded property
-                XCTAssertEqual(username.value!, "kishikawa_katsumi")
-            } else {
-                XCTFail("unknown error occurred")
+
+            do {
+                try keychain.set("kishikawa_katsumi", key: "username")
+                XCTAssertTrue(true, "no error occurred")
+            } catch {
+                XCTFail("error occurred")
             }
-            
-            if username.failed { // failed property
-                XCTFail("unknown error occurred")
-            } else {
-                XCTAssertEqual(username.value!, "kishikawa_katsumi")
+            do {
+                try keychain.set("password_1234", key: "password")
+                XCTAssertTrue(true, "no error occurred")
+            } catch {
+                XCTFail("error occurred")
             }
-    
-            let password = keychain.getStringOrError("password")
-            switch password { // enum
-            case .Success:
-                XCTAssertEqual(password.value!, "password_1234")
-            case .Failure:
-                XCTFail("unknown error occurred")
-            }
-            
-            if let error = password.error { // error object
-                XCTAssertNotNil(error)
-                XCTFail("unknown error occurred")
-            } else {
-                XCTAssertEqual(password.value!, "password_1234")
+
+            do {
+                let username = try keychain.get("username")
+                XCTAssertEqual(username, "kishikawa_katsumi")
+            } catch {
+                XCTFail("error occurred")
             }
-            
-            if password.succeeded { // check succeeded property
-                XCTAssertEqual(password.value!, "password_1234")
-            } else {
-                XCTFail("unknown error occurred")
-            }
-            
-            if password.failed { // failed property
-                XCTFail("unknown error occurred")
-            } else {
-                XCTAssertEqual(password.value!, "password_1234")
+            do {
+                let password = try keychain.get("password")
+                XCTAssertEqual(password, "password_1234")
+            } catch {
+                XCTFail("error occurred")
             }
         }
         
-        locally {
+        do {
             // Update Keychain items
             let keychain = Keychain(service: "Twitter")
-            
-            if let error = keychain.set("katsumi_kishikawa", key: "username") {
-                XCTAssertNil(error, "no error occurred")
-            }
-            if let error = keychain.set("1234_password", key: "password") {
-                XCTAssertNil(error, "no error occurred")
-            }
-            
-            let username = keychain.getStringOrError("username")
-            switch username { // enum
-            case .Success:
-                XCTAssertEqual(username.value!, "katsumi_kishikawa")
-            case .Failure:
-                XCTFail("unknown error occurred")
-            }
-            
-            if let error = username.error { // error object
-                XCTAssertNotNil(error)
-                XCTFail("unknown error occurred")
-            } else {
-                XCTAssertEqual(username.value!, "katsumi_kishikawa")
-            }
-            
-            if username.succeeded { // check succeeded property
-                XCTAssertEqual(username.value!, "katsumi_kishikawa")
-            } else {
-                XCTFail("unknown error occurred")
-            }
-            
-            if username.failed { // failed property
-                XCTFail("unknown error occurred")
-            } else {
-                XCTAssertEqual(username.value!, "katsumi_kishikawa")
-            }
-            
-            let password = keychain.getStringOrError("password")
-            switch password { // enum
-            case .Success:
-                XCTAssertEqual(password.value!, "1234_password")
-            case .Failure:
-                XCTFail("unknown error occurred")
+
+            do {
+                try keychain.set("katsumi_kishikawa", key: "username")
+                XCTAssertTrue(true, "no error occurred")
+            } catch {
+                XCTFail("error occurred")
             }
-            
-            if let error = password.error { // check error object
-                XCTAssertNotNil(error)
-                XCTFail("unknown error occurred")
-            } else {
-                XCTAssertEqual(password.value!, "1234_password")
+            do {
+                try keychain.set("1234_password", key: "password")
+                XCTAssertTrue(true, "no error occurred")
+            } catch {
+                XCTFail("error occurred")
             }
-            
-            if password.succeeded { // check succeeded property
-                XCTAssertEqual(password.value!, "1234_password")
-            } else {
-                XCTFail("unknown error occurred")
+
+            do {
+                let username = try keychain.get("username")
+                XCTAssertEqual(username, "katsumi_kishikawa")
+            } catch {
+                XCTFail("error occurred")
             }
-            
-            if password.failed { // check failed property
-                XCTFail("unknown error occurred")
-            } else {
-                XCTAssertEqual(password.value!, "1234_password")
+            do {
+                let password = try keychain.get("password")
+                XCTAssertEqual(password, "1234_password")
+            } catch {
+                XCTFail("error occurred")
             }
         }
         
-        locally {
+        do {
             // Remove Keychain items
             let keychain = Keychain(service: "Twitter")
-            
-            if let error = keychain.remove("username") {
-                XCTAssertNil(error, "no error occurred")
+
+            do {
+                try keychain.remove("username")
+                XCTAssertNil(try! keychain.get("username"))
+            } catch {
+                XCTFail("error occurred")
             }
-            if let error = keychain.remove("password") {
-                XCTAssertNil(error, "no error occurred")
+            do {
+                try keychain.remove("password")
+                XCTAssertNil(try! keychain.get("username"))
+            } catch {
+                XCTFail("error occurred")
             }
-            
-            XCTAssertNil(keychain.get("username"))
-            XCTAssertNil(keychain.get("password"))
         }
     }
     #endif
@@ -561,114 +493,114 @@ class KeychainAccessTests: XCTestCase {
         let service_2 = "com.kishikawakatsumi.KeychainAccess"
         let service_3 = "example.com"
         
-        Keychain().removeAll()
-        Keychain(service: service_1).removeAll()
-        Keychain(service: service_2).removeAll()
-        Keychain(service: service_3).removeAll()
-        
-        XCTAssertNil(Keychain().get("username"), "not stored username")
-        XCTAssertNil(Keychain().get("password"), "not stored password")
-        XCTAssertNil(Keychain(service: service_1).get("username"), "not stored username")
-        XCTAssertNil(Keychain(service: service_1).get("password"), "not stored password")
-        XCTAssertNil(Keychain(service: service_2).get("username"), "not stored username")
-        XCTAssertNil(Keychain(service: service_2).get("password"), "not stored password")
-        XCTAssertNil(Keychain(service: service_3).get("username"), "not stored username")
-        XCTAssertNil(Keychain(service: service_3).get("password"), "not stored password")
-        
-        Keychain().set(username_1, key: "username")
-        XCTAssertEqual(Keychain().get("username")!, username_1, "stored username")
-        XCTAssertEqual(Keychain(service: service_1).get("username")!, username_1, "stored username")
-        XCTAssertNil(Keychain(service: service_2).get("username"), "not stored username")
-        XCTAssertNil(Keychain(service: service_3).get("username"), "not stored username")
-        
-        Keychain(service: service_1).set(username_1, key: "username")
-        XCTAssertEqual(Keychain().get("username")!, username_1, "stored username")
-        XCTAssertEqual(Keychain(service: service_1).get("username")!, username_1, "stored username")
-        XCTAssertNil(Keychain(service: service_2).get("username"), "not stored username")
-        XCTAssertNil(Keychain(service: service_3).get("username"), "not stored username")
-        
-        Keychain(service: service_2).set(username_2, key: "username")
-        XCTAssertEqual(Keychain().get("username")!, username_1, "stored username")
-        XCTAssertEqual(Keychain(service: service_1).get("username")!, username_1, "stored username")
-        XCTAssertEqual(Keychain(service: service_2).get("username")!, username_2, "stored username")
-        XCTAssertNil(Keychain(service: service_3).get("username"), "not stored username")
-        
-        Keychain(service: service_3).set(username_3, key: "username")
-        XCTAssertEqual(Keychain().get("username")!, username_1, "stored username")
-        XCTAssertEqual(Keychain(service: service_1).get("username")!, username_1, "stored username")
-        XCTAssertEqual(Keychain(service: service_2).get("username")!, username_2, "stored username")
-        XCTAssertEqual(Keychain(service: service_3).get("username")!, username_3, "stored username")
-        
-        Keychain().set(password_1, key: "password")
-        XCTAssertEqual(Keychain().get("password")!, password_1, "stored password")
-        XCTAssertEqual(Keychain(service: service_1).get("password")!, password_1, "stored password")
-        XCTAssertNil(Keychain(service: service_2).get("password"), "not stored password")
-        XCTAssertNil(Keychain(service: service_3).get("password"), "not stored password")
-        
-        Keychain(service: service_1).set(password_1, key: "password")
-        XCTAssertEqual(Keychain().get("password")!, password_1, "stored password")
-        XCTAssertEqual(Keychain(service: service_1).get("password")!, password_1, "stored password")
-        XCTAssertNil(Keychain(service: service_2).get("password"), "not stored password")
-        XCTAssertNil(Keychain(service: service_3).get("password"), "not stored password")
-        
-        Keychain(service: service_2).set(password_2, key: "password")
-        XCTAssertEqual(Keychain().get("password")!, password_1, "stored password")
-        XCTAssertEqual(Keychain(service: service_1).get("password")!, password_1, "stored password")
-        XCTAssertEqual(Keychain(service: service_2).get("password")!, password_2, "stored password")
-        XCTAssertNil(Keychain(service: service_3).get("password"), "not stored password")
-        
-        Keychain(service: service_3).set(password_3, key: "password")
-        XCTAssertEqual(Keychain().get("password")!, password_1, "stored password")
-        XCTAssertEqual(Keychain(service: service_1).get("password")!, password_1, "stored password")
-        XCTAssertEqual(Keychain(service: service_2).get("password")!, password_2, "stored password")
-        XCTAssertEqual(Keychain(service: service_3).get("password")!, password_3, "stored password")
-        
-        Keychain().remove("username")
-        XCTAssertNil(Keychain().get("username"), "removed username")
-        XCTAssertNil(Keychain(service: service_1).get("username"), "removed username")
-        XCTAssertEqual(Keychain(service: service_2).get("username")!, username_2, "left username")
-        XCTAssertEqual(Keychain(service: service_3).get("username")!, username_3, "left username")
-        
-        Keychain(service: service_1).remove("username")
-        XCTAssertNil(Keychain().get("username"), "removed username")
-        XCTAssertNil(Keychain(service: service_1).get("username"), "removed username")
-        XCTAssertEqual(Keychain(service: service_2).get("username")!, username_2, "left username")
-        XCTAssertEqual(Keychain(service: service_3).get("username")!, username_3, "left username")
-        
-        Keychain(service: service_2).remove("username")
-        XCTAssertNil(Keychain().get("username"), "removed username")
-        XCTAssertNil(Keychain(service: service_1).get("username"), "removed username")
-        XCTAssertNil(Keychain(service: service_2).get("username"), "removed username")
-        XCTAssertEqual(Keychain(service: service_3).get("username")!, username_3, "left username")
-        
-        Keychain(service: service_3).remove("username")
-        XCTAssertNil(Keychain().get("username"), "removed username")
-        XCTAssertNil(Keychain(service: service_1).get("username"), "removed username")
-        XCTAssertNil(Keychain(service: service_2).get("username"), "removed username")
-        XCTAssertNil(Keychain(service: service_3).get("username"), "removed username")
-        
-        Keychain().remove("password")
-        XCTAssertNil(Keychain().get("password"), "removed password")
-        XCTAssertNil(Keychain(service: service_1).get("password"), "removed password")
-        XCTAssertEqual(Keychain(service: service_2).get("password")!, password_2, "left password")
-        XCTAssertEqual(Keychain(service: service_3).get("password")!, password_3, "left password")
-        
-        Keychain(service: service_1).remove("password")
-        XCTAssertNil(Keychain().get("password"), "removed password")
-        XCTAssertNil(Keychain(service: service_1).get("password"), "removed password")
-        XCTAssertEqual(Keychain(service: service_2).get("password")!, password_2, "left password")
-        XCTAssertEqual(Keychain(service: service_3).get("password")!, password_3, "left password")
-        
-        Keychain(service: service_2).remove("password")
-        XCTAssertNil(Keychain().get("password"), "removed password")
-        XCTAssertNil(Keychain(service: service_1).get("password"), "removed password")
-        XCTAssertNil(Keychain(service: service_2).get("password"), "removed password")
-        XCTAssertEqual(Keychain(service: service_3).get("password")!, password_3, "left password")
-        
-        Keychain(service: service_3).remove("password")
-        XCTAssertNil(Keychain().get("password"), "removed password")
-        XCTAssertNil(Keychain(service: service_2).get("password"), "removed password")
-        XCTAssertNil(Keychain(service: service_2).get("password"), "removed password")
-        XCTAssertNil(Keychain(service: service_2).get("password"), "removed password")
+        do { try Keychain().removeAll() } catch {}
+        do { try Keychain(service: service_1).removeAll() } catch {}
+        do { try Keychain(service: service_2).removeAll() } catch {}
+        do { try Keychain(service: service_3).removeAll() } catch {}
+        
+        XCTAssertNil(try! Keychain().get("username"), "not stored username")
+        XCTAssertNil(try! Keychain().get("password"), "not stored password")
+        XCTAssertNil(try! Keychain(service: service_1).get("username"), "not stored username")
+        XCTAssertNil(try! Keychain(service: service_1).get("password"), "not stored password")
+        XCTAssertNil(try! Keychain(service: service_2).get("username"), "not stored username")
+        XCTAssertNil(try! Keychain(service: service_2).get("password"), "not stored password")
+        XCTAssertNil(try! Keychain(service: service_3).get("username"), "not stored username")
+        XCTAssertNil(try! Keychain(service: service_3).get("password"), "not stored password")
+        
+        do { try Keychain().set(username_1, key: "username") } catch {}
+        XCTAssertEqual(try! Keychain().get("username")!, username_1, "stored username")
+        XCTAssertEqual(try! Keychain(service: service_1).get("username")!, username_1, "stored username")
+        XCTAssertNil(try! Keychain(service: service_2).get("username"), "not stored username")
+        XCTAssertNil(try! Keychain(service: service_3).get("username"), "not stored username")
+        
+        do { try Keychain(service: service_1).set(username_1, key: "username") } catch {}
+        XCTAssertEqual(try! Keychain().get("username")!, username_1, "stored username")
+        XCTAssertEqual(try! Keychain(service: service_1).get("username")!, username_1, "stored username")
+        XCTAssertNil(try! Keychain(service: service_2).get("username"), "not stored username")
+        XCTAssertNil(try! Keychain(service: service_3).get("username"), "not stored username")
+        
+        do { try Keychain(service: service_2).set(username_2, key: "username") } catch {}
+        XCTAssertEqual(try! Keychain().get("username")!, username_1, "stored username")
+        XCTAssertEqual(try! Keychain(service: service_1).get("username")!, username_1, "stored username")
+        XCTAssertEqual(try! Keychain(service: service_2).get("username")!, username_2, "stored username")
+        XCTAssertNil(try! Keychain(service: service_3).get("username"), "not stored username")
+        
+        do { try Keychain(service: service_3).set(username_3, key: "username") } catch {}
+        XCTAssertEqual(try! Keychain().get("username")!, username_1, "stored username")
+        XCTAssertEqual(try! Keychain(service: service_1).get("username")!, username_1, "stored username")
+        XCTAssertEqual(try! Keychain(service: service_2).get("username")!, username_2, "stored username")
+        XCTAssertEqual(try! Keychain(service: service_3).get("username")!, username_3, "stored username")
+
+        do { try Keychain().set(password_1, key: "password") } catch {}
+        XCTAssertEqual(try! Keychain().get("password")!, password_1, "stored password")
+        XCTAssertEqual(try! Keychain(service: service_1).get("password")!, password_1, "stored password")
+        XCTAssertNil(try! Keychain(service: service_2).get("password"), "not stored password")
+        XCTAssertNil(try! Keychain(service: service_3).get("password"), "not stored password")
+        
+        do { try Keychain(service: service_1).set(password_1, key: "password") } catch {}
+        XCTAssertEqual(try! Keychain().get("password")!, password_1, "stored password")
+        XCTAssertEqual(try! Keychain(service: service_1).get("password")!, password_1, "stored password")
+        XCTAssertNil(try! Keychain(service: service_2).get("password"), "not stored password")
+        XCTAssertNil(try! Keychain(service: service_3).get("password"), "not stored password")
+        
+        do { try Keychain(service: service_2).set(password_2, key: "password") } catch {}
+        XCTAssertEqual(try! Keychain().get("password")!, password_1, "stored password")
+        XCTAssertEqual(try! Keychain(service: service_1).get("password")!, password_1, "stored password")
+        XCTAssertEqual(try! Keychain(service: service_2).get("password")!, password_2, "stored password")
+        XCTAssertNil(try! Keychain(service: service_3).get("password"), "not stored password")
+        
+        do { try Keychain(service: service_3).set(password_3, key: "password") } catch {}
+        XCTAssertEqual(try! Keychain().get("password")!, password_1, "stored password")
+        XCTAssertEqual(try! Keychain(service: service_1).get("password")!, password_1, "stored password")
+        XCTAssertEqual(try! Keychain(service: service_2).get("password")!, password_2, "stored password")
+        XCTAssertEqual(try! Keychain(service: service_3).get("password")!, password_3, "stored password")
+        
+        do { try Keychain().remove("username") } catch {}
+        XCTAssertNil(try! Keychain().get("username"), "removed username")
+        XCTAssertNil(try! Keychain(service: service_1).get("username"), "removed username")
+        XCTAssertEqual(try! Keychain(service: service_2).get("username")!, username_2, "left username")
+        XCTAssertEqual(try! Keychain(service: service_3).get("username")!, username_3, "left username")
+        
+        do { try Keychain(service: service_1).remove("username") } catch {}
+        XCTAssertNil(try! Keychain().get("username"), "removed username")
+        XCTAssertNil(try! Keychain(service: service_1).get("username"), "removed username")
+        XCTAssertEqual(try! Keychain(service: service_2).get("username")!, username_2, "left username")
+        XCTAssertEqual(try! Keychain(service: service_3).get("username")!, username_3, "left username")
+        
+        do { try Keychain(service: service_2).remove("username") } catch {}
+        XCTAssertNil(try! Keychain().get("username"), "removed username")
+        XCTAssertNil(try! Keychain(service: service_1).get("username"), "removed username")
+        XCTAssertNil(try! Keychain(service: service_2).get("username"), "removed username")
+        XCTAssertEqual(try! Keychain(service: service_3).get("username")!, username_3, "left username")
+        
+        do { try Keychain(service: service_3).remove("username") } catch {}
+        XCTAssertNil(try! Keychain().get("username"), "removed username")
+        XCTAssertNil(try! Keychain(service: service_1).get("username"), "removed username")
+        XCTAssertNil(try! Keychain(service: service_2).get("username"), "removed username")
+        XCTAssertNil(try! Keychain(service: service_3).get("username"), "removed username")
+        
+        do { try Keychain().remove("password") } catch {}
+        XCTAssertNil(try! Keychain().get("password"), "removed password")
+        XCTAssertNil(try! Keychain(service: service_1).get("password"), "removed password")
+        XCTAssertEqual(try! Keychain(service: service_2).get("password")!, password_2, "left password")
+        XCTAssertEqual(try! Keychain(service: service_3).get("password")!, password_3, "left password")
+        
+        do { try Keychain(service: service_1).remove("password") } catch {}
+        XCTAssertNil(try! Keychain().get("password"), "removed password")
+        XCTAssertNil(try! Keychain(service: service_1).get("password"), "removed password")
+        XCTAssertEqual(try! Keychain(service: service_2).get("password")!, password_2, "left password")
+        XCTAssertEqual(try! Keychain(service: service_3).get("password")!, password_3, "left password")
+        
+        do { try Keychain(service: service_2).remove("password") } catch {}
+        XCTAssertNil(try! Keychain().get("password"), "removed password")
+        XCTAssertNil(try! Keychain(service: service_1).get("password"), "removed password")
+        XCTAssertNil(try! Keychain(service: service_2).get("password"), "removed password")
+        XCTAssertEqual(try! Keychain(service: service_3).get("password")!, password_3, "left password")
+        
+        do { try Keychain(service: service_3).remove("password") } catch {}
+        XCTAssertNil(try! Keychain().get("password"), "removed password")
+        XCTAssertNil(try! Keychain(service: service_2).get("password"), "removed password")
+        XCTAssertNil(try! Keychain(service: service_2).get("password"), "removed password")
+        XCTAssertNil(try! Keychain(service: service_2).get("password"), "removed password")
     }
 }

+ 62 - 101
README.md

@@ -95,7 +95,7 @@ keychain.set("01234567-89ab-cdef-0123-456789abcdef", key: "kishikawakatsumi")
 
 ```swift
 if let error = keychain.set("01234567-89ab-cdef-0123-456789abcdef", key: "kishikawakatsumi") {
-    println("error: \(error)")
+    print("error: \(error)")
 }
 ```
 
@@ -124,66 +124,17 @@ let secretData = keychain[data: "secret"]
 ##### as String
 
 ```swift
-let token = keychain.get("kishikawakatsumi")
+let token = try? keychain.get("kishikawakatsumi")
 ```
 
 ```swift
-let token = keychain.getString("kishikawakatsumi")
+let token = try? keychain.getString("kishikawakatsumi")
 ```
 
 ##### as NSData
 
 ```swift
-let data = keychain.getData("kishikawakatsumi")
-```
-
-#### error handling
-
-**First, get the `failable` (value or error) object**
-
-```swift
-let failable = keychain.getStringOrError("kishikawakatsumi")
-```
-
-**1. check `enum` state**
-
-```swift
-switch failable {
-case .Success:
-  println("token: \(failable.value)")
-case .Failure:
-  println("error: \(failable.error)")
-}
-```
-
-**2. check `error` object**
-
-```swift
-if let error = failable.error {
-    println("error: \(error)")
-} else {
-    println("token: \(failable.value)")
-}
-```
-
-**3. check `succeeded` property**
-
-```swift
-if failable.succeeded {
-    println("token: \(failable.value)")
-} else {
-    println("error: \(failable.error)")
-}
-```
-
-**4. check `failed` property**
-
-```swift
-if failable.failed {
-    println("error: \(failable.error)")
-} else {
-    println("token: \(failable.value)")
-}
+let data = try? keychain.getData("kishikawakatsumi")
 ```
 
 ### :key: Removing an item
@@ -197,14 +148,10 @@ keychain["kishikawakatsumi"] = nil
 #### remove method
 
 ```swift
-keychain.remove("kishikawakatsumi")
-```
-
-#### error handling
-
-```swift
-if let error = keychain.remove("kishikawakatsumi") {
-    println("error: \(error)")
+do {
+    try keychain.remove("kishikawakatsumi")
+} catch let error {
+    print("error: \(error)")
 }
 ```
 
@@ -212,10 +159,14 @@ if let error = keychain.remove("kishikawakatsumi") {
 
 ```swift
 let keychain = Keychain(server: "https://github.com", protocolType: .HTTPS)
-keychain
-    .label("github.com (kishikawakatsumi)")
-    .comment("github access token")
-    .set("01234567-89ab-cdef-0123-456789abcdef", key: "kishikawakatsumi")
+do {
+    try keychain
+        .label("github.com (kishikawakatsumi)")
+        .comment("github access token")
+        .set("01234567-89ab-cdef-0123-456789abcdef", key: "kishikawakatsumi")
+} catch let error {
+    print("error: \(error)")
+}
 ```
 
 ### :key: Configuration (Accessibility, Sharing, iCould Sync)
@@ -253,9 +204,13 @@ keychain["kishikawakatsumi"] = "01234567-89ab-cdef-0123-456789abcdef"
 ```swift
 let keychain = Keychain(service: "com.example.github-token")
 
-keychain
-    .accessibility(.AfterFirstUnlock)
-    .set("01234567-89ab-cdef-0123-456789abcdef", key: "kishikawakatsumi")
+do {
+    try keychain
+        .accessibility(.AfterFirstUnlock)
+        .set("01234567-89ab-cdef-0123-456789abcdef", key: "kishikawakatsumi")
+} catch let error {
+    print("error: \(error)")
+}
 ```
 
 ##### For foreground application
@@ -274,9 +229,13 @@ keychain["kishikawakatsumi"] = "01234567-89ab-cdef-0123-456789abcdef"
 ```swift
 let keychain = Keychain(service: "com.example.github-token")
 
-keychain
-    .accessibility(.WhenUnlocked)
-    .set("01234567-89ab-cdef-0123-456789abcdef", key: "kishikawakatsumi")
+do {
+    try keychain
+        .accessibility(.WhenUnlocked)
+        .set("01234567-89ab-cdef-0123-456789abcdef", key: "kishikawakatsumi")
+} catch let error {
+    print("error: \(error)")
+}
 ```
 
 #### :couple: Sharing Keychain items
@@ -301,9 +260,13 @@ keychain["kishikawakatsumi"] = "01234567-89ab-cdef-0123-456789abcdef"
 ```swift
 let keychain = Keychain(service: "com.example.github-token")
 
-keychain
-    .synchronizable(true)
-    .set("01234567-89ab-cdef-0123-456789abcdef", key: "kishikawakatsumi")
+do {
+    try keychain
+        .synchronizable(true)
+        .set("01234567-89ab-cdef-0123-456789abcdef", key: "kishikawakatsumi")
+} catch let error {
+    print("error: \(error)")
+}
 ```
 
 ### <a name="touch_id_integration"> :fu: Touch ID integration
@@ -319,11 +282,11 @@ If you want to store the Touch ID protected Keychain item, specify `accessibilit
 let keychain = Keychain(service: "com.example.github-token")
 
 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
-    let error = keychain
-        .accessibility(.WhenPasscodeSetThisDeviceOnly, authenticationPolicy: .UserPresence)
-        .set("01234567-89ab-cdef-0123-456789abcdef", key: "kishikawakatsumi")
-
-    if error != nil {
+    do {
+        try keychain
+            .accessibility(.WhenPasscodeSetThisDeviceOnly, authenticationPolicy: .UserPresence)
+            .set("01234567-89ab-cdef-0123-456789abcdef", key: "kishikawakatsumi")
+    } catch let error {
         // Error handling if needed...
     }
 }
@@ -343,12 +306,12 @@ If the item not protected, the `authenticationPrompt` parameter just be ignored.
 let keychain = Keychain(service: "com.example.github-token")
 
 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
-    let error = keychain
-        .accessibility(.WhenPasscodeSetThisDeviceOnly, authenticationPolicy: .UserPresence)
-        .authenticationPrompt("Authenticate to update your access token")
-        .set("01234567-89ab-cdef-0123-456789abcdef", key: "kishikawakatsumi")
-
-    if error != nil {
+    do {
+        try keychain
+            .accessibility(.WhenPasscodeSetThisDeviceOnly, authenticationPolicy: .UserPresence)
+            .authenticationPrompt("Authenticate to update your access token")
+            .set("01234567-89ab-cdef-0123-456789abcdef", key: "kishikawakatsumi")
+    } catch let error {
         // Error handling if needed...
     }
 }
@@ -364,14 +327,13 @@ If the item not protected, the `authenticationPrompt` parameter just be ignored.
 let keychain = Keychain(service: "com.example.github-token")
 
 dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
-    let failable = keychain
-        .authenticationPrompt("Authenticate to login to server")
-        .getStringOrError("kishikawakatsumi")
-
-    if failable.succeeded {
-        println("value: \(failable.value)")
-    } else {
-        println("error: \(failable.error?.localizedDescription)")
+    do {
+        let password = try keychain
+            .authenticationPrompt("Authenticate to login to server")
+            .get("kishikawakatsumi")
+
+        print("password: \(password)")
+    } catch let error {
         // Error handling if needed...
     }
 }
@@ -385,10 +347,9 @@ There is no way to show Touch ID or passcode authentication when removing Keycha
 ```swift
 let keychain = Keychain(service: "com.example.github-token")
 
-let error = keychain.remove("kishikawakatsumi")
-
-if error != nil {
-    println("error: \(error?.localizedDescription)")
+do {
+    try keychain.remove("kishikawakatsumi")
+} catch let error {
     // Error handling if needed...
 }
 ```
@@ -405,7 +366,7 @@ let keychain = Keychain(server: "https://www.kishikawakatsumi.com", protocolType
 let username = "kishikawakatsumi@mac.com"
 
 // First, check the credential in the app's Keychain
-if let password = keychain.get(username) {
+if let password = try? keychain.get(username) {
     // If found password in the Keychain,
     // then log into the server
 } else {
@@ -467,7 +428,7 @@ let password = Keychain.generatePassword() // => Nhu-GKm-s3n-pMx
 
 ```swift
 let keychain = Keychain(server: "https://github.com", protocolType: .HTTPS)
-println("\(keychain)")
+print("\(keychain)")
 ```
 
 ```
@@ -486,7 +447,7 @@ let keychain = Keychain(server: "https://github.com", protocolType: .HTTPS)
 
 let keys = keychain.allKeys()
 for key in keys {
-  println("key: \(key)")
+  print("key: \(key)")
 }
 ```
 
@@ -504,7 +465,7 @@ let keychain = Keychain(server: "https://github.com", protocolType: .HTTPS)
 
 let items = keychain.allItems()
 for item in items {
-  println("item: \(item)")
+  print("item: \(item)")
 }
 ```