2014-10-14 12 views
5

हमने चाकू में एक ऐप बनाया है जो कि चाबी का उपयोग करता है। डिवाइस पर या सिम्युलेटर में चलाने पर ऐप ठीक काम करता है लेकिन टेस्टफलाइट के माध्यम से प्रावधान किए जाने पर कीचेन तक नहीं पहुंच सकता है जब तक कि किसी नए डिवाइस के लिए प्रावधान नहीं किया गया हो जिसे पहले कभी भी एक्सकोड 6.1 के माध्यम से ऐप इंस्टॉल नहीं किया गया था। - "com.ourdomain" थास्विफ्ट कीचेन और प्रावधान प्रोफाइल

import UIKit 
    import Security 

    let serviceIdentifier = "com.ourdomain" 

    let kSecClassValue = kSecClass as NSString 
    let kSecAttrAccountValue = kSecAttrAccount as NSString 
    let kSecValueDataValue = kSecValueData as NSString 
    let kSecClassGenericPasswordValue = kSecClassGenericPassword as NSString 
    let kSecAttrServiceValue = kSecAttrService as NSString 
    let kSecMatchLimitValue = kSecMatchLimit as NSString 
    let kSecReturnDataValue = kSecReturnData as NSString 
    let kSecMatchLimitOneValue = kSecMatchLimitOne as NSString 

class KeychainManager { 

    class func setString(value: NSString, forKey: String) { 
     self.save(serviceIdentifier, key: forKey, data: value) 
    } 

    class func stringForKey(key: String) -> NSString? { 
     var token = self.load(serviceIdentifier, key: key) 

     return token 
    } 

    class func removeItemForKey(key: String) { 
     self.save(serviceIdentifier, key: key, data: "") 
    } 



    class func save(service: NSString, key: String, data: NSString) { 
     var dataFromString: NSData = data.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)! 
     // Instantiate a new default keychain query 
     var keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, key, dataFromString], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecValueDataValue]) 

     // Delete any existing items 
     SecItemDelete(keychainQuery as CFDictionaryRef) 

     if data == "" { return } 

     // Add the new keychain item 
     var status: OSStatus = SecItemAdd(keychainQuery as CFDictionaryRef, nil) 
    } 

    class func load(service: NSString, key: String) -> NSString? { 
     // Instantiate a new default keychain query 
     // Tell the query to return a result 
     // Limit our results to one item 
     var keychainQuery: NSMutableDictionary = NSMutableDictionary(objects: [kSecClassGenericPasswordValue, service, key, kCFBooleanTrue, kSecMatchLimitOneValue], forKeys: [kSecClassValue, kSecAttrServiceValue, kSecAttrAccountValue, kSecReturnDataValue, kSecMatchLimitValue]) 

     var dataTypeRef :Unmanaged<AnyObject>? 

     // Search for the keychain items 
     let status: OSStatus = SecItemCopyMatching(keychainQuery, &dataTypeRef) 

     let opaque = dataTypeRef?.toOpaque() 

     var contentsOfKeychain: NSString? 

     if let op = opaque? { 
      let retrievedData = Unmanaged<NSData>.fromOpaque(op).takeUnretainedValue() 

      // Convert the data retrieved from the keychain into a string 
      contentsOfKeychain = NSString(data: retrievedData, encoding: NSUTF8StringEncoding) 
     } else { 
      return nil 
     } 

     return contentsOfKeychain 
    } 
    } 

एप्लिकेशन पहले से ही मैंने देखा है कि "serviceIdentifier" Xcode 6.1 के माध्यम से डिवाइस पर स्थापित किया गया था के बाद:

बाद कीचेन कोड का एक अंश है ग़लत और प्रावधान के साथ आवश्यक ऐप के बंडल पहचानकर्ता से मेल नहीं खाता। "com.ourdomain.appname" हालांकि एप्लिकेशन सिर्फ डिवाइस पर काम नहीं करेगा जब Testflight के माध्यम से प्रावधान -

मैं तो "serviceIdentifier" मूल्य बंडल पहचानकर्ता मैच के लिए बदल दिया है। मैं सकारात्मक हूं क्योंकि इस डिवाइस में पहले से ही गलत पहचानकर्ता के साथ स्थापित बंडल आईडी के लिए कीचेन है लेकिन मैं इस बात को समझ नहीं सकता कि ऐप हटा दिए जाने पर या चार्ज करने के लिए प्रोविजनिंग प्रोफाइल प्राप्त करने के लिए कुंजीपटल को हटाने के लिए इसे कैसे प्राप्त किया जाए मौजूदा कीचेन (गलत पहचानकर्ता के साथ)

