Explorar o código

Merge pull request #31 from kishikawakatsumi/ios7_compat

Fix compatibility for iOS 7
kishikawa katsumi %!s(int64=10) %!d(string=hai) anos
pai
achega
892b396aef
Modificáronse 2 ficheiros con 61 adicións e 24 borrados
  1. 60 24
      Lib/KeychainAccess/Keychain.swift
  2. 1 0
      Lib/Rakefile

+ 60 - 24
Lib/KeychainAccess/Keychain.swift

@@ -157,7 +157,9 @@ public class Keychain {
     public var accessibility: Accessibility {
         return options.accessibility
     }
-
+    
+    @availability(iOS, introduced=8.0)
+    @availability(OSX, introduced=10.10)
     public var authenticationPolicy: AuthenticationPolicy? {
         return options.authenticationPolicy
     }
@@ -174,12 +176,17 @@ public class Keychain {
         return options.comment
     }
     
+    @availability(iOS, introduced=8.0)
+    @availability(OSX, unavailable)
     public var authenticationPrompt: String? {
         return options.authenticationPrompt
     }
     
     private let options: Options
     
+    private let NSFoundationVersionNumber_iOS_7_1 = 1047.25
+    private let NSFoundationVersionNumber10_9_2 = 1056.13
+    
     // MARK:
     
     public convenience init() {
@@ -237,6 +244,8 @@ public class Keychain {
         return Keychain(options)
     }
     
+    @availability(iOS, introduced=8.0)
+    @availability(OSX, introduced=10.10)
     public func accessibility(accessibility: Accessibility, authenticationPolicy: AuthenticationPolicy) -> Keychain {
         var options = self.options
         options.accessibility = accessibility
@@ -262,13 +271,13 @@ public class Keychain {
         return Keychain(options)
     }
     
-    #if os(iOS)
+    @availability(iOS, introduced=8.0)
+    @availability(OSX, unavailable)
     public func authenticationPrompt(authenticationPrompt: String) -> Keychain {
         var options = self.options
         options.authenticationPrompt = authenticationPrompt
         return Keychain(options)
     }
-    #endif
     
     // MARK:
     
@@ -342,7 +351,9 @@ public class Keychain {
         
         query[kSecAttrAccount] = key
         #if os(iOS)
-        query[kSecUseNoAuthenticationUI] = kCFBooleanTrue
+        if floor(NSFoundationVersionNumber) > floor(NSFoundationVersionNumber_iOS_7_1) {
+            query[kSecUseNoAuthenticationUI] = kCFBooleanTrue
+        }
         #endif
         
         var status = SecItemCopyMatching(query, nil)
@@ -682,7 +693,11 @@ extension Options {
         
         #if os(iOS)
         if authenticationPrompt != nil {
-            query[kSecUseOperationPrompt] = authenticationPrompt
+            if floor(NSFoundationVersionNumber) > floor(NSFoundationVersionNumber_iOS_7_1) {
+                query[kSecUseOperationPrompt] = authenticationPrompt
+            } else {
+                println("Unavailable 'authenticationPrompt' attribute on iOS versions prior to 8.0.")
+            }
         }
         #endif
         
@@ -708,28 +723,49 @@ extension Options {
             attributes[kSecAttrComment] = comment
         }
         
+        #if os(iOS)
+        let iOS_7_1_or_10_9_2 = NSFoundationVersionNumber_iOS_7_1
+        #else
+        let iOS_7_1_or_10_9_2 = NSFoundationVersionNumber10_9_2
+        #endif
         if let policy = authenticationPolicy {
-            var error: Unmanaged<CFError>?
-            let accessControl = SecAccessControlCreateWithFlags(
-                kCFAllocatorDefault,
-                accessibility.rawValue,
-                SecAccessControlCreateFlags(policy.rawValue),
-                &error
-            )
-            if let error = error?.takeUnretainedValue() {
-                var code = CFErrorGetCode(error)
-                var domain = CFErrorGetDomain(error)
-                var userInfo = CFErrorCopyUserInfo(error)
-                
-                return (attributes, NSError(domain: domain, code: code, userInfo: userInfo))
-            }
-            if accessControl == nil {
-                let message = Status.UnexpectedError.description
-                return (attributes, NSError(domain: KeychainAccessErrorDomain, code: Int(Status.UnexpectedError.rawValue), userInfo: [NSLocalizedDescriptionKey: message]))
+            if floor(NSFoundationVersionNumber) > floor(iOS_7_1_or_10_9_2) {
+                var error: Unmanaged<CFError>?
+                let accessControl = SecAccessControlCreateWithFlags(
+                    kCFAllocatorDefault,
+                    accessibility.rawValue,
+                    SecAccessControlCreateFlags(policy.rawValue),
+                    &error
+                )
+                if let error = error?.takeUnretainedValue() {
+                    var code = CFErrorGetCode(error)
+                    var domain = CFErrorGetDomain(error)
+                    var userInfo = CFErrorCopyUserInfo(error)
+                    
+                    return (attributes, NSError(domain: domain, code: code, userInfo: userInfo))
+                }
+                if accessControl == nil {
+                    let message = Status.UnexpectedError.description
+                    return (attributes, NSError(domain: KeychainAccessErrorDomain, code: Int(Status.UnexpectedError.rawValue), userInfo: [NSLocalizedDescriptionKey: message]))
+                }
+                attributes[kSecAttrAccessControl] = accessControl.takeUnretainedValue()
+            } else {
+                #if os(iOS)
+                println("Unavailable 'Touch ID integration' on iOS versions prior to 8.0.")
+                #else
+                println("Unavailable 'Touch ID integration' on OS X versions prior to 10.10.")
+                #endif
             }
-            attributes[kSecAttrAccessControl] = accessControl.takeUnretainedValue()
         } else {
-            attributes[kSecAttrAccessible] = accessibility.rawValue
+            if floor(NSFoundationVersionNumber) <= floor(iOS_7_1_or_10_9_2) && accessibility == .WhenPasscodeSetThisDeviceOnly {
+                #if os(iOS)
+                println("Unavailable 'Accessibility.WhenPasscodeSetThisDeviceOnly' attribute on iOS versions prior to 8.0.")
+                #else
+                println("Unavailable 'Accessibility.WhenPasscodeSetThisDeviceOnly' attribute on OS X versions prior to 10.10.")
+                #endif
+            } else {
+                attributes[kSecAttrAccessible] = accessibility.rawValue
+            }
         }
         
         attributes[kSecAttrSynchronizable] = synchronizable

+ 1 - 0
Lib/Rakefile

@@ -4,6 +4,7 @@ def destinations
   [ 'name=iPad 2,OS=8.1',
     'name=iPad Air,OS=8.1',
     'name=iPhone 4s,OS=8.1',
+    'name=iPhone 5,OS=8.1',
     'name=iPhone 5s,OS=8.1',
     'name=iPhone 6,OS=8.1',
     'name=iPhone 6 Plus,OS=8.1'