Xcodeからデバイスでアプリケーションを実行すると、キーチェーンにアクセスしようとしますが、エラー-34018が原因で失敗することがあります。これは、文書化されたキーチェーンエラーコードのいずれとも一致せず、一貫して再現することはできません。 (おそらく30%の確率で起こり、それがなぜ起こるのか私にはわかりません)。この問題のデバッグを非常に困難にしているのは、ドキュメントがまったくないことです。何がこれを引き起こし、それを修正する方法はありますか? Xcode 5を使用し、デバイスでiOS 7.0.4を実行しています。
これについては未解決の問題があります: https://github.com/soffes/sskeychain/issues/52
編集:リクエストごとにキーチェーンアクセスコードを追加する
キーチェーンとのインターフェイスにSSKeychain
ライブラリを使用しています。これがスニペットです。
#define SERVICE @"default"
@implementation SSKeychain (EXT)
+ (void)setValue:(NSString *)value forKey:(NSString *)key {
NSError *error = nil;
BOOL success = NO;
if (value) {
success = [self setPassword:value forService:SERVICE account:key error:&error];
} else {
success = [self deletePasswordForService:SERVICE account:key error:&error];
}
NSAssert(success, @"Unable to set keychain value %@ for key %@ error %@", value, key, error);
if (!success) {
LogError(@"Unable to set value to keychain %@", error);
}
LogTrace(@"Will set keychain account %@. is to nil? %d", key, value == nil);
if (value == nil)
LogWarn(@"Setting keychain %@ to nil!!!", key);
}
+ (NSString *)valueForKey:(NSString *)key {
NSError *error = nil;
NSString *value = [self passwordForService:SERVICE account:key error:&error];
if (error && error.code != errSecItemNotFound) {
NSAssert(!error, @"Unable to retrieve keychain value for key %@ error %@", key, error);
LogError(@"Unable to retrieve keychain value for key %@ error %@", key, error);
}
return value;
}
+ (BOOL)removeAllValues {
LogInfo(@"Completely Reseting Keychain");
return [[self accountsForService:SERVICE] all:^BOOL(NSDictionary *accountInfo) {
return [self deletePasswordForService:SERVICE account:accountInfo[@"acct"]];
}];
}
@end
ほとんどの場合、それで十分です。キーチェーンへの書き込みまたはキーチェーンからの読み取りができないアサーションエラーが発生し、重大なアサーションエラーが発生することがあります。
iOS 10/XCode 8修正:
KeyChainエンタイトルメントを追加し、プロジェクト設定->機能->キーチェーン共有->キーチェーングループの追加+オンに移動します
Appleからの回答:
更新:iOS 8.3で-34018エラーを再現できるようになりました。これは根本的な原因を特定し、修正するための最初のステップです。
いつものように、リリースの時間枠にコミットすることはできませんが、これは多くの開発者に影響を与えており、本当に解決したいと思っています。
先ほど、回避策としてキーチェーンにアクセスする前に、application:didFinishLaunchingWithOptionsおよびapplicationDidBecomeActive:にわずかな遅延を追加することを提案しました。しかし、それは実際には役に立たないようです。つまり、現時点では、アプリを再起動する以外の既知の回避策はありません。
この問題はメモリのプレッシャーに関連しているように見えるため、おそらくメモリ警告をより積極的に処理することで問題を軽減できる可能性があります。
https://forums.developer.Apple.com/thread/4743#14441
更新
OK、最新のものです。
これは、考えられる複数の原因を持つ複雑な問題です。
- 問題の一部の例は、不適切なアプリ署名が原因です。問題は100%再現可能であるため、このケースを簡単に区別できます。
- この問題のいくつかの例は、iOSがアプリ開発をサポートする方法のバグが原因です(r。23,991,853)。これをデバッグすることは、OSの別のバグ(r。23,770,418)がその影響を隠していたという事実により複雑でした。つまり、問題はデバイスがメモリ不足になったときにのみ発生しました。これらの問題はiOS 9.3で解決されたと考えています。
- この問題の原因はまだまだあると思われます。
そのため、iOS 9.3以降を実行しているユーザーデバイス(Xcodeで通信されていないデバイス)でこの問題が発生した場合は、バグレポートを提出してください。バグレポートにデバイスシステムログを含めるようにしてください(顧客のデバイスを扱う際に注意が必要な場合があることを理解しています。1つのオプションは、顧客にシステムログを表示できるApple Configuratorをインストールするよう求めることです) 。バグを報告する場合は、記録のためにバグ番号を投稿してください。
Appleを代表して、このやや恐ろしい問題の追跡に協力してくれたすべての人に感謝したいと思います。共有して楽しむ
基本的に、テストターゲットに以下を実行スクリプトとして追加して、.xcttestフォルダーをコード署名する必要があります。
codesign --verify --force --sign "$CODE_SIGN_IDENTITY" "$CODESIGNING_FOLDER_PATH"
デバイスでキーチェーンをテストすると、多くの-34018エラーが発生し、これを修正することができました。
問題がテストターゲットに存在しない場合、これはおそらく解決策ではありません。
ソースコード を調べた後。キーチェーン機能は、独自のプロセス(アプリプロセスとは別のプロセス)で実行されるセキュリティデーモンを介してアクセスされることに気付きました。
アプリとsecuritydプロセスは、 XPC と呼ばれるテクノロジーを通じて「通信」します。
必要に応じて、securitydは、XPCによる既知のlaunchdコマンドを介して起動されます。おそらく、デーモンがアクティビティモニターアプリで実行されていること(もちろんシミュレータで実行されている場合)、およびその親プロセスが起動されていることを確認できます。
ここでの私の推測では、何らかの理由でセキュリティデーモンの起動に失敗したり、実行が遅すぎたり、使用しようとしたときに準備ができていなかったりする可能性があります。
たぶん、デーモンを事前に起動する方法について考えることができます。
より正確ではないことをおaびします。調査をさらに進めるのに役立つことを願っています。
IOS 8 SDKを使用してXcode 6ベータでコードをビルドおよび実行した後、同様の動作を観察しています(Xcode 5/iOS 7で正常に動作しています)。 Xcode 6では、iOSシミュレーターではSecItemCopyMatchingは常に-34018を返します。 [機能]タブで[キーチェーンの共有]をオンにした後に機能し始めました。
ただし、別の問題があります。 (特に)デモアプリケーションで使用される静的ライブラリを開発しています。上記のソリューションはデモアプリケーションプロジェクトで機能しますが、静的ライブラリプロジェクトを単体テストしようとすると、まったく同じエラーが発生します。そして問題は、静的ライブラリプロジェクトに(スタンドアロンアプリケーションではないため)[機能]タブがないことです。
JorgeDeCorteがここに投稿したソリューションを試しましたが、テストターゲットでコード署名を行いましたが、うまくいきません。
Xcodeからアプリの起動時にすべてのブレークポイントを無効にするを試してください。後で有効にすることができます。
(上記の回避策のどれも私にとってはうまくいきませんでした)
7.1と8.0を実行しているシミュレーターで同じ問題が発生しました。掘り下げながら、Appleサンプルアプリのターゲット機能でKeyChain共有が有効になっていることに気付きました。私のアプリでそれをオンにした結果、デフォルト値で残されたエンタイトルメントファイルが作成され、現在では-34018エラーが発生しなくなりました。これは理想的ではありませんが、今のところはキーチェーン共有オプションを使用します。
私はこの問題を修正しました(と思います)。デバイスに有効な署名IDがないことを示すワイルドカードプロビジョニングプロファイルがありました。アプリのプロビジョニングプロファイルも有効でした。ワイルドカードプロファイルを削除すると、-334018エラーが表示されなくなりました。
また、ターゲットのビルド設定の[コード署名]セクションにリストされているコード署名IDとプロビジョニングプロファイルが、アプリのコード署名と同じであることを確認しました(汎用の "iPhone Developer"のものではありません)
.xctestバンドルの共同設計は、場合によっては思ったほど簡単ではありません。主にJorgeDeCorteは、彼の answer で、Run Script
として指定された短い行でほとんどの開発者に十分であると言っています。
codesign --verify --force --sign "$CODE_SIGN_IDENTITY" "$CODESIGNING_FOLDER_PATH"
ただし、キーチェーンに複数の証明書がある場合、次の行で失敗します
iPhone Developer: ambiguous (matches "iPhone Developer: Your Name (ABC123DEF45)" and "iPhone Developer: Your Name (123ABC456DE)"
複数の証明書がある場合でも正しい証明書を取得するためのソリューションは、この短いスクリプトです。確かにこれは理想的ではありませんが、私の知る限り、Xcodeが見つけて.appの署名に使用する証明書を取得する機会はありません。
echo "codesign --verify --force --sign \"$CODE_SIGN_IDENTITY\" \"$CODESIGNING_FOLDER_PATH\""
IDENTITIES=`security find-identity -v -s "Code Signing" | grep "iPhone Developer" | awk '{ print $2 }'`
for SHA in $IDENTITIES; do
codesign --verify --force --sign $SHA "$CODESIGNING_FOLDER_PATH"
if [ $? -eq 0 ]; then
echo "Matching identity found: $SHA"
exit 0
fi
done;
exit 1
-34018私のアプリ(iOS 8.4)でエラーが発生することはほとんどありませんでした。いくつかの調査の後、アプリがキーチェーンにデータを要求するときにこの問題が発生することがわかりましたtoo many。
たとえば、私の状況では、異なるアプリケーションモジュールからの1つの特定のキーに対する2つの読み取り要求が同時に発生しました。
この値をメモリにキャッシュすることを追加したことを修正するために
Xcode 8 Beta 3のこのバグに噛まれたばかりです。キーチェーン共有を有効にすることが唯一の解決策のようです。
同じ問題がありました。キーチェーン共有を設定することで修正しました。
(これはOPの質問に対する直接的な答えではありませんが、他の人を助けるかもしれません)
Xcodeをバージョン7.3.1から8.0に更新した後、シミュレーターで一貫してキーチェーンエラー-34018の取得を開始しました。
daidai's answer のこのヒントに従って、
問題の一部の例は、不適切なアプリ署名が原因です。問題は100%再現可能であるため、このケースを簡単に区別できます。
ターゲットの署名セクションでプロビジョニングプロファイルが何らかの形で[なし]に設定されていることが発見されました。
ただし、この場合、プロビジョニングプロファイルフィールドを有効な値に設定するだけでは問題を解決できませんでした。
さらに調査した結果、プッシュ通知の資格にもエラーが表示されていました。 「プッシュ通知機能をアプリIDに追加する」と書かれていました。手順は完了しましたが、手順「プッシュ通知の資格を資格ファイルに追加する」は完了していません。
「問題の修正」を押してプッシュ通知の問題を修正した後、キーチェーンエラーが解決されました。
この特定のターゲットについては、「キーチェーン共有」資格が以前にすでにオンになっていた。これをオフにしても、キーチェーンエラーはこれまでに発生していませんので、この場合に必要かどうかは明確ではありません。
Xcode 6.2、iPhone 6、iOS 8.3を搭載したテストデバイスで実行すると、同じ問題が突然発生しました。明確にするために、これはXcodeテストの実行中ではなく、実際のデバイスで実際のアプリを実行中に発生しました。シミュレーターでは問題ありませんでしたが、アプリ自体で実行することは最近までまったく問題ありませんでした。
デバイス上のプロビジョニングプロファイルを削除する(すべて削除した)、プロジェクトでキーチェーン共有機能を一時的に有効にする(実際には必要ありませんが)など、ここで見つけられるすべての提案を試しました。 Xcodeの私の開発アカウントがすべての証明書とプロビジョニングプロファイルなどで完全に更新されたことを確認してください。何も助けにはなりませんでした。
その後、一時的にアクセシビリティレベルをkSecAttrAccessibleAfterFirstUnlock
からkSecAttrAccessibleAlwaysThisDeviceOnly
に変更し、アプリを実行したところ、問題なく機能し、キーチェーンに書き込むことができました。それからkSecAttrAccessibleAfterFirstUnlock
に戻しましたが、問題は「永久に」消え去ったようです。
IOS 9でAddress Sanitizerをオフにすると、デバイスで機能し始めました。
今日、SecItemDelete APIを実行しているときにこの-34018の問題に遭遇しました。これを修正するために行ったのは:1. @ k1thソリューション https://stackoverflow.com/a/33085955/889892 に従ってください。メインスレッドから読み取るので、これを削除に合わせてください)。
申し訳ありませんがまた戻ってきます:(
私にとっては、アプリの署名の問題でした。 Xcodeで正しい署名チームに切り替えただけで、エラーは発生しなくなりました
私のために働いたもの
私のために働いた唯一の解決策は、最初にnilを指定されたキーに保存し、次に別の操作で新しい値を保存することでした。既存の値を上書きしようとすると、エラー-34018により失敗します。しかし、最初にnilを保存している限り、更新された値はその後すぐに正常に保存されます。