iOS開発で頻繁にお世話になる .p12 ファイル(秘密鍵+証明書のセット)の情報を確認する方法です。
SHA1フィンガープリント、有効期限、チームID,名前などがコマンドラインから簡単に確認できます。
証明書と秘密鍵からp12ファイルを作る
証明書と鍵ファイルからp12ファイル(pkcs12)を作る手順のメモ。
証明書(cer)をPEMに変換する、鍵(PEM private key)と結合してp12にする、という2段構え。
参考: http://spiratesta.hatenablog.com/entry/20120215/1329280918
1.公開用証明書をPEM証明書形式に変換する
$ openssl x509 -in distribution_identity.cer -inform DER -out distribution_identity.pem -outform PEM
2.PEM証明書形式をP12証明書形式に変換する
$ openssl pkcs12 -export -inkey mykey.key -in distribution_identity.pem -out distribution_identity.p12
パスワードを聞かれるので、適宜入力する(パスワード空欄だとキーチェーン取り込みできない)
3.P12証明書を開いてキーチェーンに取り込む(取り込み時に上記パスワードを入力する)
なぜ必要だったか
MacBook Pro が壊れたので修理して、クリーンインストールし直したんですが、
そのときにとあるプロジェクトのApp Storeのリリース用(Distribution)秘密鍵の移行を忘れて喪失してしまったため、
なんとかサルベージできないか、と試行錯誤するのに使いました。
Circle CIにp12の鍵が上がっていたので、CIを回してSSHで入り、
鍵ファイル(/var/folders/jm/ほげほげ/T/cert.abcdef)をcatして取り出し .key として保存、
Apple Developerサイトの Certificates,IDs & Profiles から証明書ダウンロード、
あとは手順通りの結合で事なきを得ました。バックアップは大事ですね。。
こんな記事もあります
Swift2でリリースビルドの時にログ表示しないようにする
Xcode7(Swift2) でデバッグビルドの時だけデバッグ出力して、プロダクションビルドの時はセキュリティのためデバッグログを削る方法のメモ。
このコードにより、print, debugPrintln, NSLogの出力を制御することができます。
事前準備
XcodeプロジェクトのBuild Settings → Swift Compiler → Other Swift Flags の Debug に「-DDEBUG」を追加して下さい。
コード
AppDelegate.swift の冒頭に以下のグローバル関数を追加します。
他のファイルのほうがわかりやすければAppDelegate以外でも大丈夫です。
// リリースビルドでprint, debugPrintを無効化
func print(object: Any) {
#if DEBUG
Swift.print(object, terminator: "")
#endif
}
func debugPrint(object: Any) {
#if DEBUG
Swift.debugPrint(object, terminator: "")
#endif
}
// リリースビルドでNSLog無効化
func NSLog(message:String){
#if DEBUG
Foundation.NSLog(message)
#endif
}
func NSLog(format:String, _ args:CVarArgType...){
#if DEBUG
Foundation.NSLog(String(format: format, arguments: args))
#endif
}
この記事を書いた理由
print, debugPrintは出てきますが、SwiftでNSLogを非表示にする方法がどうしても出てこなかったので記事にしました。
Swift2から廃止されたprintln, debugPrintlnはここに書いていませんが、print, debugPrint と同様の方法で対応可能です。
ググると NSLogを消す方法として、プレフィクスヘッダファイル(.pchファイル)に #define NSLog を方法が出てきますが、こちらはObjective Cにしか効果がないようなので注意。
おまけ
代替案としては、より細かいログレベル制御が可能なXCGLoggerを使うのも手です。
AppDelegateで
import XCGLogger
let log: XCGLogger = {
let log = XCGLogger.defaultInstance()
#if DEBUG
log.setup(.Debug, showThreadName: true, showLogLevel: true, showFileNames: true, showLineNumbers: true, writeToFile: nil)
#else
log.setup(.Severe, showThreadName: true, showLogLevel: true, showFileNames: true, showLineNumbers: true, writeToFile: nil)
#endif
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "MM/dd/yyyy hh:mma"
dateFormatter.locale = NSLocale.currentLocale()
log.dateFormatter = dateFormatter
return log
}()
としておくと、
log.debug("Debugレベルのログです")
log.info("infoレベルのログです")
のようにログレベルごとのログ出力ができるようになります。
[Android] [Gradle] Android Studioで “Configuration with name default not found” エラーが出た時の対処法
Android Studio や IntelliJ IDEA でプロジェクトを開こうとした時に、
“Configuration with name default not found” というエラーが出ることがあります。
resolve error Configuration with name default not found Consult IDE log for more details(help show log)
どうすればいいか
困ったときのGoogle先生頼みでぐぐるのもいいんですが、これだけでは原因が色々ありすぎてなかなか正解にたどり着けないので、ダイアログで書かれている通り help
メニューから show log
を開いて、フォルダ内の idea.log を開いてみると解決の助けになります。
Mac OS X や Linux は ~/Library/Logs/AndroidStudio/idea.log あたりを直接開いてもOKです。
ログファイルなのでめちゃくちゃ長くて読みづらいのですが、該当のエラーを知りたいだけなので
エラーメッセージ通りConfiguration with name ‘default’ not found.
で検索してみると、何件かのうち以下のような行が引っかかると思います。
(省略)
Caused by: org.gradle.api.UnknownProjectException: Cannot evaluate module volley : Configuration with name 'd
efault' not found.
at com.android.build.gradle.BasePlugin$_ensureConfigured_closure189.doCall(BasePlugin.groovy:3345)
at com.android.build.gradle.BasePlugin.ensureConfigured(BasePlugin.groovy:3339)
at com.android.build.gradle.BasePlugin.resolveDependencyForConfig(BasePlugin.groovy:3255)
at com.android.build.gradle.BasePlugin.this$2$resolveDependencyForConfig(BasePlugin.groovy)
at com.android.build.gradle.BasePlugin$this$2$resolveDependencyForConfig$1.callCurrent(Unknown Source)
at com.android.build.gradle.BasePlugin.resolveDependencies(BasePlugin.groovy:3174)
at com.android.build.gradle.internal.VariantManager.createVariantData(VariantManager.java:464)
at com.android.build.gradle.internal.VariantManager.createVariantDataForProductFlavors(VariantManager.java:550)
at com.android.build.gradle.internal.VariantManager.populateVariantDataList(VariantManager.java:326)
at com.android.build.gradle.internal.VariantManager.createAndroidTasks(VariantManager.java:212)
at com.android.build.gradle.internal.VariantManager$createAndroidTasks.call(Unknown Source)
at com.android.build.gradle.BasePlugin.createAndroidTasks(BasePlugin.groovy:463)
at com.android.build.gradle.BasePlugin$_createTasks_closure9.doCall(BasePlugin.groovy:408)
at org.gradle.listener.ClosureBackedMethodInvocationDispatch.dispatch(ClosureBackedMethodInvocationDispatch.java:40)
at org.gradle.listener.ClosureBackedMethodInvocationDispatch.dispatch(ClosureBackedMethodInvocationDispatch.java:25)
at org.gradle.listener.BroadcastDispatch.dispatch(BroadcastDispatch.java:83)
at org.gradle.listener.BroadcastDispatch.dispatch(BroadcastDispatch.java:31)
at org.gradle.messaging.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:93)
at com.sun.proxy.$Proxy13.afterEvaluate(Unknown Source)
at org.gradle.configuration.project.LifecycleProjectEvaluator.notifyAfterEvaluate(LifecycleProjectEvaluator.java:79)
... 39 more
Caused by: org.gradle.api.artifacts.UnknownConfigurationException: Configuration with name 'default' not found.
at org.gradle.api.internal.artifacts.configurations.DefaultConfigurationContainer.createNotFoundException(DefaultConfigurationContainer.java:79)
at org.gradle.api.internal.DefaultNamedDomainObjectCollection.getByName(DefaultNamedDomainObjectCollection.java:192)
at org.gradle.api.internal.artifacts.configurations.DefaultConfigurationContainer.getByName(DefaultConfigurationContainer.java:69)
at org.gradle.api.internal.artifacts.configurations.DefaultConfigurationContainer.getByName(DefaultConfigurationContainer.java:33)
at org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependency.getProjectConfiguration(DefaultProjectDependency.java:69)
at org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependency_Decorated.getProjectConfiguration(Unknown Source)
at org.gradle.api.internal.BeanDynamicObject$MetaClassAdapter.getProperty(BeanDynamicObject.java:153)
at org.gradle.api.internal.BeanDynamicObject.getProperty(BeanDynamicObject.java:107)
at org.gradle.api.internal.CompositeDynamicObject.getProperty(CompositeDynamicObject.java:78)
at org.gradle.api.internal.artifacts.dependencies.DefaultProjectDependency_Decorated.getProperty(Unknown Source)
(以下略)
上記の1行目のCannot evaluate module volley : Configuration with name ‘default’ not found.
がポイントです。
エラーダイアログに無かったCannot evaluate module volley
があることで、犯人がvolley(のgradle)だと判りましたね。
この例では、volleyがサブモジュールでインストールされてなかったためそもそもbuild.gradleがなくて怒られていたので、最終的にgit submodule add でvolleyを追加してやることで無事解決しました。
忙しい人のための解決方法
ここまで書いてきたidea.logから探す方法ですが、ログはめちゃくちゃ見づらいので、
直接 gradlew なりgradle なりをコマンドラインから実行したほうがわかりやすいです。
./gradlew tasks --info
上記のコマンドをbuild.gradle (とgradlrew)のあるディレクトリで実行すると、
Android Studioから開いた時と同じところでこけて最後にCannot evaluate module volley : Configuration with name ‘default’ not found.
のような原因が表示されます。
idea.logなんて見なくてもよかった(gradleに関しては)。
ひとこと
Android Studio で既存プロジェクトを github から git cloneして開こうとした時にはまったので。
[iOS][Swift] Swiftっぽくレコードをソートをする
NSSortDescriptorはObjective-Cでも使えるレコードの配列をレコードキーでソートするのに便利な方法ですが、Arrayのsort()メソッドやsorted()メソッドを使うとよりSwiftっぽくクロージャでソートすることができます。
変更前:
let records = NSMutableArray() let sortDescriptor = NSSortDescriptor(key: "fileSize", ascending: true) records.sortedArrayUsingDescriptors([sortDescriptor]) // レコード投入 let record1 = NSMutableDictionary() record1["filePath"] = "/path/to/file1" record1["fileSize"] = 1000 records.addObject(record1) let record2 = NSMutableDictionary() record2["filePath"] = "/path/to/file2" record2["fileSize"] = 100 records.addObject(record2) let record3 = NSMutableDictionary() record3["filePath"] = "/path/to/file3" record3["fileSize"] = 500 records.addObject(record3) println(records)
【Linux】topで表示される flush 253:0 の意味
Linux(CentOS)で重い処理の実行中にtopを見ていて、「flush 253:0」というプロセスがあるのが気になって調べてみた。
StackOverflowの「”flush 253:0″ in iotop file on RHEL. 」によると、カーネルがページキャッシュからIO書き込みを行うためのプロセスなのだそう。
ざっくり言うと、ディスク書き込みをする際、ユーザプログラムではページキャッシュに一旦書き込んでいて、
それをLinuxカーネルが処理している時に出てくるプロセス、らしい。
たしかに、ディスク書き込みを行う処理を監視していたのでした。
MySQLでmysql.slow_logテーブルをslow queryログファイル形式でダンプする
表題のとおり、スロークエリログをテーブルに書き出しているMySQL DBサーバで
slow queryログファイルの形式でエクスポートしたくなったのでその方法をメモしておきます。
参考:Exporting mysqlslowlog table slow query log format.
# コマンドここから
mysql -u “ユーザ名” -p -h “接続先ホスト” -D mysql -s -r -e “SELECT CONCAT( ‘# Time: ‘, DATE_FORMAT(start_time, ‘%y%m%d %H%i%s’), ‘\n’, ‘# User@Host: ‘, user_host, ‘\n’, ‘# Query_time: ‘, TIME_TO_SEC(query_time), ‘ Lock_time: ‘, TIME_TO_SEC(lock_time), ‘ Rows_sent: ‘, rows_sent, ‘ Rows_examined: ‘, rows_examined, ‘\n’, sql_text, ‘;’ ) FROM mysql.slow_log” > /tmp/mysql.slow_log.log
# コマンドここまで
長くて読みづらいですが、mysqlコマンドで、slow_query_logファイル形式にあわせるようにSELECTを打って整形しています。
普段はSQLで処理できるテーブルのほうが便利ですが、Percona Toolkitのpt-query-digestのように、スロークエリログをファイルとして処理するようなツールを使うためにファイルが欲しくなることもあるのですよね。
Percona Toolkitについてはこちらの記事が参考になりました。
[iOS][Objective-C] @property の基本まとめ
Objective-C でなんとなく知っているけど実はよく知らないプロパティ(@property)まわりの
基本的な仕様をまとめました。
Xcode6.1が正式リリースされてSwiftのβがとれたし、「Swift使うからいらないよ」なんて言わないで、iOS開発のお供にどうぞ。
[iOS] UIButtonのテキスト設定時のアニメーションを止める
iOS7以降(iOS7.1, iOS8も)、UIButtonにsetTitleすると勝手にボタンがアニメーションをしてしまうようです。
たとえばコードからデフォルト値設定したいだけなのに[UIButton setTitle:]したら、チラッとUIビルダーの設定値が出ちゃってなんだかあれだったので、止める方法をメモしておきます。
plist と json を相互変換する
iOSやMac OS Xで使用されるplist形式(プロパティリスト)と、
Androidやwebシステムで使いやすいJSONに相互変換したい場合のメモ。
続きを読む plist と json を相互変換する