2011年5月17日

iOS keychainWrapper trouble shooting

之前把一個project用官方提供的Keychain Services加上了自動記憶帳號密碼的功能
一直都正常運作,直到某一天一台裝置忽然跑出了不該出現的assert:
NSAssert(SecItemAdd((CFDictionaryRef)
[self dictionaryToSecItemFormat:keychainData],NULL) == noErr, @"Couldn't add the Keychain Item." );

當機,帳號密碼存不起來
想說嘗試著要把舊的刪掉加新的看看:
SecItemDelete((CFDictionaryRef)[self dictionaryToSecItemFormat:keychainData]));
結果錯誤訊息是-25300(errSecItemNotFound, The item cannot be found.)
然後試了:
SecItemAdd((CFDictionaryRef)[self dictionaryToSecItemFormat:keychainData],NULL));
得到-25299(errSecDuplicateItem, The item already exists.)
想說這下是見鬼了,查了一堆文件也沒找到解答,其他裝置好像也沒災情
解不掉就只好暫時丟著不管


今天de了一個和這相關的UI bug,就又查了一下資料,沒想到就找到了這個:
Keychain duplicate item when adding password
簡單來說不能靠 kSecAttrGeneric就可以當作identifier來辨認不同的keychain 
還要靠kSecAttrAccount和kSecAttrService才能使這個keychain唯一
附個說明這件事的官方文件
於是懸宕已久的謎團解開了:因為我還maintain了另一個project,用的也是官方code
有個keychain預設值:
[keychainData setObject:@"Service" forKey:(id)kSecAttrService];
然後我兩個project都有一個一樣的帳號,難怪只有我的裝置出事
現在分別給兩個project一個不同的serviceName,然後加了一行:
[genericPasswordQuery setObject:serviceName forKey:(id)kSecAttrService];
事情就解決啦!
下次遇到奇怪的bug看來還是要仔細讀一讀文件...
之前有人提到好像有更好用的keychain library,一下子找不到

沒有留言: