BitBucketにgitでアクセス、あるいは新しいサイトでssh認証するときの鍵の登録と確認の手順
https://qiita.com/yyosuke/items/986dabc9906674e2ea97 を参考にSSHの公開鍵をBitBucketに登録。
~/.ssh/config
に bitbucket.org
に当該の秘密鍵を使ってアクセスするように設定する。
# サイトごとに鍵を分けた方が良い。。。 Host bitbucket.org HostName bitbucket.org IdentityFile ~/.ssh/bitbucket/id_rsa User git Port 22 TCPKeepAlive yes IdentitiesOnly yes
$ ssh -T bitbucket.org The authenticity of host 'bitbucket.org (104.192.143.2)' can't be established. RSA key fingerprint is SHA256:UvlgyNccfRyg8jrD8dzU2lwwd4dDWYbx4NfILUjQkKL(この値はダミー). Are you sure you want to continue connecting (yes/no)? yes Warning: Permanently added 'bitbucket.org,104.192.143.2' (RSA) to the list of known hosts. logged in as UserName. You can use git or hg to connect to Bitbucket. Shell access is disabled.
あとはほぼGitHubと同じで、remote
リポジトリを指定するときのホストが bitbucket.org
になっているだけ。
`NS_SWIFT_NAME` マクロでObjective-CのコードがSwiftからどう見えるか規定できる
Objective-Cで書いたメソッドのシグネチャはSwiftから呼び出す時にメソッド名の一部の単語がパラメータ名の一部へ変換されるものがある。
// Objective-C - (void)addToBox:(Item *)item;
// Swift 2.3 addToBox(item) // Swift 3.0 add(toBox: item)
この変換具合がSwift2系と3系で結構違う上に前置詞などを使った動詞の塊が切り取られて引数のラベルみたいに扱われてしまう。
すると、主に一番最初の引数の意味が違って見えることがある。たとえば、 上記の例の Swfit 3.0 のシグネチャでは toBox
というラベルがついてしまっているが、第一引数はItemのインスタンスであってBoxのインスタンスではないが、そういう風に見える。
なので、Objective-C + 複数のSwiftのバージョンに対応する必要がある場合はドキュメントなどのサンプルコードをどう書くか悩ましかったりする。
こういう場合、 NS_SWIFT_NAME
を使って Swift
ではこういうシグネチャで表示してほしい、という個別設定が可能。
- (void)addToBox:(Item *)item; NS_SWIFT_NAME(addToBox(item:));
参考
Swift3でCountdownLatchを作る、あるいはSemaphoreのtimeoutをSwift3で書く
テストの都合でラッチが欲しかったので、GCDのSemaphoreのラッパークラスを書こうと思ったんですね。
それで、 https://github.com/zhuhaow/CountdownLatch を参考にすれば割と簡単では! と思ったんですが、GCDの記法がSwift3で変わりすぎていて死ぬかと思った。のでメモ。
// 参考元: https://github.com/zhuhaow/CountdownLatch import Foundation class CountDownLatch { var count: Int private let dispatchQueue = DispatchQueue(label: "CountdownQueue") // 参考: https://qiita.com/codelynx/items/56ce2f91cd3f4f409aeb let semaphore = DispatchSemaphore(value: 0) let timeInSec : Int init?(count: Int, timeInSec: Int) { guard count > 0 else { return nil } self.count = count self.timeInSec = timeInSec } func countdown() { dispatchQueue.async { self.count -= 1 if self.count == 0 { self.semaphore.signal() } } } func await() -> Bool { // 参考: http://www.brilliantraven.com/code-snippets/grand-central-dispatch.html let result = semaphore.wait(timeout: DispatchTime.now() + DispatchTimeInterval.seconds(self.timeInSec)) if (result == .success) { return true } else { return false } } }
CouuntDownLatch
を使う側のコードは以下
func doTask() { let countDownLatch = CountDownLatch(count: 1, timeInSec: 30)! checkTimeoutBeforeCompletion(latch: countDownLatch) // なんか重い処理する countDownLatch.countdown() } func checkTimeoutBeforeCompletion(latch: CountDownLatch) { let queue = DispatchQueue(label: "background", attributes: .concurrent) queue.async { let processedOnTime = latch.await() if (processedOnTime) { NSLog("processed on time") } else { assertionFailure("遅いぞ!!!!") } } }
計数型セマフォについて
http://woshidan.hatenadiary.jp/entry/2017/08/27/005353 で使い方の勉強をした気がするんですが意味がよくわかってなかったので。
計数型セマフォは「チケットを配ってチケットをもらえたスレッドは処理を先へ進めることができる」みたいなもの。 ここから下はチケットを配ってもらえたスレッドにしか実行させない、みたいな箇所で
semaphore.await();
dispatch_semaphore_wait(semaphore, time);
のように、wait
っぽい関数を置く。 (少なくともObjCの場合は) wait
関数から抜ける時にセマフォのカウンタ(比喩でいうとチケットの枚数)がデクリメントする。
初期化時にセマフォが何枚のチケットを持っているか指定して、チケットを配られたスレッドたちが実行する処理の中でチケットを返したり(Semaphoreのカウンタをインクリメントする)する。
ObjCの場合、Semaphoreのカウンタをインクリメントする処理は以下。
dispatch_semaphore_signal(semaphore)
なので、全体の処理としてはこんな感じになる。
// セマフォの用意 dispatch_semaphore_t semaphore = dispatch_semaphore_create(1); // セマフォのところで待つ時間 dispatch_time_t time = dispatch_time(DISPATCH_TIME_NOW, 1ull * NSEC_PER_SEC); // ここからセマフォで用意したチケットの枚数ぶん以上のスレッドは実行してくれるなよ long result = dispatch_semaphore_wait(semaphore, time); // 上の行を通り過ぎるとセマフォのカウンタは1減っている if (result == 0) { // セマフォのカウンタが1以上だった or 待機時間中にセマフォのカウンタが1以上になったので // 処理が進められる // 排他制御したかった処理 // この処理の最後あたりでセマフォのカウンタを戻しておきましょう dispatch_semaphore_signal(semaphore) } else { // 指定時間待機したけどセマフォのカウンタが0のままだった }
現場からは以上です。
エキスパートObjective-Cプログラミング ?iOS/OS Xのメモリ管理とマルチスレッド?
- 作者: 坂本一樹
- 出版社/メーカー: インプレス
- 発売日: 2011/11/18
- メディア: 単行本(ソフトカバー)
- 購入: 8人 クリック: 343回
- この商品を含むブログ (25件) を見る
iOSのUIをコードで追加して配置する
5回ググって書く気が失せたのでBlogged.
// https://qiita.com/i_terasaka/items/2cf7d0f7146f32c3f2c1#%E5%8F%96%E5%BE%97%E6%96%B9%E6%B3%95 let button = UIButton(type: UIButtonType.system) button.frame = CGRect(x: 180, y: 50, width: 100, height: 40) button.setTitle("button", for: UIControlState.normal) button.accessibilityIdentifier = "button" // XCUITest用 button.addTarget(self, action: #selector(ViewController.someAction), for: UIControlEvents.touchUpInside) self.view.addSubview(button) // https://qiita.com/on0z/items/9768d2bccc29cc4e1851 var wkWebView : WKWebView! wkWebView = WKWebView(frame: CGRect(x: 100, y: 100, width: self.view.frame.size.width / 2, height: self.view.frame.size.height / 2)) self.view.addSubview(wkWebView) // 初期化メソッドに差はない var uiwebview : UIWebView! uiwebview = UIWebView(frame: CGRect(x: 100, y: 120 + self.view.frame.size.height / 4 , width: self.view.frame.size.width / 2, height: self.view.frame.size.height / 4)) self.view.addSubview(uiwebview)
参考
合わせて読みたい
iOSでBundleファイルを扱う
.bundle
拡張子のついたフォルダーを用意- その下にファイルを置く
.bundle
拡張子のついたファイルをXCode上で追加したいプロジェクトに追加- 下記のように
NSString
やNSData
,UIImage
などの関数でデータを読み込む
NSString* filePath = [NSString stringWithFormat:@"%@/%@", [[NSBundle mainBundle] pathForResource:@"test" ofType:@"bundle"], FILE_NAME]; NSString* content = [NSString stringWithContentsOfFile:filename encoding:NSUTF8StringEncoding error:nil]; NSLog(@"content: %@", content); NSData *contentData = [NSData dataWithContentsOfFile:filePath options:NSDataReadingMappedIfSafe error:nil]; [UIImage imageNamed:filePath];