किसी भी मदद की सराहना की जाएगी। अग्रिम धन्यवाद

उत्तर

5

उपयोग withUnsafeMutablePointer समारोह और UnsafeMutablePointer struct करने के लिए कीचेन पर लागू करने के लिए है नीचे की तरह बजाय डेटा पुन: प्राप्त,:

var result: AnyObject? 
var status = withUnsafeMutablePointer(&result) { SecItemCopyMatching(keychainQuery, UnsafeMutablePointer($0)) } 

if status == errSecSuccess { 
    if let data = result as NSData? { 
     if let string = NSString(data: data, encoding: NSUTF8StringEncoding) { 
      // ... 
     } 
    } 
} 

यह रिलीज (सबसे तेजी से अनुकूलन) निर्माण के साथ ठीक काम करता है।

+2

यह समस्या का एक वास्तविक समाधान है! कई मामलों में अस्वीकार्य में संकलक अनुकूलन को अक्षम करने का स्वीकार्य उत्तर। इसके लायक होने के लिए, मुझे केवल 64 बिट डिवाइस पर मूल बग दिखाई देता है। – alexkent

+1

यह दीवार के खिलाफ मेरे सिर को टक्कर देने के कई घंटों के बाद मेरे लिए काम किया। धन्यवाद। – Nick

+0

काम नहीं करता है, आईफोन 6, 6+ और आईपैड एयर 2 अभी भी 'withUnsafeMutablePointer' का उपयोग करते समय समस्या का प्रदर्शन कर रहा है। स्विफ्ट 1.2 स्थिर होने तक सभी डिवाइसों के लिए 'ऑनऑन' अभी भी एकमात्र व्यवहार्य विकल्प है –

2

ठीक है तो प्रावधान प्रोफ़ाइल और कीचेन कोड में सबकुछ ठीक था। समस्या स्विफ्ट कंपाइलर में एक सेटिंग थी! "सबसे तेज़" से "कोई नहीं" से "रिलीज़" के लिए अनुकूलन स्तर को बदलना समस्या को हल करना प्रतीत होता था।

enter image description here

+2

मेरे पास एक ही समस्या है। यह डेटा टाइप प्रकार की तरह दिखता है ?toOpaque() जब आप ऑप्टिमाइज़ेशन लेवल टू-ओ सेट करते हैं तो शून्य वापस आ रहा है। हालांकि, मुझे नहीं लगता कि ऑप्टिमाइज़ेशन स्तर को ऑन-ऑन करना एक समाधान नहीं है क्योंकि यह आपको तेज़ कोड को धीमा कर देगा। मैं Xcode 6.1 (6A1052d) – JorgeDeCorte

+0

का उपयोग करता हूं, मैंने एक ही समस्या में भाग लिया है और ऐप्पल को यह बग रिपोर्ट किया है (अगर यह सहायक है तो बग 1 9 003552)। इसमें चलने वाले किसी भी व्यक्ति को वही करना चाहिए जैसे डुप्लीकेट को मुद्दों को प्राथमिकता देने में मदद करनी चाहिए। – kolizz

+0

@JorgeDeCorte - धन्यवाद। शायद हमें डेटा टाइप करने की कोशिश करनी चाहिए और स्पष्ट रूप से डेटा टाइप करना चाहिए ... क्या आपने कोशिश की है?- मैं यह देखने जा रहा हूं कि शायद यह समस्या – Mark

0

तेज अनुकूलक के परिवर्तन काम कर रहा है, लेकिन नहीं एक अच्छा तरीका है समस्या का समाधान करने के लिए। टिप्पणियों में कहा गया है, यह अनुकूलन के साथ त्वरित कंपाइलर में एक बग प्रतीत होता है।

यह केवल आईओएस नहीं है, ओएसएक्स पर सटीक वही बात होती है (शायद प्रश्न में एक टैग जोड़ें)। ओएसएसटैटस 0 (सफलता) है लेकिन ऑप्टिमाइज़ेशन के तुरंत बाद रेफरेंसिंग पॉइंटर शून्य है।

सबसे अच्छा समाधान का उद्देश्य-सी में संचार या EMKeychain की तरह एक आवरण का उपयोग कर (OSX केवल, खेद पल में एक iOS आवरण पता नहीं है)

संबंधित मुद्दे