2014-11-01 24 views
11

Tôi hiểu rằng tôi có thể chia sẻ dữ liệu giữa tiện ích mở rộng chia sẻ của mình và ứng dụng có chứa ứng dụng bằng cách bật nhóm ứng dụng và sử dụng NSUserDefaults (xem Sharing data between an iOS 8 share extension and main app).Chia sẻ giữa tiện ích mở rộng iOS và ứng dụng chứa ứng dụng có móc khóa?

Tuy nhiên, dữ liệu tôi lưu trữ là nhạy cảm, vì vậy tôi hy vọng sẽ sử dụng móc khóa. Vì vậy, người dùng sẽ nhập thông tin tài khoản trong ứng dụng có chứa và sau đó tiện ích mở rộng chia sẻ sẽ đọc dữ liệu đó để thực hiện hành động chia sẻ dự định.

Có ai biết nếu điều này là có thể không? Nứt đầu tiên của tôi tại nó cho thấy rằng phần mở rộng và ứng dụng có chứa các móc khóa riêng biệt (lưu dữ liệu bằng một khóa trong ứng dụng chứa trả về null khi cố gắng trả về dữ liệu cho khóa đó trong phần mở rộng).

Cảm ơn!

P.S. Sử dụng Lockbox để truy cập Keychain, nhưng tôi có thể bỏ qua nó nếu nó quá trừu tượng để làm cho nó hoạt động. https://github.com/granoff/Lockbox

Trả lời

8

Điều này có thể được thực hiện. Nó là sự kết hợp của việc tạo một khung làm việc để truy cập Keychain và bật "Kích hoạt Chia sẻ Keychain" trong "Khả năng". Liên kết này đã cho tôi biết những gì tôi cần biết: http://swiftandpainless.com/ios8-share-extension-with-a-shared-keychain/

+4

Rất hữu ích khi không liên kết đến các trang web khác hoặc ít nhất thêm nguồn có liên quan vào câu trả lời, liên kết đó không còn khả dụng nữa. – leolobato

+0

Có khá nhiều thông tin ở đó, tôi không lên để chưng cất và dán, nhưng đây là phiên bản Lưu trữ Internet: https://web.archive.org/web/20141028160328/http://dasdev.de/2014/ 08/12/ios8-share-extension-với-một-chia sẻ-keychain –

+0

Các repo GitHub vẫn còn đó https://github.com/dasdom/KeychainDemo quá –

0

Sử dụng lớp Objective-C KeychainItemWrapper tiêu chuẩn và với một mục của #import "KeychainItemWrapper.h" trong tiêu đề bắc cầu:

func btnSaveAction() { 

    let appGroupID = "group.com.yourcompany.appid" 
    let keychain = KeychainItemWrapper(identifier: "Password", accessGroup:appGroupID) 
    keychain.setObject(self.txtfldPassword.text!, forKey:kSecValueData) 
    keychain.setObject(self.txtfldEmail.text!, forKey:kSecAttrAccount) 

    } 

Về phía gia hạn Watch (Swift):

override func awakeWithContext(context: AnyObject?) { 
    super.awakeWithContext(context) 

    let appGroupID = "group.com.yourcompany.appid" 
    let keychain = KeychainItemWrapper(identifier: "Password", accessGroup:appGroupID) 
    println(keychain.objectForKey(kSecAttrAccount)) 
    println(keychain.objectForKey(kSecValueData)) 

} 

Trong Objective C, gia hạn watchkit:

NSString *appGroupID = @"group.com.yourcompany.appid"; 
KeychainItemWrapper *keychain = [[KeychainItemWrapper alloc] initWithIdentifier:@"Password" accessGroup:appGroupID]; 
[keychain setObject:(__bridge id)(kSecAttrAccessibleWhenUnlocked) forKey:(__bridge id)(kSecAttrAccessible)]; 
NSLog(@"account = %@", [keychain objectForKey:(__bridge id)(kSecAttrAccount)]); 
NSLog(@"password =%@", [keychain objectForKey:(__bridge id)(kSecValueData)]); 

Đừng quên bật "Keychain Sharing" dưới "Khả năng" cho cả hai ứng dụng điện thoại và xem phần mở rộng bộ cho nhóm keychain giống nhau: "group.com.yourcompany.appid"

4

Để thực hiện Keychain chia sẻ trong Xcode 8.

1) trong mục tiêu ứng dụng của bạn trong khả năng tìm và bật "Keychain Sharing", thêm một phím Keychain Group (một chuỗi phong cách ngược miền như com.myappdomain.myappname)

2) Làm chính xác như vậy cho mục tiêu mở rộng. Đảm bảo khóa Keychain Group giống nhau cho cả ứng dụng và tiện ích mở rộng.

Thêm và truy xuất dữ liệu từ Keychain theo cách thông thường của bạn, không yêu cầu thay đổi đặc biệt trong mã. Ví dụ, đây là cách tôi đưa dữ liệu vào Keychain trong ứng dụng chính (một chút lỗi thời nhưng vẫn hoạt động trong Swift 3):

let login = loginString 
let domain = domainString 
let passwordData: Data = passwordString.data(using: String.Encoding.utf8, allowLossyConversion: false)! 
let keychainQuery: [NSString: NSObject] = [ 
    kSecClass: kSecClassGenericPassword, 
    kSecAttrAccount: login as NSObject, // login and domain strings help identify 
    kSecAttrService: domain as NSObject, // the required record in the Keychain 
    kSecValueData: passwordData as NSObject] 
SecItemDelete(keychainQuery as CFDictionary) //Deletes the item just in case it already exists 
let keychainSaveStatus: OSStatus = SecItemAdd(keychainQuery as CFDictionary, nil) 

Và sau đó lấy nó trong phần mở rộng:

let keychainQuery: [NSString: NSObject] = [ 
    kSecClass: kSecClassGenericPassword, 
    kSecAttrAccount: login as NSObject, 
    kSecAttrService: domain as NSObject, 
    kSecReturnData: kCFBooleanTrue, 
    kSecMatchLimit: kSecMatchLimitOne] 
var rawResult: AnyObject? 
let keychain_get_status: OSStatus = SecItemCopyMatching(keychainQueryForPass as CFDictionary, &rawResult) 

if (keychain_get_status == errSecSuccess) { 
    if let retrievedData = rawResult as? Data, 
     let password = String(data: retrievedData, encoding: String.Encoding.utf8) { 
     // "password" contains the password string now 
    } 
} 

Lưu ý rằng bạn sẽ vẫn cần phải chuyển "đăng nhập" và "tên miền" qua phần mở rộng để xác định hồ sơ chính xác. Điều này có thể được thực hiện thông qua NSUserDefaults. Xem this answer về cách thực hiện việc này.

Các vấn đề liên quan